#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.
*/
#include <linux/config.h>
#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)
#define STI(reg) STI_M reg
.macro STI_M reg
setpsw #0x40 -> nop
; WORKAROUND: "-> nop" is a workaround for the M32700(TS1).
.endm
#define CLI(reg) CLI_M reg
.macro CLI_M reg
clrpsw #0x40 -> nop
; WORKAROUND: "-> nop" is a workaround for the M32700(TS1).
.endm
#else /* CONFIG_CHIP_M32102 */
#define STI(reg) STI_M reg
.macro STI_M reg
mvfc \reg, psw
or3 \reg, \reg, #0x0040
mvtc \reg, psw
.endm
#define CLI(reg) CLI_M reg
.macro CLI_M 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
#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
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)
.macro SWITCH_TO_KERNEL_STACK
; switch to kernel stack (spi)
clrpsw #0x80 -> nop
.endm
#else /* CONFIG_CHIP_M32102 */
.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 */
#endif /* __ASSEMBLY__ */
#endif /* _ASM_M32R_ASSEMBLER_H */