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:
@@ -4,7 +4,7 @@
|
||||
|
||||
obj-y += cache.o dma-default.o extable.o fault.o \
|
||||
gup.o init.o mmap.o page.o page-funcs.o \
|
||||
tlbex.o tlbex-fault.o uasm.o
|
||||
tlbex.o tlbex-fault.o uasm-mips.o
|
||||
|
||||
obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o
|
||||
obj-$(CONFIG_64BIT) += pgtable-64.o
|
||||
@@ -22,3 +22,5 @@ obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
|
||||
obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
|
||||
obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
|
||||
obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o
|
||||
|
||||
obj-$(CONFIG_SYS_SUPPORTS_MICROMIPS) += uasm-micromips.o
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include <asm/war.h>
|
||||
#include <asm/cacheflush.h> /* for run_uncached() */
|
||||
#include <asm/traps.h>
|
||||
#include <asm/dma-coherence.h>
|
||||
|
||||
/*
|
||||
* Special Variant of smp_call_function for use by cache functions:
|
||||
@@ -1379,20 +1380,6 @@ static void __cpuinit coherency_setup(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DMA_NONCOHERENT)
|
||||
|
||||
static int __cpuinitdata coherentio;
|
||||
|
||||
static int __init setcoherentio(char *str)
|
||||
{
|
||||
coherentio = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
early_param("coherentio", setcoherentio);
|
||||
#endif
|
||||
|
||||
static void __cpuinit r4k_cache_error_setup(void)
|
||||
{
|
||||
extern char __weak except_vec2_generic;
|
||||
@@ -1474,9 +1461,14 @@ void __cpuinit r4k_cache_init(void)
|
||||
|
||||
build_clear_page();
|
||||
build_copy_page();
|
||||
#if !defined(CONFIG_MIPS_CMP)
|
||||
|
||||
/*
|
||||
* We want to run CMP kernels on core with and without coherent
|
||||
* caches. Therefore, do not use CONFIG_MIPS_CMP to decide whether
|
||||
* or not to flush caches.
|
||||
*/
|
||||
local_r4k___flush_cache_all(NULL);
|
||||
#endif
|
||||
|
||||
coherency_setup();
|
||||
board_cache_error_setup = r4k_cache_error_setup;
|
||||
}
|
||||
|
@@ -22,6 +22,26 @@
|
||||
|
||||
#include <dma-coherence.h>
|
||||
|
||||
int coherentio = 0; /* User defined DMA coherency from command line. */
|
||||
EXPORT_SYMBOL_GPL(coherentio);
|
||||
int hw_coherentio = 0; /* Actual hardware supported DMA coherency setting. */
|
||||
|
||||
static int __init setcoherentio(char *str)
|
||||
{
|
||||
coherentio = 1;
|
||||
pr_info("Hardware DMA cache coherency (command line)\n");
|
||||
return 0;
|
||||
}
|
||||
early_param("coherentio", setcoherentio);
|
||||
|
||||
static int __init setnocoherentio(char *str)
|
||||
{
|
||||
coherentio = 0;
|
||||
pr_info("Software DMA cache coherency (command line)\n");
|
||||
return 0;
|
||||
}
|
||||
early_param("nocoherentio", setnocoherentio);
|
||||
|
||||
static inline struct page *dma_addr_to_page(struct device *dev,
|
||||
dma_addr_t dma_addr)
|
||||
{
|
||||
@@ -115,7 +135,8 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
|
||||
|
||||
if (!plat_device_is_coherent(dev)) {
|
||||
dma_cache_wback_inv((unsigned long) ret, size);
|
||||
ret = UNCAC_ADDR(ret);
|
||||
if (!hw_coherentio)
|
||||
ret = UNCAC_ADDR(ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +163,7 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
|
||||
|
||||
plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
|
||||
|
||||
if (!plat_device_is_coherent(dev))
|
||||
if (!plat_device_is_coherent(dev) && !hw_coherentio)
|
||||
addr = CAC_ADDR(addr);
|
||||
|
||||
free_pages(addr, get_order(size));
|
||||
|
@@ -51,7 +51,7 @@ void local_flush_tlb_all(void)
|
||||
#endif
|
||||
|
||||
local_irq_save(flags);
|
||||
old_ctx = read_c0_entryhi() & ASID_MASK;
|
||||
old_ctx = ASID_MASK(read_c0_entryhi());
|
||||
write_c0_entrylo0(0);
|
||||
entry = r3k_have_wired_reg ? read_c0_wired() : 8;
|
||||
for (; entry < current_cpu_data.tlbsize; entry++) {
|
||||
@@ -87,13 +87,13 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
|
||||
#ifdef DEBUG_TLB
|
||||
printk("[tlbrange<%lu,0x%08lx,0x%08lx>]",
|
||||
cpu_context(cpu, mm) & ASID_MASK, start, end);
|
||||
ASID_MASK(cpu_context(cpu, mm)), start, end);
|
||||
#endif
|
||||
local_irq_save(flags);
|
||||
size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
|
||||
if (size <= current_cpu_data.tlbsize) {
|
||||
int oldpid = read_c0_entryhi() & ASID_MASK;
|
||||
int newpid = cpu_context(cpu, mm) & ASID_MASK;
|
||||
int oldpid = ASID_MASK(read_c0_entryhi());
|
||||
int newpid = ASID_MASK(cpu_context(cpu, mm));
|
||||
|
||||
start &= PAGE_MASK;
|
||||
end += PAGE_SIZE - 1;
|
||||
@@ -166,10 +166,10 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
|
||||
#ifdef DEBUG_TLB
|
||||
printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page);
|
||||
#endif
|
||||
newpid = cpu_context(cpu, vma->vm_mm) & ASID_MASK;
|
||||
newpid = ASID_MASK(cpu_context(cpu, vma->vm_mm));
|
||||
page &= PAGE_MASK;
|
||||
local_irq_save(flags);
|
||||
oldpid = read_c0_entryhi() & ASID_MASK;
|
||||
oldpid = ASID_MASK(read_c0_entryhi());
|
||||
write_c0_entryhi(page | newpid);
|
||||
BARRIER;
|
||||
tlb_probe();
|
||||
@@ -197,10 +197,10 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
|
||||
if (current->active_mm != vma->vm_mm)
|
||||
return;
|
||||
|
||||
pid = read_c0_entryhi() & ASID_MASK;
|
||||
pid = ASID_MASK(read_c0_entryhi());
|
||||
|
||||
#ifdef DEBUG_TLB
|
||||
if ((pid != (cpu_context(cpu, vma->vm_mm) & ASID_MASK)) || (cpu_context(cpu, vma->vm_mm) == 0)) {
|
||||
if ((pid != ASID_MASK(cpu_context(cpu, vma->vm_mm))) || (cpu_context(cpu, vma->vm_mm) == 0)) {
|
||||
printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n",
|
||||
(cpu_context(cpu, vma->vm_mm)), pid);
|
||||
}
|
||||
@@ -241,7 +241,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
|
||||
|
||||
local_irq_save(flags);
|
||||
/* Save old context and create impossible VPN2 value */
|
||||
old_ctx = read_c0_entryhi() & ASID_MASK;
|
||||
old_ctx = ASID_MASK(read_c0_entryhi());
|
||||
old_pagemask = read_c0_pagemask();
|
||||
w = read_c0_wired();
|
||||
write_c0_wired(w + 1);
|
||||
@@ -264,7 +264,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
|
||||
#endif
|
||||
|
||||
local_irq_save(flags);
|
||||
old_ctx = read_c0_entryhi() & ASID_MASK;
|
||||
old_ctx = ASID_MASK(read_c0_entryhi());
|
||||
write_c0_entrylo0(entrylo0);
|
||||
write_c0_entryhi(entryhi);
|
||||
write_c0_index(wired);
|
||||
|
@@ -287,7 +287,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
|
||||
|
||||
ENTER_CRITICAL(flags);
|
||||
|
||||
pid = read_c0_entryhi() & ASID_MASK;
|
||||
pid = ASID_MASK(read_c0_entryhi());
|
||||
address &= (PAGE_MASK << 1);
|
||||
write_c0_entryhi(address | pid);
|
||||
pgdp = pgd_offset(vma->vm_mm, address);
|
||||
|
@@ -195,7 +195,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
|
||||
if (current->active_mm != vma->vm_mm)
|
||||
return;
|
||||
|
||||
pid = read_c0_entryhi() & ASID_MASK;
|
||||
pid = ASID_MASK(read_c0_entryhi());
|
||||
|
||||
local_irq_save(flags);
|
||||
address &= PAGE_MASK;
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/cache.h>
|
||||
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/war.h>
|
||||
@@ -305,6 +306,78 @@ static struct uasm_reloc relocs[128] __cpuinitdata;
|
||||
static int check_for_high_segbits __cpuinitdata;
|
||||
#endif
|
||||
|
||||
static void __cpuinit insn_fixup(unsigned int **start, unsigned int **stop,
|
||||
unsigned int i_const)
|
||||
{
|
||||
unsigned int **p;
|
||||
|
||||
for (p = start; p < stop; p++) {
|
||||
#ifndef CONFIG_CPU_MICROMIPS
|
||||
unsigned int *ip;
|
||||
|
||||
ip = *p;
|
||||
*ip = (*ip & 0xffff0000) | i_const;
|
||||
#else
|
||||
unsigned short *ip;
|
||||
|
||||
ip = ((unsigned short *)((unsigned int)*p - 1));
|
||||
if ((*ip & 0xf000) == 0x4000) {
|
||||
*ip &= 0xfff1;
|
||||
*ip |= (i_const << 1);
|
||||
} else if ((*ip & 0xf000) == 0x6000) {
|
||||
*ip &= 0xfff1;
|
||||
*ip |= ((i_const >> 2) << 1);
|
||||
} else {
|
||||
ip++;
|
||||
*ip = i_const;
|
||||
}
|
||||
#endif
|
||||
local_flush_icache_range((unsigned long)ip,
|
||||
(unsigned long)ip + sizeof(*ip));
|
||||
}
|
||||
}
|
||||
|
||||
#define asid_insn_fixup(section, const) \
|
||||
do { \
|
||||
extern unsigned int *__start_ ## section; \
|
||||
extern unsigned int *__stop_ ## section; \
|
||||
insn_fixup(&__start_ ## section, &__stop_ ## section, const); \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Caller is assumed to flush the caches before the first context switch.
|
||||
*/
|
||||
static void __cpuinit setup_asid(unsigned int inc, unsigned int mask,
|
||||
unsigned int version_mask,
|
||||
unsigned int first_version)
|
||||
{
|
||||
extern asmlinkage void handle_ri_rdhwr_vivt(void);
|
||||
unsigned long *vivt_exc;
|
||||
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
/*
|
||||
* Worst case optimised microMIPS addiu instructions support
|
||||
* only a 3-bit immediate value.
|
||||
*/
|
||||
if(inc > 7)
|
||||
panic("Invalid ASID increment value!");
|
||||
#endif
|
||||
asid_insn_fixup(__asid_inc, inc);
|
||||
asid_insn_fixup(__asid_mask, mask);
|
||||
asid_insn_fixup(__asid_version_mask, version_mask);
|
||||
asid_insn_fixup(__asid_first_version, first_version);
|
||||
|
||||
/* Patch up the 'handle_ri_rdhwr_vivt' handler. */
|
||||
vivt_exc = (unsigned long *) &handle_ri_rdhwr_vivt;
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
vivt_exc = (unsigned long *)((unsigned long) vivt_exc - 1);
|
||||
#endif
|
||||
vivt_exc++;
|
||||
*vivt_exc = (*vivt_exc & ~mask) | mask;
|
||||
|
||||
current_cpu_data.asid_cache = first_version;
|
||||
}
|
||||
|
||||
static int check_for_high_segbits __cpuinitdata;
|
||||
|
||||
static unsigned int kscratch_used_mask __cpuinitdata;
|
||||
@@ -2030,6 +2103,13 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
|
||||
|
||||
uasm_l_nopage_tlbl(&l, p);
|
||||
build_restore_work_registers(&p);
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
if ((unsigned long)tlb_do_page_fault_0 & 1) {
|
||||
uasm_i_lui(&p, K0, uasm_rel_hi((long)tlb_do_page_fault_0));
|
||||
uasm_i_addiu(&p, K0, K0, uasm_rel_lo((long)tlb_do_page_fault_0));
|
||||
uasm_i_jr(&p, K0);
|
||||
} else
|
||||
#endif
|
||||
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
|
||||
uasm_i_nop(&p);
|
||||
|
||||
@@ -2077,6 +2157,13 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
|
||||
|
||||
uasm_l_nopage_tlbs(&l, p);
|
||||
build_restore_work_registers(&p);
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
if ((unsigned long)tlb_do_page_fault_1 & 1) {
|
||||
uasm_i_lui(&p, K0, uasm_rel_hi((long)tlb_do_page_fault_1));
|
||||
uasm_i_addiu(&p, K0, K0, uasm_rel_lo((long)tlb_do_page_fault_1));
|
||||
uasm_i_jr(&p, K0);
|
||||
} else
|
||||
#endif
|
||||
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
|
||||
uasm_i_nop(&p);
|
||||
|
||||
@@ -2125,6 +2212,13 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
|
||||
|
||||
uasm_l_nopage_tlbm(&l, p);
|
||||
build_restore_work_registers(&p);
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
if ((unsigned long)tlb_do_page_fault_1 & 1) {
|
||||
uasm_i_lui(&p, K0, uasm_rel_hi((long)tlb_do_page_fault_1));
|
||||
uasm_i_addiu(&p, K0, K0, uasm_rel_lo((long)tlb_do_page_fault_1));
|
||||
uasm_i_jr(&p, K0);
|
||||
} else
|
||||
#endif
|
||||
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
|
||||
uasm_i_nop(&p);
|
||||
|
||||
@@ -2162,6 +2256,7 @@ void __cpuinit build_tlb_refill_handler(void)
|
||||
case CPU_TX3922:
|
||||
case CPU_TX3927:
|
||||
#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
|
||||
setup_asid(0x40, 0xfc0, 0xf000, ASID_FIRST_VERSION_R3000);
|
||||
if (cpu_has_local_ebase)
|
||||
build_r3000_tlb_refill_handler();
|
||||
if (!run_once) {
|
||||
@@ -2187,6 +2282,11 @@ void __cpuinit build_tlb_refill_handler(void)
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifndef CONFIG_MIPS_MT_SMTC
|
||||
setup_asid(0x1, 0xff, 0xff00, ASID_FIRST_VERSION_R4000);
|
||||
#else
|
||||
setup_asid(0x1, smtc_asid_mask, 0xff00, ASID_FIRST_VERSION_R4000);
|
||||
#endif
|
||||
if (!run_once) {
|
||||
scratch_reg = allocate_kscratch();
|
||||
#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
|
||||
|
221
arch/mips/mm/uasm-micromips.c
Normal file
221
arch/mips/mm/uasm-micromips.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* A small micro-assembler. It is intentionally kept simple, does only
|
||||
* support a subset of instructions, and does not try to hide pipeline
|
||||
* effects like branch delay slots.
|
||||
*
|
||||
* Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer
|
||||
* Copyright (C) 2005, 2007 Maciej W. Rozycki
|
||||
* Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
|
||||
* Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/inst.h>
|
||||
#include <asm/elf.h>
|
||||
#include <asm/bugs.h>
|
||||
#define UASM_ISA _UASM_ISA_MICROMIPS
|
||||
#include <asm/uasm.h>
|
||||
|
||||
#define RS_MASK 0x1f
|
||||
#define RS_SH 16
|
||||
#define RT_MASK 0x1f
|
||||
#define RT_SH 21
|
||||
#define SCIMM_MASK 0x3ff
|
||||
#define SCIMM_SH 16
|
||||
|
||||
/* This macro sets the non-variable bits of an instruction. */
|
||||
#define M(a, b, c, d, e, f) \
|
||||
((a) << OP_SH \
|
||||
| (b) << RT_SH \
|
||||
| (c) << RS_SH \
|
||||
| (d) << RD_SH \
|
||||
| (e) << RE_SH \
|
||||
| (f) << FUNC_SH)
|
||||
|
||||
/* Define these when we are not the ISA the kernel is being compiled with. */
|
||||
#ifndef CONFIG_CPU_MICROMIPS
|
||||
#define MM_uasm_i_b(buf, off) ISAOPC(_beq)(buf, 0, 0, off)
|
||||
#define MM_uasm_i_beqz(buf, rs, off) ISAOPC(_beq)(buf, rs, 0, off)
|
||||
#define MM_uasm_i_beqzl(buf, rs, off) ISAOPC(_beql)(buf, rs, 0, off)
|
||||
#define MM_uasm_i_bnez(buf, rs, off) ISAOPC(_bne)(buf, rs, 0, off)
|
||||
#endif
|
||||
|
||||
#include "uasm.c"
|
||||
|
||||
static struct insn insn_table_MM[] __uasminitdata = {
|
||||
{ insn_addu, M(mm_pool32a_op, 0, 0, 0, 0, mm_addu32_op), RT | RS | RD },
|
||||
{ insn_addiu, M(mm_addiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
|
||||
{ insn_and, M(mm_pool32a_op, 0, 0, 0, 0, mm_and_op), RT | RS | RD },
|
||||
{ insn_andi, M(mm_andi32_op, 0, 0, 0, 0, 0), RT | RS | UIMM },
|
||||
{ insn_beq, M(mm_beq32_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||
{ insn_beql, 0, 0 },
|
||||
{ insn_bgez, M(mm_pool32i_op, mm_bgez_op, 0, 0, 0, 0), RS | BIMM },
|
||||
{ insn_bgezl, 0, 0 },
|
||||
{ insn_bltz, M(mm_pool32i_op, mm_bltz_op, 0, 0, 0, 0), RS | BIMM },
|
||||
{ insn_bltzl, 0, 0 },
|
||||
{ insn_bne, M(mm_bne32_op, 0, 0, 0, 0, 0), RT | RS | BIMM },
|
||||
{ insn_cache, M(mm_pool32b_op, 0, 0, mm_cache_func, 0, 0), RT | RS | SIMM },
|
||||
{ insn_daddu, 0, 0 },
|
||||
{ insn_daddiu, 0, 0 },
|
||||
{ insn_dmfc0, 0, 0 },
|
||||
{ insn_dmtc0, 0, 0 },
|
||||
{ insn_dsll, 0, 0 },
|
||||
{ insn_dsll32, 0, 0 },
|
||||
{ insn_dsra, 0, 0 },
|
||||
{ insn_dsrl, 0, 0 },
|
||||
{ insn_dsrl32, 0, 0 },
|
||||
{ insn_drotr, 0, 0 },
|
||||
{ insn_drotr32, 0, 0 },
|
||||
{ insn_dsubu, 0, 0 },
|
||||
{ insn_eret, M(mm_pool32a_op, 0, 0, 0, mm_eret_op, mm_pool32axf_op), 0 },
|
||||
{ insn_ins, M(mm_pool32a_op, 0, 0, 0, 0, mm_ins_op), RT | RS | RD | RE },
|
||||
{ insn_ext, M(mm_pool32a_op, 0, 0, 0, 0, mm_ext_op), RT | RS | RD | RE },
|
||||
{ insn_j, M(mm_j32_op, 0, 0, 0, 0, 0), JIMM },
|
||||
{ insn_jal, M(mm_jal32_op, 0, 0, 0, 0, 0), JIMM },
|
||||
{ insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS },
|
||||
{ insn_ld, 0, 0 },
|
||||
{ insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIMM },
|
||||
{ insn_lld, 0, 0 },
|
||||
{ insn_lui, M(mm_pool32i_op, mm_lui_op, 0, 0, 0, 0), RS | SIMM },
|
||||
{ insn_lw, M(mm_lw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
|
||||
{ insn_mfc0, M(mm_pool32a_op, 0, 0, 0, mm_mfc0_op, mm_pool32axf_op), RT | RS | RD },
|
||||
{ insn_mtc0, M(mm_pool32a_op, 0, 0, 0, mm_mtc0_op, mm_pool32axf_op), RT | RS | RD },
|
||||
{ insn_or, M(mm_pool32a_op, 0, 0, 0, 0, mm_or32_op), RT | RS | RD },
|
||||
{ insn_ori, M(mm_ori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM },
|
||||
{ insn_pref, M(mm_pool32c_op, 0, 0, (mm_pref_func << 1), 0, 0), RT | RS | SIMM },
|
||||
{ insn_rfe, 0, 0 },
|
||||
{ insn_sc, M(mm_pool32c_op, 0, 0, (mm_sc_func << 1), 0, 0), RT | RS | SIMM },
|
||||
{ insn_scd, 0, 0 },
|
||||
{ insn_sd, 0, 0 },
|
||||
{ insn_sll, M(mm_pool32a_op, 0, 0, 0, 0, mm_sll32_op), RT | RS | RD },
|
||||
{ insn_sra, M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD },
|
||||
{ insn_srl, M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD },
|
||||
{ insn_rotr, M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD },
|
||||
{ insn_subu, M(mm_pool32a_op, 0, 0, 0, 0, mm_subu32_op), RT | RS | RD },
|
||||
{ insn_sw, M(mm_sw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
|
||||
{ insn_tlbp, M(mm_pool32a_op, 0, 0, 0, mm_tlbp_op, mm_pool32axf_op), 0 },
|
||||
{ insn_tlbr, M(mm_pool32a_op, 0, 0, 0, mm_tlbr_op, mm_pool32axf_op), 0 },
|
||||
{ insn_tlbwi, M(mm_pool32a_op, 0, 0, 0, mm_tlbwi_op, mm_pool32axf_op), 0 },
|
||||
{ insn_tlbwr, M(mm_pool32a_op, 0, 0, 0, mm_tlbwr_op, mm_pool32axf_op), 0 },
|
||||
{ insn_xor, M(mm_pool32a_op, 0, 0, 0, 0, mm_xor32_op), RT | RS | RD },
|
||||
{ insn_xori, M(mm_xori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM },
|
||||
{ insn_dins, 0, 0 },
|
||||
{ insn_dinsm, 0, 0 },
|
||||
{ insn_syscall, M(mm_pool32a_op, 0, 0, 0, mm_syscall_op, mm_pool32axf_op), SCIMM},
|
||||
{ insn_bbit0, 0, 0 },
|
||||
{ insn_bbit1, 0, 0 },
|
||||
{ insn_lwx, 0, 0 },
|
||||
{ insn_ldx, 0, 0 },
|
||||
{ insn_invalid, 0, 0 }
|
||||
};
|
||||
|
||||
#undef M
|
||||
|
||||
static inline __uasminit u32 build_bimm(s32 arg)
|
||||
{
|
||||
WARN(arg > 0xffff || arg < -0x10000,
|
||||
KERN_WARNING "Micro-assembler field overflow\n");
|
||||
|
||||
WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
|
||||
|
||||
return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 1) & 0x7fff);
|
||||
}
|
||||
|
||||
static inline __uasminit u32 build_jimm(u32 arg)
|
||||
{
|
||||
|
||||
WARN(arg & ~((JIMM_MASK << 2) | 1),
|
||||
KERN_WARNING "Micro-assembler field overflow\n");
|
||||
|
||||
return (arg >> 1) & JIMM_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* The order of opcode arguments is implicitly left to right,
|
||||
* starting with RS and ending with FUNC or IMM.
|
||||
*/
|
||||
static void __uasminit build_insn(u32 **buf, enum opcode opc, ...)
|
||||
{
|
||||
struct insn *ip = NULL;
|
||||
unsigned int i;
|
||||
va_list ap;
|
||||
u32 op;
|
||||
|
||||
for (i = 0; insn_table_MM[i].opcode != insn_invalid; i++)
|
||||
if (insn_table_MM[i].opcode == opc) {
|
||||
ip = &insn_table_MM[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ip || (opc == insn_daddiu && r4k_daddiu_bug()))
|
||||
panic("Unsupported Micro-assembler instruction %d", opc);
|
||||
|
||||
op = ip->match;
|
||||
va_start(ap, opc);
|
||||
if (ip->fields & RS) {
|
||||
if (opc == insn_mfc0 || opc == insn_mtc0)
|
||||
op |= build_rt(va_arg(ap, u32));
|
||||
else
|
||||
op |= build_rs(va_arg(ap, u32));
|
||||
}
|
||||
if (ip->fields & RT) {
|
||||
if (opc == insn_mfc0 || opc == insn_mtc0)
|
||||
op |= build_rs(va_arg(ap, u32));
|
||||
else
|
||||
op |= build_rt(va_arg(ap, u32));
|
||||
}
|
||||
if (ip->fields & RD)
|
||||
op |= build_rd(va_arg(ap, u32));
|
||||
if (ip->fields & RE)
|
||||
op |= build_re(va_arg(ap, u32));
|
||||
if (ip->fields & SIMM)
|
||||
op |= build_simm(va_arg(ap, s32));
|
||||
if (ip->fields & UIMM)
|
||||
op |= build_uimm(va_arg(ap, u32));
|
||||
if (ip->fields & BIMM)
|
||||
op |= build_bimm(va_arg(ap, s32));
|
||||
if (ip->fields & JIMM)
|
||||
op |= build_jimm(va_arg(ap, u32));
|
||||
if (ip->fields & FUNC)
|
||||
op |= build_func(va_arg(ap, u32));
|
||||
if (ip->fields & SET)
|
||||
op |= build_set(va_arg(ap, u32));
|
||||
if (ip->fields & SCIMM)
|
||||
op |= build_scimm(va_arg(ap, u32));
|
||||
va_end(ap);
|
||||
|
||||
#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||
**buf = ((op & 0xffff) << 16) | (op >> 16);
|
||||
#else
|
||||
**buf = op;
|
||||
#endif
|
||||
(*buf)++;
|
||||
}
|
||||
|
||||
static inline void __uasminit
|
||||
__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
|
||||
{
|
||||
long laddr = (long)lab->addr;
|
||||
long raddr = (long)rel->addr;
|
||||
|
||||
switch (rel->type) {
|
||||
case R_MIPS_PC16:
|
||||
#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||
*rel->addr |= (build_bimm(laddr - (raddr + 4)) << 16);
|
||||
#else
|
||||
*rel->addr |= build_bimm(laddr - (raddr + 4));
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("Unsupported Micro-assembler relocation %d",
|
||||
rel->type);
|
||||
}
|
||||
}
|
205
arch/mips/mm/uasm-mips.c
Normal file
205
arch/mips/mm/uasm-mips.c
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* A small micro-assembler. It is intentionally kept simple, does only
|
||||
* support a subset of instructions, and does not try to hide pipeline
|
||||
* effects like branch delay slots.
|
||||
*
|
||||
* Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer
|
||||
* Copyright (C) 2005, 2007 Maciej W. Rozycki
|
||||
* Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
|
||||
* Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/inst.h>
|
||||
#include <asm/elf.h>
|
||||
#include <asm/bugs.h>
|
||||
#define UASM_ISA _UASM_ISA_CLASSIC
|
||||
#include <asm/uasm.h>
|
||||
|
||||
#define RS_MASK 0x1f
|
||||
#define RS_SH 21
|
||||
#define RT_MASK 0x1f
|
||||
#define RT_SH 16
|
||||
#define SCIMM_MASK 0xfffff
|
||||
#define SCIMM_SH 6
|
||||
|
||||
/* This macro sets the non-variable bits of an instruction. */
|
||||
#define M(a, b, c, d, e, f) \
|
||||
((a) << OP_SH \
|
||||
| (b) << RS_SH \
|
||||
| (c) << RT_SH \
|
||||
| (d) << RD_SH \
|
||||
| (e) << RE_SH \
|
||||
| (f) << FUNC_SH)
|
||||
|
||||
/* Define these when we are not the ISA the kernel is being compiled with. */
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
#define CL_uasm_i_b(buf, off) ISAOPC(_beq)(buf, 0, 0, off)
|
||||
#define CL_uasm_i_beqz(buf, rs, off) ISAOPC(_beq)(buf, rs, 0, off)
|
||||
#define CL_uasm_i_beqzl(buf, rs, off) ISAOPC(_beql)(buf, rs, 0, off)
|
||||
#define CL_uasm_i_bnez(buf, rs, off) ISAOPC(_bne)(buf, rs, 0, off)
|
||||
#endif
|
||||
|
||||
#include "uasm.c"
|
||||
|
||||
static struct insn insn_table[] __uasminitdata = {
|
||||
{ insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
|
||||
{ insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
|
||||
{ insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
|
||||
{ insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||
{ insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||
{ insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||
{ insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||
{ insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
|
||||
{ insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM },
|
||||
{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
|
||||
{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
|
||||
{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||
{ insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
|
||||
{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
|
||||
{ insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
|
||||
{ insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
|
||||
{ insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
|
||||
{ insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE },
|
||||
{ insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE },
|
||||
{ insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE },
|
||||
{ insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE },
|
||||
{ insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE },
|
||||
{ insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE },
|
||||
{ insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
|
||||
{ insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
|
||||
{ insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 },
|
||||
{ insn_ext, M(spec3_op, 0, 0, 0, 0, ext_op), RS | RT | RD | RE },
|
||||
{ insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE },
|
||||
{ insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
|
||||
{ insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM },
|
||||
{ insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
|
||||
{ insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS },
|
||||
{ insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
|
||||
{ insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM },
|
||||
{ insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
|
||||
{ insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET},
|
||||
{ insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET},
|
||||
{ insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
|
||||
{ insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD },
|
||||
{ insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 },
|
||||
{ insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE },
|
||||
{ insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE },
|
||||
{ insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE },
|
||||
{ insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE },
|
||||
{ insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD },
|
||||
{ insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
|
||||
{ insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 },
|
||||
{ insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 },
|
||||
{ insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 },
|
||||
{ insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 },
|
||||
{ insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
|
||||
{ insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD },
|
||||
{ insn_invalid, 0, 0 }
|
||||
};
|
||||
|
||||
#undef M
|
||||
|
||||
static inline __uasminit u32 build_bimm(s32 arg)
|
||||
{
|
||||
WARN(arg > 0x1ffff || arg < -0x20000,
|
||||
KERN_WARNING "Micro-assembler field overflow\n");
|
||||
|
||||
WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
|
||||
|
||||
return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
|
||||
}
|
||||
|
||||
static inline __uasminit u32 build_jimm(u32 arg)
|
||||
{
|
||||
WARN(arg & ~(JIMM_MASK << 2),
|
||||
KERN_WARNING "Micro-assembler field overflow\n");
|
||||
|
||||
return (arg >> 2) & JIMM_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* The order of opcode arguments is implicitly left to right,
|
||||
* starting with RS and ending with FUNC or IMM.
|
||||
*/
|
||||
static void __uasminit build_insn(u32 **buf, enum opcode opc, ...)
|
||||
{
|
||||
struct insn *ip = NULL;
|
||||
unsigned int i;
|
||||
va_list ap;
|
||||
u32 op;
|
||||
|
||||
for (i = 0; insn_table[i].opcode != insn_invalid; i++)
|
||||
if (insn_table[i].opcode == opc) {
|
||||
ip = &insn_table[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ip || (opc == insn_daddiu && r4k_daddiu_bug()))
|
||||
panic("Unsupported Micro-assembler instruction %d", opc);
|
||||
|
||||
op = ip->match;
|
||||
va_start(ap, opc);
|
||||
if (ip->fields & RS)
|
||||
op |= build_rs(va_arg(ap, u32));
|
||||
if (ip->fields & RT)
|
||||
op |= build_rt(va_arg(ap, u32));
|
||||
if (ip->fields & RD)
|
||||
op |= build_rd(va_arg(ap, u32));
|
||||
if (ip->fields & RE)
|
||||
op |= build_re(va_arg(ap, u32));
|
||||
if (ip->fields & SIMM)
|
||||
op |= build_simm(va_arg(ap, s32));
|
||||
if (ip->fields & UIMM)
|
||||
op |= build_uimm(va_arg(ap, u32));
|
||||
if (ip->fields & BIMM)
|
||||
op |= build_bimm(va_arg(ap, s32));
|
||||
if (ip->fields & JIMM)
|
||||
op |= build_jimm(va_arg(ap, u32));
|
||||
if (ip->fields & FUNC)
|
||||
op |= build_func(va_arg(ap, u32));
|
||||
if (ip->fields & SET)
|
||||
op |= build_set(va_arg(ap, u32));
|
||||
if (ip->fields & SCIMM)
|
||||
op |= build_scimm(va_arg(ap, u32));
|
||||
va_end(ap);
|
||||
|
||||
**buf = op;
|
||||
(*buf)++;
|
||||
}
|
||||
|
||||
static inline void __uasminit
|
||||
__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
|
||||
{
|
||||
long laddr = (long)lab->addr;
|
||||
long raddr = (long)rel->addr;
|
||||
|
||||
switch (rel->type) {
|
||||
case R_MIPS_PC16:
|
||||
*rel->addr |= build_bimm(laddr - (raddr + 4));
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("Unsupported Micro-assembler relocation %d",
|
||||
rel->type);
|
||||
}
|
||||
}
|
@@ -10,17 +10,9 @@
|
||||
* Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer
|
||||
* Copyright (C) 2005, 2007 Maciej W. Rozycki
|
||||
* Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
|
||||
* Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/inst.h>
|
||||
#include <asm/elf.h>
|
||||
#include <asm/bugs.h>
|
||||
#include <asm/uasm.h>
|
||||
|
||||
enum fields {
|
||||
RS = 0x001,
|
||||
RT = 0x002,
|
||||
@@ -37,10 +29,6 @@ enum fields {
|
||||
|
||||
#define OP_MASK 0x3f
|
||||
#define OP_SH 26
|
||||
#define RS_MASK 0x1f
|
||||
#define RS_SH 21
|
||||
#define RT_MASK 0x1f
|
||||
#define RT_SH 16
|
||||
#define RD_MASK 0x1f
|
||||
#define RD_SH 11
|
||||
#define RE_MASK 0x1f
|
||||
@@ -53,8 +41,6 @@ enum fields {
|
||||
#define FUNC_SH 0
|
||||
#define SET_MASK 0x7
|
||||
#define SET_SH 0
|
||||
#define SCIMM_MASK 0xfffff
|
||||
#define SCIMM_SH 6
|
||||
|
||||
enum opcode {
|
||||
insn_invalid,
|
||||
@@ -77,85 +63,6 @@ struct insn {
|
||||
enum fields fields;
|
||||
};
|
||||
|
||||
/* This macro sets the non-variable bits of an instruction. */
|
||||
#define M(a, b, c, d, e, f) \
|
||||
((a) << OP_SH \
|
||||
| (b) << RS_SH \
|
||||
| (c) << RT_SH \
|
||||
| (d) << RD_SH \
|
||||
| (e) << RE_SH \
|
||||
| (f) << FUNC_SH)
|
||||
|
||||
static struct insn insn_table[] __uasminitdata = {
|
||||
{ insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
|
||||
{ insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
|
||||
{ insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
|
||||
{ insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||
{ insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||
{ insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||
{ insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||
{ insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
|
||||
{ insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM },
|
||||
{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
|
||||
{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
|
||||
{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||
{ insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
|
||||
{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
|
||||
{ insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
|
||||
{ insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
|
||||
{ insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
|
||||
{ insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE },
|
||||
{ insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE },
|
||||
{ insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE },
|
||||
{ insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE },
|
||||
{ insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE },
|
||||
{ insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE },
|
||||
{ insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
|
||||
{ insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
|
||||
{ insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 },
|
||||
{ insn_ext, M(spec3_op, 0, 0, 0, 0, ext_op), RS | RT | RD | RE },
|
||||
{ insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE },
|
||||
{ insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
|
||||
{ insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM },
|
||||
{ insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
|
||||
{ insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS },
|
||||
{ insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
|
||||
{ insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM },
|
||||
{ insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
|
||||
{ insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET},
|
||||
{ insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET},
|
||||
{ insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
|
||||
{ insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD },
|
||||
{ insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 },
|
||||
{ insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE },
|
||||
{ insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE },
|
||||
{ insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE },
|
||||
{ insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE },
|
||||
{ insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD },
|
||||
{ insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||
{ insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
|
||||
{ insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 },
|
||||
{ insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 },
|
||||
{ insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 },
|
||||
{ insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 },
|
||||
{ insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
|
||||
{ insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD },
|
||||
{ insn_invalid, 0, 0 }
|
||||
};
|
||||
|
||||
#undef M
|
||||
|
||||
static inline __uasminit u32 build_rs(u32 arg)
|
||||
{
|
||||
WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n");
|
||||
@@ -199,24 +106,6 @@ static inline __uasminit u32 build_uimm(u32 arg)
|
||||
return arg & IMM_MASK;
|
||||
}
|
||||
|
||||
static inline __uasminit u32 build_bimm(s32 arg)
|
||||
{
|
||||
WARN(arg > 0x1ffff || arg < -0x20000,
|
||||
KERN_WARNING "Micro-assembler field overflow\n");
|
||||
|
||||
WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
|
||||
|
||||
return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
|
||||
}
|
||||
|
||||
static inline __uasminit u32 build_jimm(u32 arg)
|
||||
{
|
||||
WARN(arg & ~(JIMM_MASK << 2),
|
||||
KERN_WARNING "Micro-assembler field overflow\n");
|
||||
|
||||
return (arg >> 2) & JIMM_MASK;
|
||||
}
|
||||
|
||||
static inline __uasminit u32 build_scimm(u32 arg)
|
||||
{
|
||||
WARN(arg & ~SCIMM_MASK,
|
||||
@@ -239,55 +128,7 @@ static inline __uasminit u32 build_set(u32 arg)
|
||||
return arg & SET_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* The order of opcode arguments is implicitly left to right,
|
||||
* starting with RS and ending with FUNC or IMM.
|
||||
*/
|
||||
static void __uasminit build_insn(u32 **buf, enum opcode opc, ...)
|
||||
{
|
||||
struct insn *ip = NULL;
|
||||
unsigned int i;
|
||||
va_list ap;
|
||||
u32 op;
|
||||
|
||||
for (i = 0; insn_table[i].opcode != insn_invalid; i++)
|
||||
if (insn_table[i].opcode == opc) {
|
||||
ip = &insn_table[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ip || (opc == insn_daddiu && r4k_daddiu_bug()))
|
||||
panic("Unsupported Micro-assembler instruction %d", opc);
|
||||
|
||||
op = ip->match;
|
||||
va_start(ap, opc);
|
||||
if (ip->fields & RS)
|
||||
op |= build_rs(va_arg(ap, u32));
|
||||
if (ip->fields & RT)
|
||||
op |= build_rt(va_arg(ap, u32));
|
||||
if (ip->fields & RD)
|
||||
op |= build_rd(va_arg(ap, u32));
|
||||
if (ip->fields & RE)
|
||||
op |= build_re(va_arg(ap, u32));
|
||||
if (ip->fields & SIMM)
|
||||
op |= build_simm(va_arg(ap, s32));
|
||||
if (ip->fields & UIMM)
|
||||
op |= build_uimm(va_arg(ap, u32));
|
||||
if (ip->fields & BIMM)
|
||||
op |= build_bimm(va_arg(ap, s32));
|
||||
if (ip->fields & JIMM)
|
||||
op |= build_jimm(va_arg(ap, u32));
|
||||
if (ip->fields & FUNC)
|
||||
op |= build_func(va_arg(ap, u32));
|
||||
if (ip->fields & SET)
|
||||
op |= build_set(va_arg(ap, u32));
|
||||
if (ip->fields & SCIMM)
|
||||
op |= build_scimm(va_arg(ap, u32));
|
||||
va_end(ap);
|
||||
|
||||
**buf = op;
|
||||
(*buf)++;
|
||||
}
|
||||
static void __uasminit build_insn(u32 **buf, enum opcode opc, ...);
|
||||
|
||||
#define I_u1u2u3(op) \
|
||||
Ip_u1u2u3(op) \
|
||||
@@ -445,7 +286,7 @@ I_u3u1u2(_ldx)
|
||||
|
||||
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||
#include <asm/octeon/octeon.h>
|
||||
void __uasminit uasm_i_pref(u32 **buf, unsigned int a, signed int b,
|
||||
void __uasminit ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b,
|
||||
unsigned int c)
|
||||
{
|
||||
if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) && a <= 24 && a != 5)
|
||||
@@ -457,21 +298,21 @@ void __uasminit uasm_i_pref(u32 **buf, unsigned int a, signed int b,
|
||||
else
|
||||
build_insn(buf, insn_pref, c, a, b);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_i_pref);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_i_pref));
|
||||
#else
|
||||
I_u2s3u1(_pref)
|
||||
#endif
|
||||
|
||||
/* Handle labels. */
|
||||
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)
|
||||
{
|
||||
(*lab)->addr = addr;
|
||||
(*lab)->lab = lid;
|
||||
(*lab)++;
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_build_label);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_build_label));
|
||||
|
||||
int __uasminit uasm_in_compat_space_p(long addr)
|
||||
int __uasminit ISAFUNC(uasm_in_compat_space_p)(long addr)
|
||||
{
|
||||
/* Is this address in 32bit compat space? */
|
||||
#ifdef CONFIG_64BIT
|
||||
@@ -480,7 +321,7 @@ int __uasminit uasm_in_compat_space_p(long addr)
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_in_compat_space_p);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_in_compat_space_p));
|
||||
|
||||
static int __uasminit uasm_rel_highest(long val)
|
||||
{
|
||||
@@ -500,77 +341,66 @@ static int __uasminit uasm_rel_higher(long val)
|
||||
#endif
|
||||
}
|
||||
|
||||
int __uasminit uasm_rel_hi(long val)
|
||||
int __uasminit ISAFUNC(uasm_rel_hi)(long val)
|
||||
{
|
||||
return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000;
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_rel_hi);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_hi));
|
||||
|
||||
int __uasminit uasm_rel_lo(long val)
|
||||
int __uasminit ISAFUNC(uasm_rel_lo)(long val)
|
||||
{
|
||||
return ((val & 0xffff) ^ 0x8000) - 0x8000;
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_rel_lo);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_lo));
|
||||
|
||||
void __uasminit UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr)
|
||||
void __uasminit ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr)
|
||||
{
|
||||
if (!uasm_in_compat_space_p(addr)) {
|
||||
uasm_i_lui(buf, rs, uasm_rel_highest(addr));
|
||||
if (!ISAFUNC(uasm_in_compat_space_p)(addr)) {
|
||||
ISAFUNC(uasm_i_lui)(buf, rs, uasm_rel_highest(addr));
|
||||
if (uasm_rel_higher(addr))
|
||||
uasm_i_daddiu(buf, rs, rs, uasm_rel_higher(addr));
|
||||
if (uasm_rel_hi(addr)) {
|
||||
uasm_i_dsll(buf, rs, rs, 16);
|
||||
uasm_i_daddiu(buf, rs, rs, uasm_rel_hi(addr));
|
||||
uasm_i_dsll(buf, rs, rs, 16);
|
||||
ISAFUNC(uasm_i_daddiu)(buf, rs, rs, uasm_rel_higher(addr));
|
||||
if (ISAFUNC(uasm_rel_hi(addr))) {
|
||||
ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16);
|
||||
ISAFUNC(uasm_i_daddiu)(buf, rs, rs,
|
||||
ISAFUNC(uasm_rel_hi)(addr));
|
||||
ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16);
|
||||
} else
|
||||
uasm_i_dsll32(buf, rs, rs, 0);
|
||||
ISAFUNC(uasm_i_dsll32)(buf, rs, rs, 0);
|
||||
} else
|
||||
uasm_i_lui(buf, rs, uasm_rel_hi(addr));
|
||||
ISAFUNC(uasm_i_lui)(buf, rs, ISAFUNC(uasm_rel_hi(addr)));
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(UASM_i_LA_mostly);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA_mostly));
|
||||
|
||||
void __uasminit UASM_i_LA(u32 **buf, unsigned int rs, long addr)
|
||||
void __uasminit ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr)
|
||||
{
|
||||
UASM_i_LA_mostly(buf, rs, addr);
|
||||
if (uasm_rel_lo(addr)) {
|
||||
if (!uasm_in_compat_space_p(addr))
|
||||
uasm_i_daddiu(buf, rs, rs, uasm_rel_lo(addr));
|
||||
ISAFUNC(UASM_i_LA_mostly)(buf, rs, addr);
|
||||
if (ISAFUNC(uasm_rel_lo(addr))) {
|
||||
if (!ISAFUNC(uasm_in_compat_space_p)(addr))
|
||||
ISAFUNC(uasm_i_daddiu)(buf, rs, rs,
|
||||
ISAFUNC(uasm_rel_lo(addr)));
|
||||
else
|
||||
uasm_i_addiu(buf, rs, rs, uasm_rel_lo(addr));
|
||||
ISAFUNC(uasm_i_addiu)(buf, rs, rs,
|
||||
ISAFUNC(uasm_rel_lo(addr)));
|
||||
}
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(UASM_i_LA);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA));
|
||||
|
||||
/* Handle relocations. */
|
||||
void __uasminit
|
||||
uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid)
|
||||
ISAFUNC(uasm_r_mips_pc16)(struct uasm_reloc **rel, u32 *addr, int lid)
|
||||
{
|
||||
(*rel)->addr = addr;
|
||||
(*rel)->type = R_MIPS_PC16;
|
||||
(*rel)->lab = lid;
|
||||
(*rel)++;
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_r_mips_pc16);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_r_mips_pc16));
|
||||
|
||||
static inline void __uasminit
|
||||
__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
|
||||
{
|
||||
long laddr = (long)lab->addr;
|
||||
long raddr = (long)rel->addr;
|
||||
|
||||
switch (rel->type) {
|
||||
case R_MIPS_PC16:
|
||||
*rel->addr |= build_bimm(laddr - (raddr + 4));
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("Unsupported Micro-assembler relocation %d",
|
||||
rel->type);
|
||||
}
|
||||
}
|
||||
__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab);
|
||||
|
||||
void __uasminit
|
||||
uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
|
||||
ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel, struct uasm_label *lab)
|
||||
{
|
||||
struct uasm_label *l;
|
||||
|
||||
@@ -579,40 +409,40 @@ uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
|
||||
if (rel->lab == l->lab)
|
||||
__resolve_relocs(rel, l);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_resolve_relocs);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_resolve_relocs));
|
||||
|
||||
void __uasminit
|
||||
uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off)
|
||||
ISAFUNC(uasm_move_relocs)(struct uasm_reloc *rel, u32 *first, u32 *end, long off)
|
||||
{
|
||||
for (; rel->lab != UASM_LABEL_INVALID; rel++)
|
||||
if (rel->addr >= first && rel->addr < end)
|
||||
rel->addr += off;
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_move_relocs);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_relocs));
|
||||
|
||||
void __uasminit
|
||||
uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off)
|
||||
ISAFUNC(uasm_move_labels)(struct uasm_label *lab, u32 *first, u32 *end, long off)
|
||||
{
|
||||
for (; lab->lab != UASM_LABEL_INVALID; lab++)
|
||||
if (lab->addr >= first && lab->addr < end)
|
||||
lab->addr += off;
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_move_labels);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_labels));
|
||||
|
||||
void __uasminit
|
||||
uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first,
|
||||
ISAFUNC(uasm_copy_handler)(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first,
|
||||
u32 *end, u32 *target)
|
||||
{
|
||||
long off = (long)(target - first);
|
||||
|
||||
memcpy(target, first, (end - first) * sizeof(u32));
|
||||
|
||||
uasm_move_relocs(rel, first, end, off);
|
||||
uasm_move_labels(lab, first, end, off);
|
||||
ISAFUNC(uasm_move_relocs(rel, first, end, off));
|
||||
ISAFUNC(uasm_move_labels(lab, first, end, off));
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_copy_handler);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_copy_handler));
|
||||
|
||||
int __uasminit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr)
|
||||
int __uasminit ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr)
|
||||
{
|
||||
for (; rel->lab != UASM_LABEL_INVALID; rel++) {
|
||||
if (rel->addr == addr
|
||||
@@ -623,88 +453,88 @@ int __uasminit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr)
|
||||
|
||||
return 0;
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_insn_has_bdelay);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_insn_has_bdelay));
|
||||
|
||||
/* Convenience functions for labeled branches. */
|
||||
void __uasminit
|
||||
uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
ISAFUNC(uasm_il_bltz)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
{
|
||||
uasm_r_mips_pc16(r, *p, lid);
|
||||
uasm_i_bltz(p, reg, 0);
|
||||
ISAFUNC(uasm_i_bltz)(p, reg, 0);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_il_bltz);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bltz));
|
||||
|
||||
void __uasminit
|
||||
uasm_il_b(u32 **p, struct uasm_reloc **r, int lid)
|
||||
ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid)
|
||||
{
|
||||
uasm_r_mips_pc16(r, *p, lid);
|
||||
uasm_i_b(p, 0);
|
||||
ISAFUNC(uasm_i_b)(p, 0);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_il_b);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b));
|
||||
|
||||
void __uasminit
|
||||
uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
{
|
||||
uasm_r_mips_pc16(r, *p, lid);
|
||||
uasm_i_beqz(p, reg, 0);
|
||||
ISAFUNC(uasm_i_beqz)(p, reg, 0);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_il_beqz);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqz));
|
||||
|
||||
void __uasminit
|
||||
uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
ISAFUNC(uasm_il_beqzl)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
{
|
||||
uasm_r_mips_pc16(r, *p, lid);
|
||||
uasm_i_beqzl(p, reg, 0);
|
||||
ISAFUNC(uasm_i_beqzl)(p, reg, 0);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_il_beqzl);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqzl));
|
||||
|
||||
void __uasminit
|
||||
uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1,
|
||||
ISAFUNC(uasm_il_bne)(u32 **p, struct uasm_reloc **r, unsigned int reg1,
|
||||
unsigned int reg2, int lid)
|
||||
{
|
||||
uasm_r_mips_pc16(r, *p, lid);
|
||||
uasm_i_bne(p, reg1, reg2, 0);
|
||||
ISAFUNC(uasm_i_bne)(p, reg1, reg2, 0);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_il_bne);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bne));
|
||||
|
||||
void __uasminit
|
||||
uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
ISAFUNC(uasm_il_bnez)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
{
|
||||
uasm_r_mips_pc16(r, *p, lid);
|
||||
uasm_i_bnez(p, reg, 0);
|
||||
ISAFUNC(uasm_i_bnez)(p, reg, 0);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_il_bnez);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bnez));
|
||||
|
||||
void __uasminit
|
||||
uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
ISAFUNC(uasm_il_bgezl)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
{
|
||||
uasm_r_mips_pc16(r, *p, lid);
|
||||
uasm_i_bgezl(p, reg, 0);
|
||||
ISAFUNC(uasm_i_bgezl)(p, reg, 0);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_il_bgezl);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgezl));
|
||||
|
||||
void __uasminit
|
||||
uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
ISAFUNC(uasm_il_bgez)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
|
||||
{
|
||||
uasm_r_mips_pc16(r, *p, lid);
|
||||
uasm_i_bgez(p, reg, 0);
|
||||
ISAFUNC(uasm_i_bgez)(p, reg, 0);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_il_bgez);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgez));
|
||||
|
||||
void __uasminit
|
||||
uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg,
|
||||
ISAFUNC(uasm_il_bbit0)(u32 **p, struct uasm_reloc **r, unsigned int reg,
|
||||
unsigned int bit, int lid)
|
||||
{
|
||||
uasm_r_mips_pc16(r, *p, lid);
|
||||
uasm_i_bbit0(p, reg, bit, 0);
|
||||
ISAFUNC(uasm_i_bbit0)(p, reg, bit, 0);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_il_bbit0);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit0));
|
||||
|
||||
void __uasminit
|
||||
uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg,
|
||||
ISAFUNC(uasm_il_bbit1)(u32 **p, struct uasm_reloc **r, unsigned int reg,
|
||||
unsigned int bit, int lid)
|
||||
{
|
||||
uasm_r_mips_pc16(r, *p, lid);
|
||||
uasm_i_bbit1(p, reg, bit, 0);
|
||||
ISAFUNC(uasm_i_bbit1)(p, reg, bit, 0);
|
||||
}
|
||||
UASM_EXPORT_SYMBOL(uasm_il_bbit1);
|
||||
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit1));
|
||||
|
Reference in New Issue
Block a user