Merge branch 'mti-next' of git://git.linux-mips.org/pub/scm/sjhill/linux-sjhill into mips-for-linux-next

This commit is contained in:
Ralf Baechle
2013-05-09 17:57:30 +02:00
90 changed files with 5839 additions and 1420 deletions

View File

@@ -296,6 +296,7 @@ symbol = value
#define LONG_SUBU subu
#define LONG_L lw
#define LONG_S sw
#define LONG_SP swp
#define LONG_SLL sll
#define LONG_SLLV sllv
#define LONG_SRL srl
@@ -318,6 +319,7 @@ symbol = value
#define LONG_SUBU dsubu
#define LONG_L ld
#define LONG_S sd
#define LONG_SP sdp
#define LONG_SLL dsll
#define LONG_SLLV dsllv
#define LONG_SRL dsrl

View File

@@ -11,6 +11,14 @@
#include <asm/ptrace.h>
#include <asm/inst.h>
extern int __isa_exception_epc(struct pt_regs *regs);
extern int __compute_return_epc(struct pt_regs *regs);
extern int __compute_return_epc_for_insn(struct pt_regs *regs,
union mips_instruction insn);
extern int __microMIPS_compute_return_epc(struct pt_regs *regs);
extern int __MIPS16e_compute_return_epc(struct pt_regs *regs);
static inline int delay_slot(struct pt_regs *regs)
{
return regs->cp0_cause & CAUSEF_BD;
@@ -18,20 +26,27 @@ static inline int delay_slot(struct pt_regs *regs)
static inline unsigned long exception_epc(struct pt_regs *regs)
{
if (!delay_slot(regs))
if (likely(!delay_slot(regs)))
return regs->cp0_epc;
if (get_isa16_mode(regs->cp0_epc))
return __isa_exception_epc(regs);
return regs->cp0_epc + 4;
}
#define BRANCH_LIKELY_TAKEN 0x0001
extern int __compute_return_epc(struct pt_regs *regs);
extern int __compute_return_epc_for_insn(struct pt_regs *regs,
union mips_instruction insn);
static inline int compute_return_epc(struct pt_regs *regs)
{
if (get_isa16_mode(regs->cp0_epc)) {
if (cpu_has_mmips)
return __microMIPS_compute_return_epc(regs);
if (cpu_has_mips16)
return __MIPS16e_compute_return_epc(regs);
return regs->cp0_epc;
}
if (!delay_slot(regs)) {
regs->cp0_epc += 4;
return 0;
@@ -40,4 +55,19 @@ static inline int compute_return_epc(struct pt_regs *regs)
return __compute_return_epc(regs);
}
static inline int MIPS16e_compute_return_epc(struct pt_regs *regs,
union mips16e_instruction *inst)
{
if (likely(!delay_slot(regs))) {
if (inst->ri.opcode == MIPS16e_extend_op) {
regs->cp0_epc += 4;
return 0;
}
regs->cp0_epc += 2;
return 0;
}
return __MIPS16e_compute_return_epc(regs);
}
#endif /* _ASM_BRANCH_H */

View File

@@ -0,0 +1,15 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org>
*
*/
#ifndef __ASM_DMA_COHERENCE_H
#define __ASM_DMA_COHERENCE_H
extern int coherentio;
extern int hw_coherentio;
#endif

View File

@@ -2,6 +2,7 @@
#define _ASM_DMA_MAPPING_H
#include <asm/scatterlist.h>
#include <asm/dma-coherence.h>
#include <asm/cache.h>
#include <asm-generic/dma-coherent.h>

View File

@@ -54,6 +54,12 @@ do { \
extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
unsigned long cpc);
extern int do_dsemulret(struct pt_regs *xcp);
extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
struct mips_fpu_struct *ctx, int has_fpu,
void *__user *fault_addr);
int process_fpemu_return(int sig, void __user *fault_addr);
int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
unsigned long *contpc);
/*
* Instruction inserted following the badinst to further tag the sequence

View File

@@ -0,0 +1,47 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2012 MIPS Technologies, Inc.
*/
#ifndef __ASM_FW_H_
#define __ASM_FW_H_
#include <asm/bootinfo.h> /* For cleaner code... */
enum fw_memtypes {
fw_dontuse,
fw_code,
fw_free,
};
typedef struct {
unsigned long base; /* Within KSEG0 */
unsigned int size; /* bytes */
enum fw_memtypes type; /* fw_memtypes */
} fw_memblock_t;
/* Maximum number of memory block descriptors. */
#define FW_MAX_MEMBLOCKS 32
extern int fw_argc;
extern int *_fw_argv;
extern int *_fw_envp;
/*
* Most firmware like YAMON, PMON, etc. pass arguments and environment
* variables as 32-bit pointers. These take care of sign extension.
*/
#define fw_argv(index) ((char *)(long)_fw_argv[(index)])
#define fw_envp(index) ((char *)(long)_fw_envp[(index)])
extern void fw_init_cmdline(void);
extern char *fw_getcmdline(void);
extern fw_memblock_t *fw_getmdesc(void);
extern void fw_meminit(void);
extern char *fw_getenv(char *name);
extern unsigned long fw_getenvl(char *name);
extern void fw_init_early_console(char port);
#endif /* __ASM_FW_H_ */

View File

@@ -202,7 +202,7 @@
#define GIC_VPE_WD_COUNT0_OFS 0x0094
#define GIC_VPE_WD_INITIAL0_OFS 0x0098
#define GIC_VPE_COMPARE_LO_OFS 0x00a0
#define GIC_VPE_COMPARE_HI 0x00a4
#define GIC_VPE_COMPARE_HI_OFS 0x00a4
#define GIC_VPE_EIC_SHADOW_SET_BASE 0x0100
#define GIC_VPE_EIC_SS(intr) \
@@ -359,7 +359,11 @@ struct gic_shared_intr_map {
/* Mapped interrupt to pin X, then GIC will generate the vector (X+1). */
#define GIC_PIN_TO_VEC_OFFSET (1)
extern int gic_present;
#include <linux/clocksource.h>
#include <linux/irq.h>
extern unsigned int gic_present;
extern unsigned int gic_frequency;
extern unsigned long _gic_base;
extern unsigned int gic_irq_base;
extern unsigned int gic_irq_flags[];
@@ -368,18 +372,20 @@ extern struct gic_shared_intr_map gic_shared_intr_map[];
extern void gic_init(unsigned long gic_base_addr,
unsigned long gic_addrspace_size, struct gic_intr_map *intrmap,
unsigned int intrmap_size, unsigned int irqbase);
extern void gic_clocksource_init(unsigned int);
extern unsigned int gic_get_int(void);
extern unsigned int gic_compare_int (void);
extern cycle_t gic_read_count(void);
extern cycle_t gic_read_compare(void);
extern void gic_write_compare(cycle_t cnt);
extern void gic_send_ipi(unsigned int intr);
extern unsigned int plat_ipi_call_int_xlate(unsigned int);
extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
extern void gic_bind_eic_interrupt(int irq, int set);
extern unsigned int gic_get_timer_pending(void);
extern unsigned int gic_get_int(void);
extern void gic_enable_interrupt(int irq_vec);
extern void gic_disable_interrupt(int irq_vec);
extern void gic_irq_ack(struct irq_data *d);
extern void gic_finish_irq(struct irq_data *d);
extern void gic_platform_init(int irqs, struct irq_chip *irq_controller);
#endif /* _ASM_GICREGS_H */

View File

@@ -73,4 +73,16 @@
typedef unsigned int mips_instruction;
/* microMIPS instruction decode structure. Do NOT export!!! */
struct mm_decoded_insn {
mips_instruction insn;
mips_instruction next_insn;
int pc_inc;
int next_pc_inc;
int micro_mips_mode;
};
/* Recode table from 16-bit register notation to 32-bit GPR. Do NOT export!!! */
extern const int reg16to32[];
#endif /* _ASM_INST_H */

View File

@@ -336,7 +336,7 @@ enum emulation_result {
#define VPN2_MASK 0xffffe000
#define TLB_IS_GLOBAL(x) (((x).tlb_lo0 & MIPS3_PG_G) && ((x).tlb_lo1 & MIPS3_PG_G))
#define TLB_VPN2(x) ((x).tlb_hi & VPN2_MASK)
#define TLB_ASID(x) ((x).tlb_hi & ASID_MASK)
#define TLB_ASID(x) (ASID_MASK((x).tlb_hi))
#define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) ? ((x).tlb_lo1 & MIPS3_PG_V) : ((x).tlb_lo0 & MIPS3_PG_V))
struct kvm_mips_tlb {

View File

@@ -61,9 +61,8 @@ static inline int plat_device_is_coherent(struct device *dev)
{
#ifdef CONFIG_DMA_COHERENT
return 1;
#endif
#ifdef CONFIG_DMA_NONCOHERENT
return 0;
#else
return coherentio;
#endif
}

View File

@@ -28,7 +28,11 @@
/* #define cpu_has_prefetch ? */
#define cpu_has_mcheck 1
/* #define cpu_has_ejtag ? */
#ifdef CONFIG_CPU_MICROMIPS
#define cpu_has_llsc 0
#else
#define cpu_has_llsc 1
#endif
/* #define cpu_has_vtag_icache ? */
/* #define cpu_has_dc_aliases ? */
/* #define cpu_has_ic_fills_f_dc ? */

View File

@@ -83,4 +83,7 @@ extern void mips_pcibios_init(void);
#define mips_pcibios_init() do { } while (0)
#endif
extern void mips_scroll_message(void);
extern void mips_display_message(const char *str);
#endif /* __ASM_MIPS_BOARDS_GENERIC_H */

View File

@@ -1,47 +0,0 @@
/*
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
*
* ########################################################################
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* ########################################################################
*
* MIPS boards bootprom interface for the Linux kernel.
*
*/
#ifndef _MIPS_PROM_H
#define _MIPS_PROM_H
extern char *prom_getcmdline(void);
extern char *prom_getenv(char *name);
extern void prom_init_cmdline(void);
extern void prom_meminit(void);
extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
extern void mips_display_message(const char *str);
extern void mips_display_word(unsigned int num);
extern void mips_scroll_message(void);
extern int get_ethernet_addr(char *ethernet_addr);
/* Memory descriptor management. */
#define PROM_MAX_PMEMBLOCKS 32
struct prom_pmemblock {
unsigned long base; /* Within KSEG0. */
unsigned int size; /* In bytes. */
unsigned int type; /* free or prom memory */
};
#endif /* !(_MIPS_PROM_H) */

View File

@@ -596,6 +596,7 @@
#define MIPS_CONF3_RXI (_ULCAST_(1) << 12)
#define MIPS_CONF3_ULRI (_ULCAST_(1) << 13)
#define MIPS_CONF3_ISA (_ULCAST_(3) << 14)
#define MIPS_CONF3_ISA_OE (_ULCAST_(3) << 16)
#define MIPS_CONF3_VZ (_ULCAST_(1) << 23)
#define MIPS_CONF4_MMUSIZEEXT (_ULCAST_(255) << 0)
@@ -622,6 +623,24 @@
#ifndef __ASSEMBLY__
/*
* Macros for handling the ISA mode bit for microMIPS.
*/
#define get_isa16_mode(x) ((x) & 0x1)
#define msk_isa16_mode(x) ((x) & ~0x1)
#define set_isa16_mode(x) do { (x) |= 0x1; } while(0)
/*
* microMIPS instructions can be 16-bit or 32-bit in length. This
* returns a 1 if the instruction is 16-bit and a 0 if 32-bit.
*/
static inline int mm_insn_16bit(u16 insn)
{
u16 opcode = (insn >> 10) & 0x7;
return (opcode >= 1 && opcode <= 3) ? 1 : 0;
}
/*
* Functions to access the R10000 performance counters. These are basically
* mfc0 and mtc0 instructions from and to coprocessor register with a 5-bit

View File

@@ -67,45 +67,68 @@ extern unsigned long pgd_current[];
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
#endif
#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
#define ASID_INC 0x40
#define ASID_MASK 0xfc0
#define ASID_INC(asid) \
({ \
unsigned long __asid = asid; \
__asm__("1:\taddiu\t%0,1\t\t\t\t# patched\n\t" \
".section\t__asid_inc,\"a\"\n\t" \
".word\t1b\n\t" \
".previous" \
:"=r" (__asid) \
:"0" (__asid)); \
__asid; \
})
#define ASID_MASK(asid) \
({ \
unsigned long __asid = asid; \
__asm__("1:\tandi\t%0,%1,0xfc0\t\t\t# patched\n\t" \
".section\t__asid_mask,\"a\"\n\t" \
".word\t1b\n\t" \
".previous" \
:"=r" (__asid) \
:"r" (__asid)); \
__asid; \
})
#define ASID_VERSION_MASK \
({ \
unsigned long __asid; \
__asm__("1:\taddiu\t%0,$0,0xff00\t\t\t\t# patched\n\t" \
".section\t__asid_version_mask,\"a\"\n\t" \
".word\t1b\n\t" \
".previous" \
:"=r" (__asid)); \
__asid; \
})
#define ASID_FIRST_VERSION \
({ \
unsigned long __asid = asid; \
__asm__("1:\tli\t%0,0x100\t\t\t\t# patched\n\t" \
".section\t__asid_first_version,\"a\"\n\t" \
".word\t1b\n\t" \
".previous" \
:"=r" (__asid)); \
__asid; \
})
#elif defined(CONFIG_CPU_R8000)
#define ASID_INC 0x10
#define ASID_MASK 0xff0
#elif defined(CONFIG_MIPS_MT_SMTC)
#define ASID_INC 0x1
extern unsigned long smtc_asid_mask;
#define ASID_MASK (smtc_asid_mask)
#define HW_ASID_MASK 0xff
/* End SMTC/34K debug hack */
#else /* FIXME: not correct for R6000 */
#define ASID_INC 0x1
#define ASID_MASK 0xff
#define ASID_FIRST_VERSION_R3000 0x1000
#define ASID_FIRST_VERSION_R4000 0x100
#define ASID_FIRST_VERSION_R8000 0x1000
#define ASID_FIRST_VERSION_RM9000 0x1000
#ifdef CONFIG_MIPS_MT_SMTC
#define SMTC_HW_ASID_MASK 0xff
extern unsigned int smtc_asid_mask;
#endif
#define cpu_context(cpu, mm) ((mm)->context.asid[cpu])
#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK)
#define cpu_asid(cpu, mm) ASID_MASK(cpu_context((cpu), (mm)))
#define asid_cache(cpu) (cpu_data[cpu].asid_cache)
static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
/*
* All unused by hardware upper bits will be considered
* as a software asid extension.
*/
#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
#ifndef CONFIG_MIPS_MT_SMTC
/* Normal, classic MIPS get_new_mmu_context */
static inline void
@@ -114,7 +137,7 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
extern void kvm_local_flush_tlb_all(void);
unsigned long asid = asid_cache(cpu);
if (! ((asid += ASID_INC) & ASID_MASK) ) {
if (!ASID_MASK((asid = ASID_INC(asid)))) {
if (cpu_has_vtag_icache)
flush_icache_all();
#ifdef CONFIG_VIRTUALIZATION
@@ -177,7 +200,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
* free up the ASID value for use and flush any old
* instances of it from the TLB.
*/
oldasid = (read_c0_entryhi() & ASID_MASK);
oldasid = ASID_MASK(read_c0_entryhi());
if(smtc_live_asid[mytlb][oldasid]) {
smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
if(smtc_live_asid[mytlb][oldasid] == 0)
@@ -188,7 +211,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
* having ASID_MASK smaller than the hardware maximum,
* make sure no "soft" bits become "hard"...
*/
write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
write_c0_entryhi((read_c0_entryhi() & ~SMTC_HW_ASID_MASK) |
cpu_asid(cpu, next));
ehb(); /* Make sure it propagates to TCStatus */
evpe(mtflags);
@@ -241,15 +264,15 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
#ifdef CONFIG_MIPS_MT_SMTC
/* See comments for similar code above */
mtflags = dvpe();
oldasid = read_c0_entryhi() & ASID_MASK;
oldasid = ASID_MASK(read_c0_entryhi());
if(smtc_live_asid[mytlb][oldasid]) {
smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
if(smtc_live_asid[mytlb][oldasid] == 0)
smtc_flush_tlb_asid(oldasid);
}
/* See comments for similar code above */
write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
cpu_asid(cpu, next));
write_c0_entryhi((read_c0_entryhi() & ~SMTC_HW_ASID_MASK) |
cpu_asid(cpu, next));
ehb(); /* Make sure it propagates to TCStatus */
evpe(mtflags);
#else
@@ -286,14 +309,14 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
#ifdef CONFIG_MIPS_MT_SMTC
/* See comments for similar code above */
prevvpe = dvpe();
oldasid = (read_c0_entryhi() & ASID_MASK);
oldasid = ASID_MASK(read_c0_entryhi());
if (smtc_live_asid[mytlb][oldasid]) {
smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
if(smtc_live_asid[mytlb][oldasid] == 0)
smtc_flush_tlb_asid(oldasid);
}
/* See comments for similar code above */
write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
write_c0_entryhi((read_c0_entryhi() & ~SMTC_HW_ASID_MASK)
| cpu_asid(cpu, mm));
ehb(); /* Make sure it propagates to TCStatus */
evpe(prevvpe);

View File

@@ -139,7 +139,7 @@
1: move ra, k0
li k0, 3
mtc0 k0, $22
#endif /* CONFIG_CPU_LOONGSON2F */
#endif /* CONFIG_CPU_JUMP_WORKAROUNDS */
#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
lui k1, %hi(kernelsp)
#else
@@ -189,6 +189,7 @@
LONG_S $0, PT_R0(sp)
mfc0 v1, CP0_STATUS
LONG_S $2, PT_R2(sp)
LONG_S v1, PT_STATUS(sp)
#ifdef CONFIG_MIPS_MT_SMTC
/*
* Ideally, these instructions would be shuffled in
@@ -200,21 +201,20 @@
LONG_S k0, PT_TCSTATUS(sp)
#endif /* CONFIG_MIPS_MT_SMTC */
LONG_S $4, PT_R4(sp)
LONG_S $5, PT_R5(sp)
LONG_S v1, PT_STATUS(sp)
mfc0 v1, CP0_CAUSE
LONG_S $6, PT_R6(sp)
LONG_S $7, PT_R7(sp)
LONG_S $5, PT_R5(sp)
LONG_S v1, PT_CAUSE(sp)
LONG_S $6, PT_R6(sp)
MFC0 v1, CP0_EPC
LONG_S $7, PT_R7(sp)
#ifdef CONFIG_64BIT
LONG_S $8, PT_R8(sp)
LONG_S $9, PT_R9(sp)
#endif
LONG_S v1, PT_EPC(sp)
LONG_S $25, PT_R25(sp)
LONG_S $28, PT_R28(sp)
LONG_S $31, PT_R31(sp)
LONG_S v1, PT_EPC(sp)
ori $28, sp, _THREAD_MASK
xori $28, _THREAD_MASK
#ifdef CONFIG_CPU_CAVIUM_OCTEON

View File

@@ -52,13 +52,15 @@ extern int (*perf_irq)(void);
*/
extern unsigned int __weak get_c0_compare_int(void);
extern int r4k_clockevent_init(void);
extern int smtc_clockevent_init(void);
extern int gic_clockevent_init(void);
static inline int mips_clockevent_init(void)
{
#ifdef CONFIG_MIPS_MT_SMTC
extern int smtc_clockevent_init(void);
return smtc_clockevent_init();
#elif defined(CONFIG_CEVT_GIC)
return (gic_clockevent_init() | r4k_clockevent_init());
#elif defined(CONFIG_CEVT_R4K)
return r4k_clockevent_init();
#else
@@ -69,9 +71,7 @@ static inline int mips_clockevent_init(void)
/*
* Initialize the count register as a clocksource
*/
#ifdef CONFIG_CSRC_R4K
extern int init_r4k_clocksource(void);
#endif
static inline int init_mips_clocksource(void)
{

View File

@@ -270,6 +270,7 @@ do { \
__asm__ __volatile__( \
"1: " insn " %1, %3 \n" \
"2: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"3: li %0, %4 \n" \
" j 2b \n" \
@@ -296,7 +297,9 @@ do { \
__asm__ __volatile__( \
"1: lw %1, (%3) \n" \
"2: lw %D1, 4(%3) \n" \
"3: .section .fixup,\"ax\" \n" \
"3: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"4: li %0, %4 \n" \
" move %1, $0 \n" \
" move %D1, $0 \n" \
@@ -364,6 +367,7 @@ do { \
__asm__ __volatile__( \
"1: " insn " %z2, %3 # __put_user_asm\n" \
"2: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"3: li %0, %4 \n" \
" j 2b \n" \
@@ -382,6 +386,7 @@ do { \
"1: sw %2, (%3) # __put_user_asm_ll32 \n" \
"2: sw %D2, 4(%3) \n" \
"3: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"4: li %0, %4 \n" \
" j 3b \n" \
@@ -533,6 +538,7 @@ do { \
__asm__ __volatile__( \
"1: " insn " %1, %3 \n" \
"2: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"3: li %0, %4 \n" \
" j 2b \n" \
@@ -558,7 +564,9 @@ do { \
"1: ulw %1, (%3) \n" \
"2: ulw %D1, 4(%3) \n" \
" move %0, $0 \n" \
"3: .section .fixup,\"ax\" \n" \
"3: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"4: li %0, %4 \n" \
" move %1, $0 \n" \
" move %D1, $0 \n" \
@@ -625,6 +633,7 @@ do { \
__asm__ __volatile__( \
"1: " insn " %z2, %3 # __put_user_unaligned_asm\n" \
"2: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"3: li %0, %4 \n" \
" j 2b \n" \
@@ -643,6 +652,7 @@ do { \
"1: sw %2, (%3) # __put_user_unaligned_asm_ll32 \n" \
"2: sw %D2, 4(%3) \n" \
"3: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"4: li %0, %4 \n" \
" j 3b \n" \

View File

@@ -6,7 +6,7 @@
* Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer
* Copyright (C) 2005 Maciej W. Rozycki
* Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
* Copyright (C) 2012 MIPS Technologies, Inc.
* Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved.
*/
#include <linux/types.h>
@@ -22,44 +22,75 @@
#define UASM_EXPORT_SYMBOL(sym)
#endif
#define _UASM_ISA_CLASSIC 0
#define _UASM_ISA_MICROMIPS 1
#ifndef UASM_ISA
#ifdef CONFIG_CPU_MICROMIPS
#define UASM_ISA _UASM_ISA_MICROMIPS
#else
#define UASM_ISA _UASM_ISA_CLASSIC
#endif
#endif
#if (UASM_ISA == _UASM_ISA_CLASSIC)
#ifdef CONFIG_CPU_MICROMIPS
#define ISAOPC(op) CL_uasm_i##op
#define ISAFUNC(x) CL_##x
#else
#define ISAOPC(op) uasm_i##op
#define ISAFUNC(x) x
#endif
#elif (UASM_ISA == _UASM_ISA_MICROMIPS)
#ifdef CONFIG_CPU_MICROMIPS
#define ISAOPC(op) uasm_i##op
#define ISAFUNC(x) x
#else
#define ISAOPC(op) MM_uasm_i##op
#define ISAFUNC(x) MM_##x
#endif
#else
#error Unsupported micro-assembler ISA!!!
#endif
#define Ip_u1u2u3(op) \
void __uasminit \
uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
#define Ip_u2u1u3(op) \
void __uasminit \
uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
#define Ip_u3u1u2(op) \
void __uasminit \
uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
#define Ip_u1u2s3(op) \
void __uasminit \
uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c)
ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c)
#define Ip_u2s3u1(op) \
void __uasminit \
uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c)
ISAOPC(op)(u32 **buf, unsigned int a, signed int b, unsigned int c)
#define Ip_u2u1s3(op) \
void __uasminit \
uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c)
ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c)
#define Ip_u2u1msbu3(op) \
void __uasminit \
uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \
ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \
unsigned int d)
#define Ip_u1u2(op) \
void __uasminit uasm_i##op(u32 **buf, unsigned int a, unsigned int b)
void __uasminit ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b)
#define Ip_u1s2(op) \
void __uasminit uasm_i##op(u32 **buf, unsigned int a, signed int b)
void __uasminit ISAOPC(op)(u32 **buf, unsigned int a, signed int b)
#define Ip_u1(op) void __uasminit uasm_i##op(u32 **buf, unsigned int a)
#define Ip_u1(op) void __uasminit ISAOPC(op)(u32 **buf, unsigned int a)
#define Ip_0(op) void __uasminit uasm_i##op(u32 **buf)
#define Ip_0(op) void __uasminit ISAOPC(op)(u32 **buf)
Ip_u2u1s3(_addiu);
Ip_u3u1u2(_addu);
@@ -132,19 +163,20 @@ struct uasm_label {
int lab;
};
void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid);
void __uasminit ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr,
int lid);
#ifdef CONFIG_64BIT
int uasm_in_compat_space_p(long addr);
int ISAFUNC(uasm_in_compat_space_p)(long addr);
#endif
int uasm_rel_hi(long val);
int uasm_rel_lo(long val);
void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr);
void UASM_i_LA(u32 **buf, unsigned int rs, long addr);
int ISAFUNC(uasm_rel_hi)(long val);
int ISAFUNC(uasm_rel_lo)(long val);
void ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr);
void ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr);
#define UASM_L_LA(lb) \
static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
static inline void __uasminit ISAFUNC(uasm_l##lb)(struct uasm_label **lab, u32 *addr) \
{ \
uasm_build_label(lab, addr, label##lb); \
ISAFUNC(uasm_build_label)(lab, addr, label##lb); \
}
/* convenience macros for instructions */
@@ -196,27 +228,27 @@ static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1,
unsigned int a2, unsigned int a3)
{
if (a3 < 32)
uasm_i_drotr(p, a1, a2, a3);
ISAOPC(_drotr)(p, a1, a2, a3);
else
uasm_i_drotr32(p, a1, a2, a3 - 32);
ISAOPC(_drotr32)(p, a1, a2, a3 - 32);
}
static inline void uasm_i_dsll_safe(u32 **p, unsigned int a1,
unsigned int a2, unsigned int a3)
{
if (a3 < 32)
uasm_i_dsll(p, a1, a2, a3);
ISAOPC(_dsll)(p, a1, a2, a3);
else
uasm_i_dsll32(p, a1, a2, a3 - 32);
ISAOPC(_dsll32)(p, a1, a2, a3 - 32);
}
static inline void uasm_i_dsrl_safe(u32 **p, unsigned int a1,
unsigned int a2, unsigned int a3)
{
if (a3 < 32)
uasm_i_dsrl(p, a1, a2, a3);
ISAOPC(_dsrl)(p, a1, a2, a3);
else
uasm_i_dsrl32(p, a1, a2, a3 - 32);
ISAOPC(_dsrl32)(p, a1, a2, a3 - 32);
}
/* Handle relocations. */