| #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 */ |