#ifndef _ASM_M32R_ASSEMBLER_H #define _ASM_M32R_ASSEMBLER_H /* * linux/asm-m32r/assembler.h * * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org> * * This file contains M32R architecture specific macro definitions. */ #ifndef __STR #ifdef __ASSEMBLY__ #define __STR(x) x #else #define __STR(x) #x #endif #endif /* __STR */ #ifdef CONFIG_SMP #define M32R_LOCK __STR(lock) #define M32R_UNLOCK __STR(unlock) #else #define M32R_LOCK __STR(ld) #define M32R_UNLOCK __STR(st) #endif #ifdef __ASSEMBLY__ #undef ENTRY #define ENTRY(name) ENTRY_M name .macro ENTRY_M name .global \name ALIGN \name: .endm #endif /** * LDIMM - load immediate value * STI - enable interruption * CLI - disable interruption */ #ifdef __ASSEMBLY__ #define LDIMM(reg,x) LDIMM reg x .macro LDIMM reg x seth \reg, #high(\x) or3 \reg, \reg, #low(\x) .endm #if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104)) #define ENABLE_INTERRUPTS(reg) ENABLE_INTERRUPTS reg .macro ENABLE_INTERRUPTS reg setpsw #0x40 -> nop ; WORKAROUND: "-> nop" is a workaround for the M32700(TS1). .endm #define DISABLE_INTERRUPTS(reg) DISABLE_INTERRUPTS reg .macro DISABLE_INTERRUPTS reg clrpsw #0x40 -> nop ; WORKAROUND: "-> nop" is a workaround for the M32700(TS1). .endm #else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */ #define ENABLE_INTERRUPTS(reg) ENABLE_INTERRUPTS reg .macro ENABLE_INTERRUPTS reg mvfc \reg, psw or3 \reg, \reg, #0x0040 mvtc \reg, psw .endm #define DISABLE_INTERRUPTS(reg) DISABLE_INTERRUPTS reg .macro DISABLE_INTERRUPTS reg mvfc \reg, psw and3 \reg, \reg, #0xffbf mvtc \reg, psw .endm #endif /* CONFIG_CHIP_M32102 */ .macro SAVE_ALL push r0 ; orig_r0 push sp ; spi (r15) push lr ; r14 push r13 mvfc r13, cr3 ; spu push r13 mvfc r13, bbpc push r13 mvfc r13, bbpsw push r13 mvfc r13, bpc push r13 mvfc r13, psw push r13 #if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2) mvfaclo r13, a1 push r13 mvfachi r13, a1 push r13 mvfaclo r13, a0 push r13 mvfachi r13, a0 push r13 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R) mvfaclo r13 push r13 mvfachi r13 push r13 ldi r13, #0 push r13 ; dummy push acc1h push r13 ; dummy push acc1l #else #error unknown isa configuration #endif ldi r13, #-1 push r13 ; syscall_nr (default: -1) push r12 push r11 push r10 push r9 push r8 push r7 push r3 push r2 push r1 push r0 addi sp, #-4 ; room for implicit pt_regs parameter push r6 push r5 push r4 .endm .macro RESTORE_ALL pop r4 pop r5 pop r6 addi sp, #4 pop r0 pop r1 pop r2 pop r3 pop r7 pop r8 pop r9 pop r10 pop r11 pop r12 addi r15, #4 ; Skip syscall number #if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2) pop r13 mvtachi r13, a0 pop r13 mvtaclo r13, a0 pop r13 mvtachi r13, a1 pop r13 mvtaclo r13, a1 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R) pop r13 ; dummy pop acc1h pop r13 ; dummy pop acc1l pop r13 mvtachi r13 pop r13 mvtaclo r13 #else #error unknown isa configuration #endif pop r14 mvtc r14, psw pop r14 mvtc r14, bpc addi sp, #8 ; Skip bbpsw, bbpc pop r14 mvtc r14, cr3 ; spu pop r13 pop lr ; r14 pop sp ; spi (r15) addi sp, #4 ; Skip orig_r0 .fillinsn 1: rte .section .fixup,"ax" 2: bl do_exit .previous .section __ex_table,"a" ALIGN .long 1b, 2b .previous .endm #define GET_CURRENT(reg) get_current reg .macro get_current reg ldi \reg, #-8192 and \reg, sp .endm #if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104)) .macro SWITCH_TO_KERNEL_STACK ; switch to kernel stack (spi) clrpsw #0x80 -> nop .endm #else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */ .macro SWITCH_TO_KERNEL_STACK push r0 ; save r0 for working mvfc r0, psw and3 r0, r0, #0x00ff7f mvtc r0, psw slli r0, #16 bltz r0, 1f ; check BSM-bit ; ;; called from kernel context: previous stack = spi pop r0 ; retrieve r0 bra 2f .fillinsn 1: ;; called from user context: previous stack = spu mvfc r0, cr3 ; spu addi r0, #4 mvtc r0, cr3 ; spu ld r0, @(-4,r0) ; retrieve r0 .fillinsn 2: .endm #endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */ #endif /* __ASSEMBLY__ */ #endif /* _ASM_M32R_ASSEMBLER_H */