14baa9922SRussell King /* 24baa9922SRussell King * arch/arm/include/asm/assembler.h 34baa9922SRussell King * 44baa9922SRussell King * Copyright (C) 1996-2000 Russell King 54baa9922SRussell King * 64baa9922SRussell King * This program is free software; you can redistribute it and/or modify 74baa9922SRussell King * it under the terms of the GNU General Public License version 2 as 84baa9922SRussell King * published by the Free Software Foundation. 94baa9922SRussell King * 104baa9922SRussell King * This file contains arm architecture specific defines 114baa9922SRussell King * for the different processors. 124baa9922SRussell King * 134baa9922SRussell King * Do not include any C declarations in this file - it is included by 144baa9922SRussell King * assembler source. 154baa9922SRussell King */ 164baa9922SRussell King #ifndef __ASSEMBLY__ 174baa9922SRussell King #error "Only include this from assembly code" 184baa9922SRussell King #endif 194baa9922SRussell King 204baa9922SRussell King #include <asm/ptrace.h> 214baa9922SRussell King 224baa9922SRussell King /* 234baa9922SRussell King * Endian independent macros for shifting bytes within registers. 244baa9922SRussell King */ 254baa9922SRussell King #ifndef __ARMEB__ 264baa9922SRussell King #define pull lsr 274baa9922SRussell King #define push lsl 284baa9922SRussell King #define get_byte_0 lsl #0 294baa9922SRussell King #define get_byte_1 lsr #8 304baa9922SRussell King #define get_byte_2 lsr #16 314baa9922SRussell King #define get_byte_3 lsr #24 324baa9922SRussell King #define put_byte_0 lsl #0 334baa9922SRussell King #define put_byte_1 lsl #8 344baa9922SRussell King #define put_byte_2 lsl #16 354baa9922SRussell King #define put_byte_3 lsl #24 364baa9922SRussell King #else 374baa9922SRussell King #define pull lsl 384baa9922SRussell King #define push lsr 394baa9922SRussell King #define get_byte_0 lsr #24 404baa9922SRussell King #define get_byte_1 lsr #16 414baa9922SRussell King #define get_byte_2 lsr #8 424baa9922SRussell King #define get_byte_3 lsl #0 434baa9922SRussell King #define put_byte_0 lsl #24 444baa9922SRussell King #define put_byte_1 lsl #16 454baa9922SRussell King #define put_byte_2 lsl #8 464baa9922SRussell King #define put_byte_3 lsl #0 474baa9922SRussell King #endif 484baa9922SRussell King 494baa9922SRussell King /* 504baa9922SRussell King * Data preload for architectures that support it 514baa9922SRussell King */ 524baa9922SRussell King #if __LINUX_ARM_ARCH__ >= 5 534baa9922SRussell King #define PLD(code...) code 544baa9922SRussell King #else 554baa9922SRussell King #define PLD(code...) 564baa9922SRussell King #endif 574baa9922SRussell King 584baa9922SRussell King /* 594baa9922SRussell King * This can be used to enable code to cacheline align the destination 604baa9922SRussell King * pointer when bulk writing to memory. Experiments on StrongARM and 614baa9922SRussell King * XScale didn't show this a worthwhile thing to do when the cache is not 624baa9922SRussell King * set to write-allocate (this would need further testing on XScale when WA 634baa9922SRussell King * is used). 644baa9922SRussell King * 654baa9922SRussell King * On Feroceon there is much to gain however, regardless of cache mode. 664baa9922SRussell King */ 674baa9922SRussell King #ifdef CONFIG_CPU_FEROCEON 684baa9922SRussell King #define CALGN(code...) code 694baa9922SRussell King #else 704baa9922SRussell King #define CALGN(code...) 714baa9922SRussell King #endif 724baa9922SRussell King 734baa9922SRussell King /* 744baa9922SRussell King * Enable and disable interrupts 754baa9922SRussell King */ 764baa9922SRussell King #if __LINUX_ARM_ARCH__ >= 6 774baa9922SRussell King .macro disable_irq 784baa9922SRussell King cpsid i 794baa9922SRussell King .endm 804baa9922SRussell King 814baa9922SRussell King .macro enable_irq 824baa9922SRussell King cpsie i 834baa9922SRussell King .endm 844baa9922SRussell King #else 854baa9922SRussell King .macro disable_irq 864baa9922SRussell King msr cpsr_c, #PSR_I_BIT | SVC_MODE 874baa9922SRussell King .endm 884baa9922SRussell King 894baa9922SRussell King .macro enable_irq 904baa9922SRussell King msr cpsr_c, #SVC_MODE 914baa9922SRussell King .endm 924baa9922SRussell King #endif 934baa9922SRussell King 944baa9922SRussell King /* 954baa9922SRussell King * Save the current IRQ state and disable IRQs. Note that this macro 964baa9922SRussell King * assumes FIQs are enabled, and that the processor is in SVC mode. 974baa9922SRussell King */ 984baa9922SRussell King .macro save_and_disable_irqs, oldcpsr 994baa9922SRussell King mrs \oldcpsr, cpsr 1004baa9922SRussell King disable_irq 1014baa9922SRussell King .endm 1024baa9922SRussell King 1034baa9922SRussell King /* 1044baa9922SRussell King * Restore interrupt state previously stored in a register. We don't 1054baa9922SRussell King * guarantee that this will preserve the flags. 1064baa9922SRussell King */ 1074baa9922SRussell King .macro restore_irqs, oldcpsr 1084baa9922SRussell King msr cpsr_c, \oldcpsr 1094baa9922SRussell King .endm 1104baa9922SRussell King 1114baa9922SRussell King #define USER(x...) \ 1124baa9922SRussell King 9999: x; \ 1134baa9922SRussell King .section __ex_table,"a"; \ 1144baa9922SRussell King .align 3; \ 1154baa9922SRussell King .long 9999b,9001f; \ 1164baa9922SRussell King .previous 117bac4e960SRussell King 118bac4e960SRussell King /* 119bac4e960SRussell King * SMP data memory barrier 120bac4e960SRussell King */ 121bac4e960SRussell King .macro smp_dmb 122bac4e960SRussell King #ifdef CONFIG_SMP 123bac4e960SRussell King #if __LINUX_ARM_ARCH__ >= 7 124bac4e960SRussell King dmb 125bac4e960SRussell King #elif __LINUX_ARM_ARCH__ == 6 126bac4e960SRussell King mcr p15, 0, r0, c7, c10, 5 @ dmb 127bac4e960SRussell King #endif 128bac4e960SRussell King #endif 129bac4e960SRussell King .endm 130b86040a5SCatalin Marinas 131b86040a5SCatalin Marinas #ifdef CONFIG_THUMB2_KERNEL 132b86040a5SCatalin Marinas .macro setmode, mode, reg 133b86040a5SCatalin Marinas mov \reg, #\mode 134b86040a5SCatalin Marinas msr cpsr_c, \reg 135b86040a5SCatalin Marinas .endm 136b86040a5SCatalin Marinas #else 137b86040a5SCatalin Marinas .macro setmode, mode, reg 138b86040a5SCatalin Marinas msr cpsr_c, #\mode 139b86040a5SCatalin Marinas .endm 140b86040a5SCatalin Marinas #endif 1418b592783SCatalin Marinas 1428b592783SCatalin Marinas /* 1438b592783SCatalin Marinas * STRT/LDRT access macros with ARM and Thumb-2 variants 1448b592783SCatalin Marinas */ 1458b592783SCatalin Marinas #ifdef CONFIG_THUMB2_KERNEL 1468b592783SCatalin Marinas 1478b592783SCatalin Marinas .macro usraccoff, instr, reg, ptr, inc, off, cond, abort 1488b592783SCatalin Marinas 9999: 1498b592783SCatalin Marinas .if \inc == 1 1508b592783SCatalin Marinas \instr\cond\()bt \reg, [\ptr, #\off] 1518b592783SCatalin Marinas .elseif \inc == 4 1528b592783SCatalin Marinas \instr\cond\()t \reg, [\ptr, #\off] 1538b592783SCatalin Marinas .else 1548b592783SCatalin Marinas .error "Unsupported inc macro argument" 1558b592783SCatalin Marinas .endif 1568b592783SCatalin Marinas 1578b592783SCatalin Marinas .section __ex_table,"a" 1588b592783SCatalin Marinas .align 3 1598b592783SCatalin Marinas .long 9999b, \abort 1608b592783SCatalin Marinas .previous 1618b592783SCatalin Marinas .endm 1628b592783SCatalin Marinas 1638b592783SCatalin Marinas .macro usracc, instr, reg, ptr, inc, cond, rept, abort 1648b592783SCatalin Marinas @ explicit IT instruction needed because of the label 1658b592783SCatalin Marinas @ introduced by the USER macro 1668b592783SCatalin Marinas .ifnc \cond,al 1678b592783SCatalin Marinas .if \rept == 1 1688b592783SCatalin Marinas itt \cond 1698b592783SCatalin Marinas .elseif \rept == 2 1708b592783SCatalin Marinas ittt \cond 1718b592783SCatalin Marinas .else 1728b592783SCatalin Marinas .error "Unsupported rept macro argument" 1738b592783SCatalin Marinas .endif 1748b592783SCatalin Marinas .endif 1758b592783SCatalin Marinas 1768b592783SCatalin Marinas @ Slightly optimised to avoid incrementing the pointer twice 1778b592783SCatalin Marinas usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort 1788b592783SCatalin Marinas .if \rept == 2 1798b592783SCatalin Marinas usraccoff \instr, \reg, \ptr, \inc, 4, \cond, \abort 1808b592783SCatalin Marinas .endif 1818b592783SCatalin Marinas 1828b592783SCatalin Marinas add\cond \ptr, #\rept * \inc 1838b592783SCatalin Marinas .endm 1848b592783SCatalin Marinas 1858b592783SCatalin Marinas #else /* !CONFIG_THUMB2_KERNEL */ 1868b592783SCatalin Marinas 1878b592783SCatalin Marinas .macro usracc, instr, reg, ptr, inc, cond, rept, abort 1888b592783SCatalin Marinas .rept \rept 1898b592783SCatalin Marinas 9999: 1908b592783SCatalin Marinas .if \inc == 1 1918b592783SCatalin Marinas \instr\cond\()bt \reg, [\ptr], #\inc 1928b592783SCatalin Marinas .elseif \inc == 4 1938b592783SCatalin Marinas \instr\cond\()t \reg, [\ptr], #\inc 1948b592783SCatalin Marinas .else 1958b592783SCatalin Marinas .error "Unsupported inc macro argument" 1968b592783SCatalin Marinas .endif 1978b592783SCatalin Marinas 1988b592783SCatalin Marinas .section __ex_table,"a" 1998b592783SCatalin Marinas .align 3 2008b592783SCatalin Marinas .long 9999b, \abort 2018b592783SCatalin Marinas .previous 2028b592783SCatalin Marinas .endr 2038b592783SCatalin Marinas .endm 2048b592783SCatalin Marinas 2058b592783SCatalin Marinas #endif /* CONFIG_THUMB2_KERNEL */ 2068b592783SCatalin Marinas 2078b592783SCatalin Marinas .macro strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f 2088b592783SCatalin Marinas usracc str, \reg, \ptr, \inc, \cond, \rept, \abort 2098b592783SCatalin Marinas .endm 2108b592783SCatalin Marinas 2118b592783SCatalin Marinas .macro ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f 2128b592783SCatalin Marinas usracc ldr, \reg, \ptr, \inc, \cond, \rept, \abort 2138b592783SCatalin Marinas .endm 214