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> 21247055aaSCatalin Marinas #include <asm/domain.h> 224baa9922SRussell King 234baa9922SRussell King /* 244baa9922SRussell King * Endian independent macros for shifting bytes within registers. 254baa9922SRussell King */ 264baa9922SRussell King #ifndef __ARMEB__ 274baa9922SRussell King #define pull lsr 284baa9922SRussell King #define push lsl 294baa9922SRussell King #define get_byte_0 lsl #0 304baa9922SRussell King #define get_byte_1 lsr #8 314baa9922SRussell King #define get_byte_2 lsr #16 324baa9922SRussell King #define get_byte_3 lsr #24 334baa9922SRussell King #define put_byte_0 lsl #0 344baa9922SRussell King #define put_byte_1 lsl #8 354baa9922SRussell King #define put_byte_2 lsl #16 364baa9922SRussell King #define put_byte_3 lsl #24 374baa9922SRussell King #else 384baa9922SRussell King #define pull lsl 394baa9922SRussell King #define push lsr 404baa9922SRussell King #define get_byte_0 lsr #24 414baa9922SRussell King #define get_byte_1 lsr #16 424baa9922SRussell King #define get_byte_2 lsr #8 434baa9922SRussell King #define get_byte_3 lsl #0 444baa9922SRussell King #define put_byte_0 lsl #24 454baa9922SRussell King #define put_byte_1 lsl #16 464baa9922SRussell King #define put_byte_2 lsl #8 474baa9922SRussell King #define put_byte_3 lsl #0 484baa9922SRussell King #endif 494baa9922SRussell King 504baa9922SRussell King /* 514baa9922SRussell King * Data preload for architectures that support it 524baa9922SRussell King */ 534baa9922SRussell King #if __LINUX_ARM_ARCH__ >= 5 544baa9922SRussell King #define PLD(code...) code 554baa9922SRussell King #else 564baa9922SRussell King #define PLD(code...) 574baa9922SRussell King #endif 584baa9922SRussell King 594baa9922SRussell King /* 604baa9922SRussell King * This can be used to enable code to cacheline align the destination 614baa9922SRussell King * pointer when bulk writing to memory. Experiments on StrongARM and 624baa9922SRussell King * XScale didn't show this a worthwhile thing to do when the cache is not 634baa9922SRussell King * set to write-allocate (this would need further testing on XScale when WA 644baa9922SRussell King * is used). 654baa9922SRussell King * 664baa9922SRussell King * On Feroceon there is much to gain however, regardless of cache mode. 674baa9922SRussell King */ 684baa9922SRussell King #ifdef CONFIG_CPU_FEROCEON 694baa9922SRussell King #define CALGN(code...) code 704baa9922SRussell King #else 714baa9922SRussell King #define CALGN(code...) 724baa9922SRussell King #endif 734baa9922SRussell King 744baa9922SRussell King /* 754baa9922SRussell King * Enable and disable interrupts 764baa9922SRussell King */ 774baa9922SRussell King #if __LINUX_ARM_ARCH__ >= 6 780d928b0bSUwe Kleine-König .macro disable_irq_notrace 794baa9922SRussell King cpsid i 804baa9922SRussell King .endm 814baa9922SRussell King 820d928b0bSUwe Kleine-König .macro enable_irq_notrace 834baa9922SRussell King cpsie i 844baa9922SRussell King .endm 854baa9922SRussell King #else 860d928b0bSUwe Kleine-König .macro disable_irq_notrace 874baa9922SRussell King msr cpsr_c, #PSR_I_BIT | SVC_MODE 884baa9922SRussell King .endm 894baa9922SRussell King 900d928b0bSUwe Kleine-König .macro enable_irq_notrace 914baa9922SRussell King msr cpsr_c, #SVC_MODE 924baa9922SRussell King .endm 934baa9922SRussell King #endif 944baa9922SRussell King 950d928b0bSUwe Kleine-König .macro asm_trace_hardirqs_off 960d928b0bSUwe Kleine-König #if defined(CONFIG_TRACE_IRQFLAGS) 970d928b0bSUwe Kleine-König stmdb sp!, {r0-r3, ip, lr} 980d928b0bSUwe Kleine-König bl trace_hardirqs_off 990d928b0bSUwe Kleine-König ldmia sp!, {r0-r3, ip, lr} 1000d928b0bSUwe Kleine-König #endif 1010d928b0bSUwe Kleine-König .endm 1020d928b0bSUwe Kleine-König 1030d928b0bSUwe Kleine-König .macro asm_trace_hardirqs_on_cond, cond 1040d928b0bSUwe Kleine-König #if defined(CONFIG_TRACE_IRQFLAGS) 1050d928b0bSUwe Kleine-König /* 1060d928b0bSUwe Kleine-König * actually the registers should be pushed and pop'd conditionally, but 1070d928b0bSUwe Kleine-König * after bl the flags are certainly clobbered 1080d928b0bSUwe Kleine-König */ 1090d928b0bSUwe Kleine-König stmdb sp!, {r0-r3, ip, lr} 1100d928b0bSUwe Kleine-König bl\cond trace_hardirqs_on 1110d928b0bSUwe Kleine-König ldmia sp!, {r0-r3, ip, lr} 1120d928b0bSUwe Kleine-König #endif 1130d928b0bSUwe Kleine-König .endm 1140d928b0bSUwe Kleine-König 1150d928b0bSUwe Kleine-König .macro asm_trace_hardirqs_on 1160d928b0bSUwe Kleine-König asm_trace_hardirqs_on_cond al 1170d928b0bSUwe Kleine-König .endm 1180d928b0bSUwe Kleine-König 1190d928b0bSUwe Kleine-König .macro disable_irq 1200d928b0bSUwe Kleine-König disable_irq_notrace 1210d928b0bSUwe Kleine-König asm_trace_hardirqs_off 1220d928b0bSUwe Kleine-König .endm 1230d928b0bSUwe Kleine-König 1240d928b0bSUwe Kleine-König .macro enable_irq 1250d928b0bSUwe Kleine-König asm_trace_hardirqs_on 1260d928b0bSUwe Kleine-König enable_irq_notrace 1270d928b0bSUwe Kleine-König .endm 1284baa9922SRussell King /* 1294baa9922SRussell King * Save the current IRQ state and disable IRQs. Note that this macro 1304baa9922SRussell King * assumes FIQs are enabled, and that the processor is in SVC mode. 1314baa9922SRussell King */ 1324baa9922SRussell King .macro save_and_disable_irqs, oldcpsr 1334baa9922SRussell King mrs \oldcpsr, cpsr 1344baa9922SRussell King disable_irq 1354baa9922SRussell King .endm 1364baa9922SRussell King 1374baa9922SRussell King /* 1384baa9922SRussell King * Restore interrupt state previously stored in a register. We don't 1394baa9922SRussell King * guarantee that this will preserve the flags. 1404baa9922SRussell King */ 1410d928b0bSUwe Kleine-König .macro restore_irqs_notrace, oldcpsr 1424baa9922SRussell King msr cpsr_c, \oldcpsr 1434baa9922SRussell King .endm 1444baa9922SRussell King 1450d928b0bSUwe Kleine-König .macro restore_irqs, oldcpsr 1460d928b0bSUwe Kleine-König tst \oldcpsr, #PSR_I_BIT 1470d928b0bSUwe Kleine-König asm_trace_hardirqs_on_cond eq 1480d928b0bSUwe Kleine-König restore_irqs_notrace \oldcpsr 1490d928b0bSUwe Kleine-König .endm 1500d928b0bSUwe Kleine-König 1514baa9922SRussell King #define USER(x...) \ 1524baa9922SRussell King 9999: x; \ 1534260415fSRussell King .pushsection __ex_table,"a"; \ 1544baa9922SRussell King .align 3; \ 1554baa9922SRussell King .long 9999b,9001f; \ 1564260415fSRussell King .popsection 157bac4e960SRussell King 158f00ec48fSRussell King #ifdef CONFIG_SMP 159f00ec48fSRussell King #define ALT_SMP(instr...) \ 160f00ec48fSRussell King 9998: instr 161f00ec48fSRussell King #define ALT_UP(instr...) \ 162f00ec48fSRussell King .pushsection ".alt.smp.init", "a" ;\ 163f00ec48fSRussell King .long 9998b ;\ 164f00ec48fSRussell King instr ;\ 165f00ec48fSRussell King .popsection 166f00ec48fSRussell King #define ALT_UP_B(label) \ 167f00ec48fSRussell King .equ up_b_offset, label - 9998b ;\ 168f00ec48fSRussell King .pushsection ".alt.smp.init", "a" ;\ 169f00ec48fSRussell King .long 9998b ;\ 170f00ec48fSRussell King b . + up_b_offset ;\ 171f00ec48fSRussell King .popsection 172f00ec48fSRussell King #else 173f00ec48fSRussell King #define ALT_SMP(instr...) 174f00ec48fSRussell King #define ALT_UP(instr...) instr 175f00ec48fSRussell King #define ALT_UP_B(label) b label 176f00ec48fSRussell King #endif 177f00ec48fSRussell King 178bac4e960SRussell King /* 179bac4e960SRussell King * SMP data memory barrier 180bac4e960SRussell King */ 181bac4e960SRussell King .macro smp_dmb 182bac4e960SRussell King #ifdef CONFIG_SMP 183bac4e960SRussell King #if __LINUX_ARM_ARCH__ >= 7 184f00ec48fSRussell King ALT_SMP(dmb) 185bac4e960SRussell King #elif __LINUX_ARM_ARCH__ == 6 186f00ec48fSRussell King ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb 187f00ec48fSRussell King #else 188f00ec48fSRussell King #error Incompatible SMP platform 189bac4e960SRussell King #endif 190f00ec48fSRussell King ALT_UP(nop) 191bac4e960SRussell King #endif 192bac4e960SRussell King .endm 193b86040a5SCatalin Marinas 194b86040a5SCatalin Marinas #ifdef CONFIG_THUMB2_KERNEL 195b86040a5SCatalin Marinas .macro setmode, mode, reg 196b86040a5SCatalin Marinas mov \reg, #\mode 197b86040a5SCatalin Marinas msr cpsr_c, \reg 198b86040a5SCatalin Marinas .endm 199b86040a5SCatalin Marinas #else 200b86040a5SCatalin Marinas .macro setmode, mode, reg 201b86040a5SCatalin Marinas msr cpsr_c, #\mode 202b86040a5SCatalin Marinas .endm 203b86040a5SCatalin Marinas #endif 2048b592783SCatalin Marinas 2058b592783SCatalin Marinas /* 2068b592783SCatalin Marinas * STRT/LDRT access macros with ARM and Thumb-2 variants 2078b592783SCatalin Marinas */ 2088b592783SCatalin Marinas #ifdef CONFIG_THUMB2_KERNEL 2098b592783SCatalin Marinas 210247055aaSCatalin Marinas .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T() 2118b592783SCatalin Marinas 9999: 2128b592783SCatalin Marinas .if \inc == 1 213247055aaSCatalin Marinas \instr\cond\()b\()\t\().w \reg, [\ptr, #\off] 2148b592783SCatalin Marinas .elseif \inc == 4 215247055aaSCatalin Marinas \instr\cond\()\t\().w \reg, [\ptr, #\off] 2168b592783SCatalin Marinas .else 2178b592783SCatalin Marinas .error "Unsupported inc macro argument" 2188b592783SCatalin Marinas .endif 2198b592783SCatalin Marinas 2204260415fSRussell King .pushsection __ex_table,"a" 2218b592783SCatalin Marinas .align 3 2228b592783SCatalin Marinas .long 9999b, \abort 2234260415fSRussell King .popsection 2248b592783SCatalin Marinas .endm 2258b592783SCatalin Marinas 2268b592783SCatalin Marinas .macro usracc, instr, reg, ptr, inc, cond, rept, abort 2278b592783SCatalin Marinas @ explicit IT instruction needed because of the label 2288b592783SCatalin Marinas @ introduced by the USER macro 2298b592783SCatalin Marinas .ifnc \cond,al 2308b592783SCatalin Marinas .if \rept == 1 2318b592783SCatalin Marinas itt \cond 2328b592783SCatalin Marinas .elseif \rept == 2 2338b592783SCatalin Marinas ittt \cond 2348b592783SCatalin Marinas .else 2358b592783SCatalin Marinas .error "Unsupported rept macro argument" 2368b592783SCatalin Marinas .endif 2378b592783SCatalin Marinas .endif 2388b592783SCatalin Marinas 2398b592783SCatalin Marinas @ Slightly optimised to avoid incrementing the pointer twice 2408b592783SCatalin Marinas usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort 2418b592783SCatalin Marinas .if \rept == 2 2428b592783SCatalin Marinas usraccoff \instr, \reg, \ptr, \inc, 4, \cond, \abort 2438b592783SCatalin Marinas .endif 2448b592783SCatalin Marinas 2458b592783SCatalin Marinas add\cond \ptr, #\rept * \inc 2468b592783SCatalin Marinas .endm 2478b592783SCatalin Marinas 2488b592783SCatalin Marinas #else /* !CONFIG_THUMB2_KERNEL */ 2498b592783SCatalin Marinas 250247055aaSCatalin Marinas .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=T() 2518b592783SCatalin Marinas .rept \rept 2528b592783SCatalin Marinas 9999: 2538b592783SCatalin Marinas .if \inc == 1 254247055aaSCatalin Marinas \instr\cond\()b\()\t \reg, [\ptr], #\inc 2558b592783SCatalin Marinas .elseif \inc == 4 256247055aaSCatalin Marinas \instr\cond\()\t \reg, [\ptr], #\inc 2578b592783SCatalin Marinas .else 2588b592783SCatalin Marinas .error "Unsupported inc macro argument" 2598b592783SCatalin Marinas .endif 2608b592783SCatalin Marinas 2614260415fSRussell King .pushsection __ex_table,"a" 2628b592783SCatalin Marinas .align 3 2638b592783SCatalin Marinas .long 9999b, \abort 2644260415fSRussell King .popsection 2658b592783SCatalin Marinas .endr 2668b592783SCatalin Marinas .endm 2678b592783SCatalin Marinas 2688b592783SCatalin Marinas #endif /* CONFIG_THUMB2_KERNEL */ 2698b592783SCatalin Marinas 2708b592783SCatalin Marinas .macro strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f 2718b592783SCatalin Marinas usracc str, \reg, \ptr, \inc, \cond, \rept, \abort 2728b592783SCatalin Marinas .endm 2738b592783SCatalin Marinas 2748b592783SCatalin Marinas .macro ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f 2758b592783SCatalin Marinas usracc ldr, \reg, \ptr, \inc, \cond, \rept, \abort 2768b592783SCatalin Marinas .endm 277