162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/arm/include/asm/assembler.h 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1996-2000 Russell King 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This file contains arm architecture specific defines 862306a36Sopenharmony_ci * for the different processors. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Do not include any C declarations in this file - it is included by 1162306a36Sopenharmony_ci * assembler source. 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci#ifndef __ASM_ASSEMBLER_H__ 1462306a36Sopenharmony_ci#define __ASM_ASSEMBLER_H__ 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 1762306a36Sopenharmony_ci#error "Only include this from assembly code" 1862306a36Sopenharmony_ci#endif 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <asm/ptrace.h> 2162306a36Sopenharmony_ci#include <asm/opcodes-virt.h> 2262306a36Sopenharmony_ci#include <asm/asm-offsets.h> 2362306a36Sopenharmony_ci#include <asm/page.h> 2462306a36Sopenharmony_ci#include <asm/thread_info.h> 2562306a36Sopenharmony_ci#include <asm/uaccess-asm.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define IOMEM(x) (x) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* 3062306a36Sopenharmony_ci * Endian independent macros for shifting bytes within registers. 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_ci#ifndef __ARMEB__ 3362306a36Sopenharmony_ci#define lspull lsr 3462306a36Sopenharmony_ci#define lspush lsl 3562306a36Sopenharmony_ci#define get_byte_0 lsl #0 3662306a36Sopenharmony_ci#define get_byte_1 lsr #8 3762306a36Sopenharmony_ci#define get_byte_2 lsr #16 3862306a36Sopenharmony_ci#define get_byte_3 lsr #24 3962306a36Sopenharmony_ci#define put_byte_0 lsl #0 4062306a36Sopenharmony_ci#define put_byte_1 lsl #8 4162306a36Sopenharmony_ci#define put_byte_2 lsl #16 4262306a36Sopenharmony_ci#define put_byte_3 lsl #24 4362306a36Sopenharmony_ci#else 4462306a36Sopenharmony_ci#define lspull lsl 4562306a36Sopenharmony_ci#define lspush lsr 4662306a36Sopenharmony_ci#define get_byte_0 lsr #24 4762306a36Sopenharmony_ci#define get_byte_1 lsr #16 4862306a36Sopenharmony_ci#define get_byte_2 lsr #8 4962306a36Sopenharmony_ci#define get_byte_3 lsl #0 5062306a36Sopenharmony_ci#define put_byte_0 lsl #24 5162306a36Sopenharmony_ci#define put_byte_1 lsl #16 5262306a36Sopenharmony_ci#define put_byte_2 lsl #8 5362306a36Sopenharmony_ci#define put_byte_3 lsl #0 5462306a36Sopenharmony_ci#endif 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* Select code for any configuration running in BE8 mode */ 5762306a36Sopenharmony_ci#ifdef CONFIG_CPU_ENDIAN_BE8 5862306a36Sopenharmony_ci#define ARM_BE8(code...) code 5962306a36Sopenharmony_ci#else 6062306a36Sopenharmony_ci#define ARM_BE8(code...) 6162306a36Sopenharmony_ci#endif 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* 6462306a36Sopenharmony_ci * Data preload for architectures that support it 6562306a36Sopenharmony_ci */ 6662306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 5 6762306a36Sopenharmony_ci#define PLD(code...) code 6862306a36Sopenharmony_ci#else 6962306a36Sopenharmony_ci#define PLD(code...) 7062306a36Sopenharmony_ci#endif 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* 7362306a36Sopenharmony_ci * This can be used to enable code to cacheline align the destination 7462306a36Sopenharmony_ci * pointer when bulk writing to memory. Experiments on StrongARM and 7562306a36Sopenharmony_ci * XScale didn't show this a worthwhile thing to do when the cache is not 7662306a36Sopenharmony_ci * set to write-allocate (this would need further testing on XScale when WA 7762306a36Sopenharmony_ci * is used). 7862306a36Sopenharmony_ci * 7962306a36Sopenharmony_ci * On Feroceon there is much to gain however, regardless of cache mode. 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_ci#ifdef CONFIG_CPU_FEROCEON 8262306a36Sopenharmony_ci#define CALGN(code...) code 8362306a36Sopenharmony_ci#else 8462306a36Sopenharmony_ci#define CALGN(code...) 8562306a36Sopenharmony_ci#endif 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci#define IMM12_MASK 0xfff 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/* the frame pointer used for stack unwinding */ 9062306a36Sopenharmony_ciARM( fpreg .req r11 ) 9162306a36Sopenharmony_ciTHUMB( fpreg .req r7 ) 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* 9462306a36Sopenharmony_ci * Enable and disable interrupts 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6 9762306a36Sopenharmony_ci .macro disable_irq_notrace 9862306a36Sopenharmony_ci cpsid i 9962306a36Sopenharmony_ci .endm 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci .macro enable_irq_notrace 10262306a36Sopenharmony_ci cpsie i 10362306a36Sopenharmony_ci .endm 10462306a36Sopenharmony_ci#else 10562306a36Sopenharmony_ci .macro disable_irq_notrace 10662306a36Sopenharmony_ci msr cpsr_c, #PSR_I_BIT | SVC_MODE 10762306a36Sopenharmony_ci .endm 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci .macro enable_irq_notrace 11062306a36Sopenharmony_ci msr cpsr_c, #SVC_MODE 11162306a36Sopenharmony_ci .endm 11262306a36Sopenharmony_ci#endif 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 7 11562306a36Sopenharmony_ci .macro dsb, args 11662306a36Sopenharmony_ci mcr p15, 0, r0, c7, c10, 4 11762306a36Sopenharmony_ci .endm 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci .macro isb, args 12062306a36Sopenharmony_ci mcr p15, 0, r0, c7, c5, 4 12162306a36Sopenharmony_ci .endm 12262306a36Sopenharmony_ci#endif 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci .macro asm_trace_hardirqs_off, save=1 12562306a36Sopenharmony_ci#if defined(CONFIG_TRACE_IRQFLAGS) 12662306a36Sopenharmony_ci .if \save 12762306a36Sopenharmony_ci stmdb sp!, {r0-r3, ip, lr} 12862306a36Sopenharmony_ci .endif 12962306a36Sopenharmony_ci bl trace_hardirqs_off 13062306a36Sopenharmony_ci .if \save 13162306a36Sopenharmony_ci ldmia sp!, {r0-r3, ip, lr} 13262306a36Sopenharmony_ci .endif 13362306a36Sopenharmony_ci#endif 13462306a36Sopenharmony_ci .endm 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci .macro asm_trace_hardirqs_on, cond=al, save=1 13762306a36Sopenharmony_ci#if defined(CONFIG_TRACE_IRQFLAGS) 13862306a36Sopenharmony_ci /* 13962306a36Sopenharmony_ci * actually the registers should be pushed and pop'd conditionally, but 14062306a36Sopenharmony_ci * after bl the flags are certainly clobbered 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_ci .if \save 14362306a36Sopenharmony_ci stmdb sp!, {r0-r3, ip, lr} 14462306a36Sopenharmony_ci .endif 14562306a36Sopenharmony_ci bl\cond trace_hardirqs_on 14662306a36Sopenharmony_ci .if \save 14762306a36Sopenharmony_ci ldmia sp!, {r0-r3, ip, lr} 14862306a36Sopenharmony_ci .endif 14962306a36Sopenharmony_ci#endif 15062306a36Sopenharmony_ci .endm 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci .macro disable_irq, save=1 15362306a36Sopenharmony_ci disable_irq_notrace 15462306a36Sopenharmony_ci asm_trace_hardirqs_off \save 15562306a36Sopenharmony_ci .endm 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci .macro enable_irq 15862306a36Sopenharmony_ci asm_trace_hardirqs_on 15962306a36Sopenharmony_ci enable_irq_notrace 16062306a36Sopenharmony_ci .endm 16162306a36Sopenharmony_ci/* 16262306a36Sopenharmony_ci * Save the current IRQ state and disable IRQs. Note that this macro 16362306a36Sopenharmony_ci * assumes FIQs are enabled, and that the processor is in SVC mode. 16462306a36Sopenharmony_ci */ 16562306a36Sopenharmony_ci .macro save_and_disable_irqs, oldcpsr 16662306a36Sopenharmony_ci#ifdef CONFIG_CPU_V7M 16762306a36Sopenharmony_ci mrs \oldcpsr, primask 16862306a36Sopenharmony_ci#else 16962306a36Sopenharmony_ci mrs \oldcpsr, cpsr 17062306a36Sopenharmony_ci#endif 17162306a36Sopenharmony_ci disable_irq 17262306a36Sopenharmony_ci .endm 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci .macro save_and_disable_irqs_notrace, oldcpsr 17562306a36Sopenharmony_ci#ifdef CONFIG_CPU_V7M 17662306a36Sopenharmony_ci mrs \oldcpsr, primask 17762306a36Sopenharmony_ci#else 17862306a36Sopenharmony_ci mrs \oldcpsr, cpsr 17962306a36Sopenharmony_ci#endif 18062306a36Sopenharmony_ci disable_irq_notrace 18162306a36Sopenharmony_ci .endm 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci/* 18462306a36Sopenharmony_ci * Restore interrupt state previously stored in a register. We don't 18562306a36Sopenharmony_ci * guarantee that this will preserve the flags. 18662306a36Sopenharmony_ci */ 18762306a36Sopenharmony_ci .macro restore_irqs_notrace, oldcpsr 18862306a36Sopenharmony_ci#ifdef CONFIG_CPU_V7M 18962306a36Sopenharmony_ci msr primask, \oldcpsr 19062306a36Sopenharmony_ci#else 19162306a36Sopenharmony_ci msr cpsr_c, \oldcpsr 19262306a36Sopenharmony_ci#endif 19362306a36Sopenharmony_ci .endm 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci .macro restore_irqs, oldcpsr 19662306a36Sopenharmony_ci tst \oldcpsr, #PSR_I_BIT 19762306a36Sopenharmony_ci asm_trace_hardirqs_on cond=eq 19862306a36Sopenharmony_ci restore_irqs_notrace \oldcpsr 19962306a36Sopenharmony_ci .endm 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/* 20262306a36Sopenharmony_ci * Assembly version of "adr rd, BSYM(sym)". This should only be used to 20362306a36Sopenharmony_ci * reference local symbols in the same assembly file which are to be 20462306a36Sopenharmony_ci * resolved by the assembler. Other usage is undefined. 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_ci .irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo 20762306a36Sopenharmony_ci .macro badr\c, rd, sym 20862306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL 20962306a36Sopenharmony_ci adr\c \rd, \sym + 1 21062306a36Sopenharmony_ci#else 21162306a36Sopenharmony_ci adr\c \rd, \sym 21262306a36Sopenharmony_ci#endif 21362306a36Sopenharmony_ci .endm 21462306a36Sopenharmony_ci .endr 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci/* 21762306a36Sopenharmony_ci * Get current thread_info. 21862306a36Sopenharmony_ci */ 21962306a36Sopenharmony_ci .macro get_thread_info, rd 22062306a36Sopenharmony_ci /* thread_info is the first member of struct task_struct */ 22162306a36Sopenharmony_ci get_current \rd 22262306a36Sopenharmony_ci .endm 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci/* 22562306a36Sopenharmony_ci * Increment/decrement the preempt count. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ci#ifdef CONFIG_PREEMPT_COUNT 22862306a36Sopenharmony_ci .macro inc_preempt_count, ti, tmp 22962306a36Sopenharmony_ci ldr \tmp, [\ti, #TI_PREEMPT] @ get preempt count 23062306a36Sopenharmony_ci add \tmp, \tmp, #1 @ increment it 23162306a36Sopenharmony_ci str \tmp, [\ti, #TI_PREEMPT] 23262306a36Sopenharmony_ci .endm 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci .macro dec_preempt_count, ti, tmp 23562306a36Sopenharmony_ci ldr \tmp, [\ti, #TI_PREEMPT] @ get preempt count 23662306a36Sopenharmony_ci sub \tmp, \tmp, #1 @ decrement it 23762306a36Sopenharmony_ci str \tmp, [\ti, #TI_PREEMPT] 23862306a36Sopenharmony_ci .endm 23962306a36Sopenharmony_ci#else 24062306a36Sopenharmony_ci .macro inc_preempt_count, ti, tmp 24162306a36Sopenharmony_ci .endm 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci .macro dec_preempt_count, ti, tmp 24462306a36Sopenharmony_ci .endm 24562306a36Sopenharmony_ci#endif 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci#define USERL(l, x...) \ 24862306a36Sopenharmony_ci9999: x; \ 24962306a36Sopenharmony_ci .pushsection __ex_table,"a"; \ 25062306a36Sopenharmony_ci .align 3; \ 25162306a36Sopenharmony_ci .long 9999b,l; \ 25262306a36Sopenharmony_ci .popsection 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci#define USER(x...) USERL(9001f, x) 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci#ifdef CONFIG_SMP 25762306a36Sopenharmony_ci#define ALT_SMP(instr...) \ 25862306a36Sopenharmony_ci9998: instr 25962306a36Sopenharmony_ci/* 26062306a36Sopenharmony_ci * Note: if you get assembler errors from ALT_UP() when building with 26162306a36Sopenharmony_ci * CONFIG_THUMB2_KERNEL, you almost certainly need to use 26262306a36Sopenharmony_ci * ALT_SMP( W(instr) ... ) 26362306a36Sopenharmony_ci */ 26462306a36Sopenharmony_ci#define ALT_UP(instr...) \ 26562306a36Sopenharmony_ci .pushsection ".alt.smp.init", "a" ;\ 26662306a36Sopenharmony_ci .align 2 ;\ 26762306a36Sopenharmony_ci .long 9998b - . ;\ 26862306a36Sopenharmony_ci9997: instr ;\ 26962306a36Sopenharmony_ci .if . - 9997b == 2 ;\ 27062306a36Sopenharmony_ci nop ;\ 27162306a36Sopenharmony_ci .endif ;\ 27262306a36Sopenharmony_ci .if . - 9997b != 4 ;\ 27362306a36Sopenharmony_ci .error "ALT_UP() content must assemble to exactly 4 bytes";\ 27462306a36Sopenharmony_ci .endif ;\ 27562306a36Sopenharmony_ci .popsection 27662306a36Sopenharmony_ci#define ALT_UP_B(label) \ 27762306a36Sopenharmony_ci .pushsection ".alt.smp.init", "a" ;\ 27862306a36Sopenharmony_ci .align 2 ;\ 27962306a36Sopenharmony_ci .long 9998b - . ;\ 28062306a36Sopenharmony_ci W(b) . + (label - 9998b) ;\ 28162306a36Sopenharmony_ci .popsection 28262306a36Sopenharmony_ci#else 28362306a36Sopenharmony_ci#define ALT_SMP(instr...) 28462306a36Sopenharmony_ci#define ALT_UP(instr...) instr 28562306a36Sopenharmony_ci#define ALT_UP_B(label) b label 28662306a36Sopenharmony_ci#endif 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* 28962306a36Sopenharmony_ci * this_cpu_offset - load the per-CPU offset of this CPU into 29062306a36Sopenharmony_ci * register 'rd' 29162306a36Sopenharmony_ci */ 29262306a36Sopenharmony_ci .macro this_cpu_offset, rd:req 29362306a36Sopenharmony_ci#ifdef CONFIG_SMP 29462306a36Sopenharmony_ciALT_SMP(mrc p15, 0, \rd, c13, c0, 4) 29562306a36Sopenharmony_ci#ifdef CONFIG_CPU_V6 29662306a36Sopenharmony_ciALT_UP_B(.L1_\@) 29762306a36Sopenharmony_ci.L0_\@: 29862306a36Sopenharmony_ci .subsection 1 29962306a36Sopenharmony_ci.L1_\@: ldr_va \rd, __per_cpu_offset 30062306a36Sopenharmony_ci b .L0_\@ 30162306a36Sopenharmony_ci .previous 30262306a36Sopenharmony_ci#endif 30362306a36Sopenharmony_ci#else 30462306a36Sopenharmony_ci mov \rd, #0 30562306a36Sopenharmony_ci#endif 30662306a36Sopenharmony_ci .endm 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci /* 30962306a36Sopenharmony_ci * set_current - store the task pointer of this CPU's current task 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_ci .macro set_current, rn:req, tmp:req 31262306a36Sopenharmony_ci#if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP) 31362306a36Sopenharmony_ci9998: mcr p15, 0, \rn, c13, c0, 3 @ set TPIDRURO register 31462306a36Sopenharmony_ci#ifdef CONFIG_CPU_V6 31562306a36Sopenharmony_ciALT_UP_B(.L0_\@) 31662306a36Sopenharmony_ci .subsection 1 31762306a36Sopenharmony_ci.L0_\@: str_va \rn, __current, \tmp 31862306a36Sopenharmony_ci b .L1_\@ 31962306a36Sopenharmony_ci .previous 32062306a36Sopenharmony_ci.L1_\@: 32162306a36Sopenharmony_ci#endif 32262306a36Sopenharmony_ci#else 32362306a36Sopenharmony_ci str_va \rn, __current, \tmp 32462306a36Sopenharmony_ci#endif 32562306a36Sopenharmony_ci .endm 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* 32862306a36Sopenharmony_ci * get_current - load the task pointer of this CPU's current task 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_ci .macro get_current, rd:req 33162306a36Sopenharmony_ci#if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP) 33262306a36Sopenharmony_ci9998: mrc p15, 0, \rd, c13, c0, 3 @ get TPIDRURO register 33362306a36Sopenharmony_ci#ifdef CONFIG_CPU_V6 33462306a36Sopenharmony_ciALT_UP_B(.L0_\@) 33562306a36Sopenharmony_ci .subsection 1 33662306a36Sopenharmony_ci.L0_\@: ldr_va \rd, __current 33762306a36Sopenharmony_ci b .L1_\@ 33862306a36Sopenharmony_ci .previous 33962306a36Sopenharmony_ci.L1_\@: 34062306a36Sopenharmony_ci#endif 34162306a36Sopenharmony_ci#else 34262306a36Sopenharmony_ci ldr_va \rd, __current 34362306a36Sopenharmony_ci#endif 34462306a36Sopenharmony_ci .endm 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci /* 34762306a36Sopenharmony_ci * reload_current - reload the task pointer of this CPU's current task 34862306a36Sopenharmony_ci * into the TLS register 34962306a36Sopenharmony_ci */ 35062306a36Sopenharmony_ci .macro reload_current, t1:req, t2:req 35162306a36Sopenharmony_ci#if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP) 35262306a36Sopenharmony_ci#ifdef CONFIG_CPU_V6 35362306a36Sopenharmony_ciALT_SMP(nop) 35462306a36Sopenharmony_ciALT_UP_B(.L0_\@) 35562306a36Sopenharmony_ci#endif 35662306a36Sopenharmony_ci ldr_this_cpu \t1, __entry_task, \t1, \t2 35762306a36Sopenharmony_ci mcr p15, 0, \t1, c13, c0, 3 @ store in TPIDRURO 35862306a36Sopenharmony_ci.L0_\@: 35962306a36Sopenharmony_ci#endif 36062306a36Sopenharmony_ci .endm 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci/* 36362306a36Sopenharmony_ci * Instruction barrier 36462306a36Sopenharmony_ci */ 36562306a36Sopenharmony_ci .macro instr_sync 36662306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7 36762306a36Sopenharmony_ci isb 36862306a36Sopenharmony_ci#elif __LINUX_ARM_ARCH__ == 6 36962306a36Sopenharmony_ci mcr p15, 0, r0, c7, c5, 4 37062306a36Sopenharmony_ci#endif 37162306a36Sopenharmony_ci .endm 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci/* 37462306a36Sopenharmony_ci * SMP data memory barrier 37562306a36Sopenharmony_ci */ 37662306a36Sopenharmony_ci .macro smp_dmb mode 37762306a36Sopenharmony_ci#ifdef CONFIG_SMP 37862306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7 37962306a36Sopenharmony_ci .ifeqs "\mode","arm" 38062306a36Sopenharmony_ci ALT_SMP(dmb ish) 38162306a36Sopenharmony_ci .else 38262306a36Sopenharmony_ci ALT_SMP(W(dmb) ish) 38362306a36Sopenharmony_ci .endif 38462306a36Sopenharmony_ci#elif __LINUX_ARM_ARCH__ == 6 38562306a36Sopenharmony_ci ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb 38662306a36Sopenharmony_ci#else 38762306a36Sopenharmony_ci#error Incompatible SMP platform 38862306a36Sopenharmony_ci#endif 38962306a36Sopenharmony_ci .ifeqs "\mode","arm" 39062306a36Sopenharmony_ci ALT_UP(nop) 39162306a36Sopenharmony_ci .else 39262306a36Sopenharmony_ci ALT_UP(W(nop)) 39362306a36Sopenharmony_ci .endif 39462306a36Sopenharmony_ci#endif 39562306a36Sopenharmony_ci .endm 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci/* 39862306a36Sopenharmony_ci * Raw SMP data memory barrier 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_ci .macro __smp_dmb mode 40162306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7 40262306a36Sopenharmony_ci .ifeqs "\mode","arm" 40362306a36Sopenharmony_ci dmb ish 40462306a36Sopenharmony_ci .else 40562306a36Sopenharmony_ci W(dmb) ish 40662306a36Sopenharmony_ci .endif 40762306a36Sopenharmony_ci#elif __LINUX_ARM_ARCH__ == 6 40862306a36Sopenharmony_ci mcr p15, 0, r0, c7, c10, 5 @ dmb 40962306a36Sopenharmony_ci#else 41062306a36Sopenharmony_ci .error "Incompatible SMP platform" 41162306a36Sopenharmony_ci#endif 41262306a36Sopenharmony_ci .endm 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci#if defined(CONFIG_CPU_V7M) 41562306a36Sopenharmony_ci /* 41662306a36Sopenharmony_ci * setmode is used to assert to be in svc mode during boot. For v7-M 41762306a36Sopenharmony_ci * this is done in __v7m_setup, so setmode can be empty here. 41862306a36Sopenharmony_ci */ 41962306a36Sopenharmony_ci .macro setmode, mode, reg 42062306a36Sopenharmony_ci .endm 42162306a36Sopenharmony_ci#elif defined(CONFIG_THUMB2_KERNEL) 42262306a36Sopenharmony_ci .macro setmode, mode, reg 42362306a36Sopenharmony_ci mov \reg, #\mode 42462306a36Sopenharmony_ci msr cpsr_c, \reg 42562306a36Sopenharmony_ci .endm 42662306a36Sopenharmony_ci#else 42762306a36Sopenharmony_ci .macro setmode, mode, reg 42862306a36Sopenharmony_ci msr cpsr_c, #\mode 42962306a36Sopenharmony_ci .endm 43062306a36Sopenharmony_ci#endif 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci/* 43362306a36Sopenharmony_ci * Helper macro to enter SVC mode cleanly and mask interrupts. reg is 43462306a36Sopenharmony_ci * a scratch register for the macro to overwrite. 43562306a36Sopenharmony_ci * 43662306a36Sopenharmony_ci * This macro is intended for forcing the CPU into SVC mode at boot time. 43762306a36Sopenharmony_ci * you cannot return to the original mode. 43862306a36Sopenharmony_ci */ 43962306a36Sopenharmony_ci.macro safe_svcmode_maskall reg:req 44062306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6 && !defined(CONFIG_CPU_V7M) 44162306a36Sopenharmony_ci mrs \reg , cpsr 44262306a36Sopenharmony_ci eor \reg, \reg, #HYP_MODE 44362306a36Sopenharmony_ci tst \reg, #MODE_MASK 44462306a36Sopenharmony_ci bic \reg , \reg , #MODE_MASK 44562306a36Sopenharmony_ci orr \reg , \reg , #PSR_I_BIT | PSR_F_BIT | SVC_MODE 44662306a36Sopenharmony_ciTHUMB( orr \reg , \reg , #PSR_T_BIT ) 44762306a36Sopenharmony_ci bne 1f 44862306a36Sopenharmony_ci orr \reg, \reg, #PSR_A_BIT 44962306a36Sopenharmony_ci badr lr, 2f 45062306a36Sopenharmony_ci msr spsr_cxsf, \reg 45162306a36Sopenharmony_ci __MSR_ELR_HYP(14) 45262306a36Sopenharmony_ci __ERET 45362306a36Sopenharmony_ci1: msr cpsr_c, \reg 45462306a36Sopenharmony_ci2: 45562306a36Sopenharmony_ci#else 45662306a36Sopenharmony_ci/* 45762306a36Sopenharmony_ci * workaround for possibly broken pre-v6 hardware 45862306a36Sopenharmony_ci * (akita, Sharp Zaurus C-1000, PXA270-based) 45962306a36Sopenharmony_ci */ 46062306a36Sopenharmony_ci setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, \reg 46162306a36Sopenharmony_ci#endif 46262306a36Sopenharmony_ci.endm 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci/* 46562306a36Sopenharmony_ci * STRT/LDRT access macros with ARM and Thumb-2 variants 46662306a36Sopenharmony_ci */ 46762306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER() 47062306a36Sopenharmony_ci9999: 47162306a36Sopenharmony_ci .if \inc == 1 47262306a36Sopenharmony_ci \instr\()b\t\cond\().w \reg, [\ptr, #\off] 47362306a36Sopenharmony_ci .elseif \inc == 4 47462306a36Sopenharmony_ci \instr\t\cond\().w \reg, [\ptr, #\off] 47562306a36Sopenharmony_ci .else 47662306a36Sopenharmony_ci .error "Unsupported inc macro argument" 47762306a36Sopenharmony_ci .endif 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci .pushsection __ex_table,"a" 48062306a36Sopenharmony_ci .align 3 48162306a36Sopenharmony_ci .long 9999b, \abort 48262306a36Sopenharmony_ci .popsection 48362306a36Sopenharmony_ci .endm 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci .macro usracc, instr, reg, ptr, inc, cond, rept, abort 48662306a36Sopenharmony_ci @ explicit IT instruction needed because of the label 48762306a36Sopenharmony_ci @ introduced by the USER macro 48862306a36Sopenharmony_ci .ifnc \cond,al 48962306a36Sopenharmony_ci .if \rept == 1 49062306a36Sopenharmony_ci itt \cond 49162306a36Sopenharmony_ci .elseif \rept == 2 49262306a36Sopenharmony_ci ittt \cond 49362306a36Sopenharmony_ci .else 49462306a36Sopenharmony_ci .error "Unsupported rept macro argument" 49562306a36Sopenharmony_ci .endif 49662306a36Sopenharmony_ci .endif 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci @ Slightly optimised to avoid incrementing the pointer twice 49962306a36Sopenharmony_ci usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort 50062306a36Sopenharmony_ci .if \rept == 2 50162306a36Sopenharmony_ci usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort 50262306a36Sopenharmony_ci .endif 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci add\cond \ptr, #\rept * \inc 50562306a36Sopenharmony_ci .endm 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci#else /* !CONFIG_THUMB2_KERNEL */ 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER() 51062306a36Sopenharmony_ci .rept \rept 51162306a36Sopenharmony_ci9999: 51262306a36Sopenharmony_ci .if \inc == 1 51362306a36Sopenharmony_ci \instr\()b\t\cond \reg, [\ptr], #\inc 51462306a36Sopenharmony_ci .elseif \inc == 4 51562306a36Sopenharmony_ci \instr\t\cond \reg, [\ptr], #\inc 51662306a36Sopenharmony_ci .else 51762306a36Sopenharmony_ci .error "Unsupported inc macro argument" 51862306a36Sopenharmony_ci .endif 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci .pushsection __ex_table,"a" 52162306a36Sopenharmony_ci .align 3 52262306a36Sopenharmony_ci .long 9999b, \abort 52362306a36Sopenharmony_ci .popsection 52462306a36Sopenharmony_ci .endr 52562306a36Sopenharmony_ci .endm 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci#endif /* CONFIG_THUMB2_KERNEL */ 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci .macro strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f 53062306a36Sopenharmony_ci usracc str, \reg, \ptr, \inc, \cond, \rept, \abort 53162306a36Sopenharmony_ci .endm 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci .macro ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f 53462306a36Sopenharmony_ci usracc ldr, \reg, \ptr, \inc, \cond, \rept, \abort 53562306a36Sopenharmony_ci .endm 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci/* Utility macro for declaring string literals */ 53862306a36Sopenharmony_ci .macro string name:req, string 53962306a36Sopenharmony_ci .type \name , #object 54062306a36Sopenharmony_ci\name: 54162306a36Sopenharmony_ci .asciz "\string" 54262306a36Sopenharmony_ci .size \name , . - \name 54362306a36Sopenharmony_ci .endm 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci .irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo 54662306a36Sopenharmony_ci .macro ret\c, reg 54762306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 6 54862306a36Sopenharmony_ci mov\c pc, \reg 54962306a36Sopenharmony_ci#else 55062306a36Sopenharmony_ci .ifeqs "\reg", "lr" 55162306a36Sopenharmony_ci bx\c \reg 55262306a36Sopenharmony_ci .else 55362306a36Sopenharmony_ci mov\c pc, \reg 55462306a36Sopenharmony_ci .endif 55562306a36Sopenharmony_ci#endif 55662306a36Sopenharmony_ci .endm 55762306a36Sopenharmony_ci .endr 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci .macro ret.w, reg 56062306a36Sopenharmony_ci ret \reg 56162306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL 56262306a36Sopenharmony_ci nop 56362306a36Sopenharmony_ci#endif 56462306a36Sopenharmony_ci .endm 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci .macro bug, msg, line 56762306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL 56862306a36Sopenharmony_ci1: .inst 0xde02 56962306a36Sopenharmony_ci#else 57062306a36Sopenharmony_ci1: .inst 0xe7f001f2 57162306a36Sopenharmony_ci#endif 57262306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_BUGVERBOSE 57362306a36Sopenharmony_ci .pushsection .rodata.str, "aMS", %progbits, 1 57462306a36Sopenharmony_ci2: .asciz "\msg" 57562306a36Sopenharmony_ci .popsection 57662306a36Sopenharmony_ci .pushsection __bug_table, "aw" 57762306a36Sopenharmony_ci .align 2 57862306a36Sopenharmony_ci .word 1b, 2b 57962306a36Sopenharmony_ci .hword \line 58062306a36Sopenharmony_ci .popsection 58162306a36Sopenharmony_ci#endif 58262306a36Sopenharmony_ci .endm 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci#ifdef CONFIG_KPROBES 58562306a36Sopenharmony_ci#define _ASM_NOKPROBE(entry) \ 58662306a36Sopenharmony_ci .pushsection "_kprobe_blacklist", "aw" ; \ 58762306a36Sopenharmony_ci .balign 4 ; \ 58862306a36Sopenharmony_ci .long entry; \ 58962306a36Sopenharmony_ci .popsection 59062306a36Sopenharmony_ci#else 59162306a36Sopenharmony_ci#define _ASM_NOKPROBE(entry) 59262306a36Sopenharmony_ci#endif 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci .macro __adldst_l, op, reg, sym, tmp, c 59562306a36Sopenharmony_ci .if __LINUX_ARM_ARCH__ < 7 59662306a36Sopenharmony_ci ldr\c \tmp, .La\@ 59762306a36Sopenharmony_ci .subsection 1 59862306a36Sopenharmony_ci .align 2 59962306a36Sopenharmony_ci.La\@: .long \sym - .Lpc\@ 60062306a36Sopenharmony_ci .previous 60162306a36Sopenharmony_ci .else 60262306a36Sopenharmony_ci .ifnb \c 60362306a36Sopenharmony_ci THUMB( ittt \c ) 60462306a36Sopenharmony_ci .endif 60562306a36Sopenharmony_ci movw\c \tmp, #:lower16:\sym - .Lpc\@ 60662306a36Sopenharmony_ci movt\c \tmp, #:upper16:\sym - .Lpc\@ 60762306a36Sopenharmony_ci .endif 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci#ifndef CONFIG_THUMB2_KERNEL 61062306a36Sopenharmony_ci .set .Lpc\@, . + 8 // PC bias 61162306a36Sopenharmony_ci .ifc \op, add 61262306a36Sopenharmony_ci add\c \reg, \tmp, pc 61362306a36Sopenharmony_ci .else 61462306a36Sopenharmony_ci \op\c \reg, [pc, \tmp] 61562306a36Sopenharmony_ci .endif 61662306a36Sopenharmony_ci#else 61762306a36Sopenharmony_ci.Lb\@: add\c \tmp, \tmp, pc 61862306a36Sopenharmony_ci /* 61962306a36Sopenharmony_ci * In Thumb-2 builds, the PC bias depends on whether we are currently 62062306a36Sopenharmony_ci * emitting into a .arm or a .thumb section. The size of the add opcode 62162306a36Sopenharmony_ci * above will be 2 bytes when emitting in Thumb mode and 4 bytes when 62262306a36Sopenharmony_ci * emitting in ARM mode, so let's use this to account for the bias. 62362306a36Sopenharmony_ci */ 62462306a36Sopenharmony_ci .set .Lpc\@, . + (. - .Lb\@) 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci .ifnc \op, add 62762306a36Sopenharmony_ci \op\c \reg, [\tmp] 62862306a36Sopenharmony_ci .endif 62962306a36Sopenharmony_ci#endif 63062306a36Sopenharmony_ci .endm 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci /* 63362306a36Sopenharmony_ci * mov_l - move a constant value or [relocated] address into a register 63462306a36Sopenharmony_ci */ 63562306a36Sopenharmony_ci .macro mov_l, dst:req, imm:req, cond 63662306a36Sopenharmony_ci .if __LINUX_ARM_ARCH__ < 7 63762306a36Sopenharmony_ci ldr\cond \dst, =\imm 63862306a36Sopenharmony_ci .else 63962306a36Sopenharmony_ci movw\cond \dst, #:lower16:\imm 64062306a36Sopenharmony_ci movt\cond \dst, #:upper16:\imm 64162306a36Sopenharmony_ci .endif 64262306a36Sopenharmony_ci .endm 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci /* 64562306a36Sopenharmony_ci * adr_l - adr pseudo-op with unlimited range 64662306a36Sopenharmony_ci * 64762306a36Sopenharmony_ci * @dst: destination register 64862306a36Sopenharmony_ci * @sym: name of the symbol 64962306a36Sopenharmony_ci * @cond: conditional opcode suffix 65062306a36Sopenharmony_ci */ 65162306a36Sopenharmony_ci .macro adr_l, dst:req, sym:req, cond 65262306a36Sopenharmony_ci __adldst_l add, \dst, \sym, \dst, \cond 65362306a36Sopenharmony_ci .endm 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci /* 65662306a36Sopenharmony_ci * ldr_l - ldr <literal> pseudo-op with unlimited range 65762306a36Sopenharmony_ci * 65862306a36Sopenharmony_ci * @dst: destination register 65962306a36Sopenharmony_ci * @sym: name of the symbol 66062306a36Sopenharmony_ci * @cond: conditional opcode suffix 66162306a36Sopenharmony_ci */ 66262306a36Sopenharmony_ci .macro ldr_l, dst:req, sym:req, cond 66362306a36Sopenharmony_ci __adldst_l ldr, \dst, \sym, \dst, \cond 66462306a36Sopenharmony_ci .endm 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci /* 66762306a36Sopenharmony_ci * str_l - str <literal> pseudo-op with unlimited range 66862306a36Sopenharmony_ci * 66962306a36Sopenharmony_ci * @src: source register 67062306a36Sopenharmony_ci * @sym: name of the symbol 67162306a36Sopenharmony_ci * @tmp: mandatory scratch register 67262306a36Sopenharmony_ci * @cond: conditional opcode suffix 67362306a36Sopenharmony_ci */ 67462306a36Sopenharmony_ci .macro str_l, src:req, sym:req, tmp:req, cond 67562306a36Sopenharmony_ci __adldst_l str, \src, \sym, \tmp, \cond 67662306a36Sopenharmony_ci .endm 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci .macro __ldst_va, op, reg, tmp, sym, cond, offset 67962306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7 || \ 68062306a36Sopenharmony_ci !defined(CONFIG_ARM_HAS_GROUP_RELOCS) || \ 68162306a36Sopenharmony_ci (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) 68262306a36Sopenharmony_ci mov_l \tmp, \sym, \cond 68362306a36Sopenharmony_ci#else 68462306a36Sopenharmony_ci /* 68562306a36Sopenharmony_ci * Avoid a literal load, by emitting a sequence of ADD/LDR instructions 68662306a36Sopenharmony_ci * with the appropriate relocations. The combined sequence has a range 68762306a36Sopenharmony_ci * of -/+ 256 MiB, which should be sufficient for the core kernel and 68862306a36Sopenharmony_ci * for modules loaded into the module region. 68962306a36Sopenharmony_ci */ 69062306a36Sopenharmony_ci .globl \sym 69162306a36Sopenharmony_ci .reloc .L0_\@, R_ARM_ALU_PC_G0_NC, \sym 69262306a36Sopenharmony_ci .reloc .L1_\@, R_ARM_ALU_PC_G1_NC, \sym 69362306a36Sopenharmony_ci .reloc .L2_\@, R_ARM_LDR_PC_G2, \sym 69462306a36Sopenharmony_ci.L0_\@: sub\cond \tmp, pc, #8 - \offset 69562306a36Sopenharmony_ci.L1_\@: sub\cond \tmp, \tmp, #4 - \offset 69662306a36Sopenharmony_ci.L2_\@: 69762306a36Sopenharmony_ci#endif 69862306a36Sopenharmony_ci \op\cond \reg, [\tmp, #\offset] 69962306a36Sopenharmony_ci .endm 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci /* 70262306a36Sopenharmony_ci * ldr_va - load a 32-bit word from the virtual address of \sym 70362306a36Sopenharmony_ci */ 70462306a36Sopenharmony_ci .macro ldr_va, rd:req, sym:req, cond, tmp, offset=0 70562306a36Sopenharmony_ci .ifnb \tmp 70662306a36Sopenharmony_ci __ldst_va ldr, \rd, \tmp, \sym, \cond, \offset 70762306a36Sopenharmony_ci .else 70862306a36Sopenharmony_ci __ldst_va ldr, \rd, \rd, \sym, \cond, \offset 70962306a36Sopenharmony_ci .endif 71062306a36Sopenharmony_ci .endm 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci /* 71362306a36Sopenharmony_ci * str_va - store a 32-bit word to the virtual address of \sym 71462306a36Sopenharmony_ci */ 71562306a36Sopenharmony_ci .macro str_va, rn:req, sym:req, tmp:req, cond 71662306a36Sopenharmony_ci __ldst_va str, \rn, \tmp, \sym, \cond, 0 71762306a36Sopenharmony_ci .endm 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* 72062306a36Sopenharmony_ci * ldr_this_cpu_armv6 - Load a 32-bit word from the per-CPU variable 'sym', 72162306a36Sopenharmony_ci * without using a temp register. Supported in ARM mode 72262306a36Sopenharmony_ci * only. 72362306a36Sopenharmony_ci */ 72462306a36Sopenharmony_ci .macro ldr_this_cpu_armv6, rd:req, sym:req 72562306a36Sopenharmony_ci this_cpu_offset \rd 72662306a36Sopenharmony_ci .globl \sym 72762306a36Sopenharmony_ci .reloc .L0_\@, R_ARM_ALU_PC_G0_NC, \sym 72862306a36Sopenharmony_ci .reloc .L1_\@, R_ARM_ALU_PC_G1_NC, \sym 72962306a36Sopenharmony_ci .reloc .L2_\@, R_ARM_LDR_PC_G2, \sym 73062306a36Sopenharmony_ci add \rd, \rd, pc 73162306a36Sopenharmony_ci.L0_\@: sub \rd, \rd, #4 73262306a36Sopenharmony_ci.L1_\@: sub \rd, \rd, #0 73362306a36Sopenharmony_ci.L2_\@: ldr \rd, [\rd, #4] 73462306a36Sopenharmony_ci .endm 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci /* 73762306a36Sopenharmony_ci * ldr_this_cpu - Load a 32-bit word from the per-CPU variable 'sym' 73862306a36Sopenharmony_ci * into register 'rd', which may be the stack pointer, 73962306a36Sopenharmony_ci * using 't1' and 't2' as general temp registers. These 74062306a36Sopenharmony_ci * are permitted to overlap with 'rd' if != sp 74162306a36Sopenharmony_ci */ 74262306a36Sopenharmony_ci .macro ldr_this_cpu, rd:req, sym:req, t1:req, t2:req 74362306a36Sopenharmony_ci#ifndef CONFIG_SMP 74462306a36Sopenharmony_ci ldr_va \rd, \sym, tmp=\t1 74562306a36Sopenharmony_ci#elif __LINUX_ARM_ARCH__ >= 7 || \ 74662306a36Sopenharmony_ci !defined(CONFIG_ARM_HAS_GROUP_RELOCS) || \ 74762306a36Sopenharmony_ci (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) 74862306a36Sopenharmony_ci this_cpu_offset \t1 74962306a36Sopenharmony_ci mov_l \t2, \sym 75062306a36Sopenharmony_ci ldr \rd, [\t1, \t2] 75162306a36Sopenharmony_ci#else 75262306a36Sopenharmony_ci ldr_this_cpu_armv6 \rd, \sym 75362306a36Sopenharmony_ci#endif 75462306a36Sopenharmony_ci .endm 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci /* 75762306a36Sopenharmony_ci * rev_l - byte-swap a 32-bit value 75862306a36Sopenharmony_ci * 75962306a36Sopenharmony_ci * @val: source/destination register 76062306a36Sopenharmony_ci * @tmp: scratch register 76162306a36Sopenharmony_ci */ 76262306a36Sopenharmony_ci .macro rev_l, val:req, tmp:req 76362306a36Sopenharmony_ci .if __LINUX_ARM_ARCH__ < 6 76462306a36Sopenharmony_ci eor \tmp, \val, \val, ror #16 76562306a36Sopenharmony_ci bic \tmp, \tmp, #0x00ff0000 76662306a36Sopenharmony_ci mov \val, \val, ror #8 76762306a36Sopenharmony_ci eor \val, \val, \tmp, lsr #8 76862306a36Sopenharmony_ci .else 76962306a36Sopenharmony_ci rev \val, \val 77062306a36Sopenharmony_ci .endif 77162306a36Sopenharmony_ci .endm 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci .if __LINUX_ARM_ARCH__ < 6 77462306a36Sopenharmony_ci .set .Lrev_l_uses_tmp, 1 77562306a36Sopenharmony_ci .else 77662306a36Sopenharmony_ci .set .Lrev_l_uses_tmp, 0 77762306a36Sopenharmony_ci .endif 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci /* 78062306a36Sopenharmony_ci * bl_r - branch and link to register 78162306a36Sopenharmony_ci * 78262306a36Sopenharmony_ci * @dst: target to branch to 78362306a36Sopenharmony_ci * @c: conditional opcode suffix 78462306a36Sopenharmony_ci */ 78562306a36Sopenharmony_ci .macro bl_r, dst:req, c 78662306a36Sopenharmony_ci .if __LINUX_ARM_ARCH__ < 6 78762306a36Sopenharmony_ci mov\c lr, pc 78862306a36Sopenharmony_ci mov\c pc, \dst 78962306a36Sopenharmony_ci .else 79062306a36Sopenharmony_ci blx\c \dst 79162306a36Sopenharmony_ci .endif 79262306a36Sopenharmony_ci .endm 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci#endif /* __ASM_ASSEMBLER_H__ */ 795