1/* 2 * Copyright 2013, winocm. <winocm@icloud.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * Redistributions in binary form must reproduce the above copyright notice, this 12 * list of conditions and the following disclaimer in the documentation and/or 13 * other materials provided with the distribution. 14 * 15 * If you are going to use this software in any form that does not involve 16 * releasing the source to this project or improving it, let me know beforehand. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29/* 30 * Shouldn't we use mach/arm/asm.h instead? Just wondering. 31 */ 32/* 33 * ASM helper functions 34 */ 35 36#ifndef _ARM_ASM_HELP_H_ 37#define _ARM_ASM_HELP_H_ 38 39#include <arm/arch.h> 40 41/* 42 * LLVM-AS is a horrible sin upon humanity. 43 */ 44#define LoadConstantToReg(_Data, _Reg) \ 45 ldr _Reg, [pc, #0] ; \ 46 b 1f ; \ 47 .long (_Data) ; \ 481: 49 50/* 51 * Procedure enter and exit for both ARM and thumb states. 52 */ 53#define EnterARM(function) \ 54 .code 32 ; \ 55 .globl _ ##function ; \ 56 .align 4 ; \ 57 _##function: ; \ 58 59#define EnterThumb(function) ; \ 60 .code 16 ; \ 61 .thumb_func _ ##function ; \ 62 .globl _ ##function ; \ 63 .align 4 ; \ 64 _##function: ; \ 65 66#define EnterARM_NoAlign(function) \ 67 .code 32 ; \ 68 .globl _ ##function ; \ 69 _##function: ; \ 70 71#define EnterThumb_NoAlign(function) \ 72 .code 16 ; \ 73 .thumb_func _ ##function ; \ 74 .globl _ ##function ; \ 75 _##function: ; \ 76 77/* AArch64 stuff */ 78#ifdef _ARM_ARCH_8 79#undef EnterARM 80#undef EnterThumb 81#undef EnterARM_NoAlign 82#undef EnterThumb_NoAlign 83 84#define EnterAArch64(function) \ 85 .align 6 ; \ 86 .globl _ ##function ; \ 87 _##function: ; 88 89#define EnterAArch64_NoAlign(function) \ 90 .align 6 ; \ 91 .globl _ ##function ; \ 92 _##function: ; 93 94#define EnterARM_NoAlign EnterAArch64_NoAlign 95#define EnterThumb_NoAlign EnterAArch64_NoAlign 96#define EnterARM EnterAArch64 97#define EnterThumb EnterAArch64 98#endif 99 100/* 101 * ARM atomic function helper macro. 102 */ 103#define AtomicMachine(name, instr) \ 104 EnterARM(hw_atomic_ ##name) \ 105 mov r12, r0 ; \ 106 try_ ##name: ; \ 107 ldrex r0, [r12] ; \ 108 instr r0, r0, r1 ; \ 109 strex r3, r0, [r12] ; \ 110 movs r3, r3 ; \ 111 bxeq lr ; \ 112 b try_ ##name ; 113 114/* These are used for platforms that do not support LDREX/STREX properly. */ 115#define AtomicPrologue \ 116 mrs r3, cpsr ; \ 117 orr r2, r3, #0xC0 ; \ 118 msr cpsr_cf, r2 119 120#define AtomicEpilogue \ 121 msr cpsr_cf, r3 122 123#define AtomicMachineNoExclusive(name, instr) \ 124 EnterARM(hw_atomic_ ##name) \ 125 AtomicPrologue ; \ 126 mov r12, r0 ; \ 127 try_ ##name: ; \ 128 ldr r0, [r12] ; \ 129 instr r0, r0, r1 ; \ 130 str r0, [r12] ; \ 131 AtomicEpilogue ; \ 132 bx lr ; \ 133 134/* 135 * Helper macro to get physical address mapping in virtual address space. 136 */ 137#define GetPhysAddr(rX) \ 138 LoadConstantToReg(_gPhysBase, r4); \ 139 ldr r4, [r4]; \ 140 sub rX, rX, r4; \ 141 LoadConstantToReg(_gVirtBase, r4); \ 142 ldr r4, [r4]; \ 143 add rX, rX, r4 144 145/* 146 * Thread crap. 147 */ 148 149#define _1KB 1024 150#define _1MB 1024 * _1KB 151 152#define LoadLockHardwareRegister(register) \ 153 mrc p15, 0, register, c13, c0, 4 154 155#define LoadThreadRegister(register) \ 156 mrc p15, 0, register, c13, c0, 4 157 158#define IncrementPreemptLevel(register, scratch) \ 159 ldr scratch, [register, MACHINE_THREAD_PREEMPT_COUNT] ; \ 160 adds scratch, scratch, #1 ; \ 161 str scratch, [register, MACHINE_THREAD_PREEMPT_COUNT] ; 162 163#define DecrementPreemptLevel(register, scratch) \ 164 ldr scratch, [register, MACHINE_THREAD_PREEMPT_COUNT] ; \ 165 subs scratch, scratch, #1 ; \ 166 str scratch, [register, MACHINE_THREAD_PREEMPT_COUNT] ; 167 168#endif 169