#ifndef _MIPS_ASM_H
#define _MIPS_ASM_H
#include <sys/cdefs.h>
#include <mips/regdef.h>
#if defined(_KERNEL_OPT)
#include "opt_gprof.h"
#include "opt_multiprocessor.h"
#endif
#ifdef __ASSEMBLER__
#define __BIT(n) (1 << (n))
#define __BITS(hi,lo) ((~((~0)<<((hi)+1)))&((~0)<<(lo)))
#define __LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
#define __SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask))
#define __SHIFTIN(__x, __mask) ((__x) * __LOWEST_SET_BIT(__mask))
#endif
#ifndef GPROF
#define _MIPS_ASM_MCOUNT(x)
#else
#if defined(__mips_o32)
#define _MIPS_ASM_MCOUNT(x) \
.set push; \
.set noreorder; \
.set noat; \
subu sp,16; \
sw t9,12(sp); \
move AT,ra; \
lui t9,%hi(_mcount); \
addiu t9,t9,%lo(_mcount); \
jalr t9; \
nop; \
lw t9,4(sp); \
addiu sp,8; \
addiu t9,40; \
.set pop;
#elif defined(__mips_o64)
# error yeahnah
#else
#ifdef __mips_abicalls
#if defined(__mips_n32)
#define _MIPS_ASM_MCOUNT(x) \
.set push; \
.set noreorder; \
.set noat; \
subu sp,16; \
sw t9,8(sp); \
move AT,ra; \
lui t9,%hi(_mcount); \
addiu t9,t9,%lo(_mcount); \
jalr t9; \
nop; \
lw t9,8(sp); \
addiu sp,16; \
.set pop;
#else
#define _MIPS_ASM_MCOUNT(x) \
.set push; \
.set noreorder; \
.set noat; \
dsubu sp,16; \
sd gp,0(sp); \
sd t9,8(sp); \
move AT,ra; \
lui gp,%hi(%neg(%gp_rel(x))); \
daddiu gp,%lo(%neg(%gp_rel(x))); \
daddu gp,gp,t9; \
ld t9,%call16(_mcount)(gp); \
jalr t9; \
nop; \
ld gp,0(sp); \
ld t9,8(sp); \
daddiu sp,16; \
.set pop;
#endif
#else
#define _MIPS_ASM_MCOUNT(x) \
.set push; \
.set noreorder; \
.set noat; \
move AT,ra; \
jal _mcount; \
nop; \
.set pop;
#endif
#endif
#endif
#ifdef USE_AENT
#define AENT(x) \
.aent x, 0
#else
#define AENT(x)
#endif
#define WEAK_ALIAS(alias,sym) \
.weak alias; \
alias = sym
#define STRONG_ALIAS(alias,sym) \
.globl alias; \
alias = sym
#define WARN_REFERENCES(sym,msg) \
.pushsection __CONCAT(.gnu.warning.,sym); \
.ascii msg; \
.popsection
#define STATIC_LEAF_NOPROFILE(x) \
.ent _C_LABEL(x); \
_C_LABEL(x): ; \
.frame sp, 0, ra
#define LEAF_NOPROFILE(x) \
.globl _C_LABEL(x); \
STATIC_LEAF_NOPROFILE(x)
#define STATIC_LEAF(x) \
STATIC_LEAF_NOPROFILE(x); \
_MIPS_ASM_MCOUNT(x)
#define LEAF(x) \
LEAF_NOPROFILE(x); \
_MIPS_ASM_MCOUNT(x)
#define STATIC_XLEAF(x) \
AENT (_C_LABEL(x)); \
_C_LABEL(x):
#define XLEAF(x) \
.globl _C_LABEL(x); \
STATIC_XLEAF(x)
#define STATIC_NESTED_NOPROFILE(x, fsize, retpc) \
.ent _C_LABEL(x); \
.type _C_LABEL(x), @function; \
_C_LABEL(x): ; \
.frame sp, fsize, retpc
#define NESTED_NOPROFILE(x, fsize, retpc) \
.globl _C_LABEL(x); \
STATIC_NESTED_NOPROFILE(x, fsize, retpc)
#define NESTED(x, fsize, retpc) \
NESTED_NOPROFILE(x, fsize, retpc); \
_MIPS_ASM_MCOUNT(x)
#define STATIC_NESTED(x, fsize, retpc) \
STATIC_NESTED_NOPROFILE(x, fsize, retpc); \
_MIPS_ASM_MCOUNT(x)
#define XNESTED(x) \
.globl _C_LABEL(x); \
AENT (_C_LABEL(x)); \
_C_LABEL(x):
#define END(x) \
.end _C_LABEL(x); \
.size _C_LABEL(x), . - _C_LABEL(x)
#define IMPORT(sym, size) \
.extern _C_LABEL(sym),size
#define EXPORT(x) \
.globl _C_LABEL(x); \
_C_LABEL(x):
#define EXPORT_OBJECT(x) \
EXPORT(x); \
.type _C_LABEL(x), @object;
#define VECTOR(x, regmask) \
.ent _C_LABEL(x); \
EXPORT(x); \
#define VECTOR_END(x) \
EXPORT(__CONCAT(x,_end)); \
END(x); \
.org _C_LABEL(x) + 0x80
#define PANIC(msg) \
PTR_LA a0, 9f; \
jal _C_LABEL(panic); \
nop; \
MSG(msg)
#define PRINTF(msg) \
PTR_LA a0, 9f; \
jal _C_LABEL(printf); \
nop; \
MSG(msg)
#define MSG(msg) \
.rdata; \
9: .asciz msg; \
.text
#define ASMSTR(str) \
.asciz str; \
.align 3
#ifdef _NETBSD_REVISIONID
#define RCSID(x) .pushsection ".ident","MS",@progbits,1; \
.asciz x; \
.ascii "$"; .ascii "NetBSD: "; .ascii __FILE__; \
.ascii " "; .ascii _NETBSD_REVISIONID; \
.asciz " $"; \
.popsection
#else
#define RCSID(x) .pushsection ".ident","MS",@progbits,1; \
.asciz x; \
.popsection
#endif
#define ALEAF(x) XLEAF(x)
#define NLEAF(x) LEAF_NOPROFILE(x)
#define NON_LEAF(x, fsize, retpc) NESTED(x, fsize, retpc)
#define NNON_LEAF(x, fsize, retpc) NESTED_NOPROFILE(x, fsize, retpc)
#if defined(__mips_o32)
#define SZREG 4
#else
#define SZREG 8
#endif
#if defined(__mips_o32) || defined(__mips_o64)
#define ALSK 7
#define ALMASK -7
#define SZFPREG 4
#define FP_L lwc1
#define FP_S swc1
#else
#define ALSK 15
#define ALMASK -15
#define SZFPREG 8
#define FP_L ldc1
#define FP_S sdc1
#endif
#if defined(__mips_o32) || defined(__mips_o64)
#define CALLFRAME_SIZ (SZREG * (4 + 2))
#define CALLFRAME_S0 0
#elif defined(__mips_n32) || defined(__mips_n64)
#define CALLFRAME_SIZ (SZREG * 4)
#define CALLFRAME_S0 (CALLFRAME_SIZ - 4 * SZREG)
#endif
#ifndef _KERNEL
#define CALLFRAME_GP (CALLFRAME_SIZ - 3 * SZREG)
#endif
#define CALLFRAME_SP (CALLFRAME_SIZ - 2 * SZREG)
#define CALLFRAME_RA (CALLFRAME_SIZ - 1 * SZREG)
#ifdef __mips_o32
#define PTR_ADD add
#define PTR_ADDI addi
#define PTR_ADDU addu
#define PTR_ADDIU addiu
#define PTR_SUB subu
#define PTR_SUBI subi
#define PTR_SUBU subu
#define PTR_SUBIU subu
#define PTR_L lw
#define PTR_LA la
#define PTR_S sw
#define PTR_SLL sll
#define PTR_SLLV sllv
#define PTR_SRL srl
#define PTR_SRLV srlv
#define PTR_SRA sra
#define PTR_SRAV srav
#define PTR_LL ll
#define PTR_SC sc
#define PTR_WORD .word
#define PTR_SCALESHIFT 2
#else
#define PTR_ADD dadd
#define PTR_ADDI daddi
#define PTR_ADDU daddu
#define PTR_ADDIU daddiu
#define PTR_SUB dsubu
#define PTR_SUBI dsubi
#define PTR_SUBU dsubu
#define PTR_SUBIU dsubu
#ifdef __mips_n32
#define PTR_L lw
#define PTR_LL ll
#define PTR_SC sc
#define PTR_S sw
#define PTR_SCALESHIFT 2
#define PTR_WORD .word
#else
#define PTR_L ld
#define PTR_LL lld
#define PTR_SC scd
#define PTR_S sd
#define PTR_SCALESHIFT 3
#define PTR_WORD .dword
#endif
#define PTR_LA dla
#define PTR_SLL dsll
#define PTR_SLLV dsllv
#define PTR_SRL dsrl
#define PTR_SRLV dsrlv
#define PTR_SRA dsra
#define PTR_SRAV dsrav
#endif
#if _MIPS_SZINT == 32
#define INT_ADD add
#define INT_ADDI addi
#define INT_ADDU addu
#define INT_ADDIU addiu
#define INT_SUB subu
#define INT_SUBI subi
#define INT_SUBU subu
#define INT_SUBIU subu
#define INT_L lw
#define INT_LA la
#define INT_S sw
#define INT_SLL sll
#define INT_SLLV sllv
#define INT_SRL srl
#define INT_SRLV srlv
#define INT_SRA sra
#define INT_SRAV srav
#define INT_LL ll
#define INT_SC sc
#define INT_WORD .word
#define INT_SCALESHIFT 2
#else
#define INT_ADD dadd
#define INT_ADDI daddi
#define INT_ADDU daddu
#define INT_ADDIU daddiu
#define INT_SUB dsubu
#define INT_SUBI dsubi
#define INT_SUBU dsubu
#define INT_SUBIU dsubu
#define INT_L ld
#define INT_LA dla
#define INT_S sd
#define INT_SLL dsll
#define INT_SLLV dsllv
#define INT_SRL dsrl
#define INT_SRLV dsrlv
#define INT_SRA dsra
#define INT_SRAV dsrav
#define INT_LL lld
#define INT_SC scd
#define INT_WORD .dword
#define INT_SCALESHIFT 3
#endif
#if _MIPS_SZLONG == 32
#define LONG_ADD add
#define LONG_ADDI addi
#define LONG_ADDU addu
#define LONG_ADDIU addiu
#define LONG_SUB subu
#define LONG_SUBI subi
#define LONG_SUBU subu
#define LONG_SUBIU subu
#define LONG_L lw
#define LONG_LA la
#define LONG_S sw
#define LONG_SLL sll
#define LONG_SLLV sllv
#define LONG_SRL srl
#define LONG_SRLV srlv
#define LONG_SRA sra
#define LONG_SRAV srav
#define LONG_LL ll
#define LONG_SC sc
#define LONG_WORD .word
#define LONG_SCALESHIFT 2
#else
#define LONG_ADD dadd
#define LONG_ADDI daddi
#define LONG_ADDU daddu
#define LONG_ADDIU daddiu
#define LONG_SUB dsubu
#define LONG_SUBI dsubi
#define LONG_SUBU dsubu
#define LONG_SUBIU dsubu
#define LONG_L ld
#define LONG_LA dla
#define LONG_S sd
#define LONG_SLL dsll
#define LONG_SLLV dsllv
#define LONG_SRL dsrl
#define LONG_SRLV dsrlv
#define LONG_SRA dsra
#define LONG_SRAV dsrav
#define LONG_LL lld
#define LONG_SC scd
#define LONG_WORD .dword
#define LONG_SCALESHIFT 3
#endif
#if SZREG == 4
#define REG_L lw
#define REG_S sw
#define REG_LI li
#define REG_ADDU addu
#define REG_SLL sll
#define REG_SLLV sllv
#define REG_SRL srl
#define REG_SRLV srlv
#define REG_SRA sra
#define REG_SRAV srav
#define REG_LL ll
#define REG_SC sc
#define REG_SCALESHIFT 2
#else
#define REG_L ld
#define REG_S sd
#define REG_LI dli
#define REG_ADDU daddu
#define REG_SLL dsll
#define REG_SLLV dsllv
#define REG_SRL dsrl
#define REG_SRLV dsrlv
#define REG_SRA dsra
#define REG_SRAV dsrav
#define REG_LL lld
#define REG_SC scd
#define REG_SCALESHIFT 3
#endif
#if (MIPS1 + MIPS2) > 0
#define NOP_L nop
#else
#define NOP_L
#endif
#if defined(MULTIPROCESSOR) && defined(__OCTEON__)
#define LLSCSYNC
#define BDSYNC sync
#define BDSYNC_ACQ nop
#define SYNC_ACQ
#define SYNC_REL sync 4
#define BDSYNC_PLUNGER sync 4
#define SYNC_PLUNGER sync 4
#elif defined(MULTIPROCESSOR) && (__mips >= 3 || !defined(__mips_o32))
#define LLSCSYNC
#define BDSYNC sync
#define BDSYNC_ACQ sync
#define SYNC_ACQ sync
#define SYNC_REL sync
#define BDSYNC_PLUNGER nop
#define SYNC_PLUNGER
#else
#define LLSCSYNC
#define BDSYNC nop
#define BDSYNC_ACQ nop
#define SYNC_ACQ
#define SYNC_REL
#define BDSYNC_PLUNGER nop
#define SYNC_PLUNGER
#endif
#ifdef MULTIPROCESSOR
#define SYNC_DEKKER sync
#else
#define SYNC_DEKKER
#endif
#define SYNC_PRODUCER SYNC_REL
#define SYNC_CONSUMER SYNC_ACQ
#if defined(MIPS1) || defined(MIPS2) || defined(MIPS3)
#define MFC0_HAZARD sll $0,$0,1
#else
#define MFC0_HAZARD
#endif
#if _MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2 || \
_MIPS_ISA == _MIPS_ISA_MIPS32
#define MFC0 mfc0
#define MTC0 mtc0
#endif
#if _MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4 || \
_MIPS_ISA == _MIPS_ISA_MIPS64
#define MFC0 dmfc0
#define MTC0 dmtc0
#endif
#if defined(__mips_o32) || defined(__mips_o64)
#ifdef __mips_abicalls
#define CPRESTORE(r) .cprestore r
#define CPLOAD(r) .cpload r
#else
#define CPRESTORE(r)
#define CPLOAD(r)
#endif
#define SETUP_GP \
.set push; \
.set noreorder; \
.cpload t9; \
.set pop
#define SETUP_GPX(r) \
.set push; \
.set noreorder; \
move r,ra; \
bal 7f; \
nop; \
7: .cpload ra; \
move ra,r; \
.set pop
#define SETUP_GPX_L(r,lbl) \
.set push; \
.set noreorder; \
move r,ra; \
bal lbl; \
nop; \
lbl: .cpload ra; \
move ra,r; \
.set pop
#define SAVE_GP(x) .cprestore x
#define SETUP_GP64(a,b)
#define SETUP_GP64_R(a,b)
#define SETUP_GPX64(a,b)
#define SETUP_GPX64_L(a,b,c)
#define RESTORE_GP64
#define USE_ALT_CP(a)
#endif
#if defined(__mips_o32) || defined(__mips_o64)
#define REG_PROLOGUE .set push
#define REG_EPILOGUE .set pop
#endif
#if defined(__mips_n32) || defined(__mips_n64)
#define REG_PROLOGUE .set push ; .set mips3
#define REG_EPILOGUE .set pop
#endif
#if defined(__mips_n32) || defined(__mips_n64)
#define SETUP_GP
#define SETUP_GPX(r)
#define SETUP_GPX_L(r,lbl)
#define SAVE_GP(x)
#define SETUP_GP64(a,b) .cpsetup t9, a, b
#define SETUP_GPX64(a,b) \
.set push; \
move b,ra; \
.set noreorder; \
bal 7f; \
nop; \
7: .set pop; \
.cpsetup ra, a, 7b; \
move ra,b
#define SETUP_GPX64_L(a,b,c) \
.set push; \
move b,ra; \
.set noreorder; \
bal c; \
nop; \
c: .set pop; \
.cpsetup ra, a, c; \
move ra,b
#define RESTORE_GP64 .cpreturn
#define USE_ALT_CP(a) .cplocal a
#endif
#ifdef MIPS_DYNAMIC_STATUS_MASK
#define DYNAMIC_STATUS_MASK(sr,scratch) \
lw scratch, mips_dynamic_status_mask; \
and sr, sr, scratch
#define DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1) \
ori sr, (MIPS_INT_MASK | MIPS_SR_INT_IE); \
DYNAMIC_STATUS_MASK(sr,scratch1)
#else
#define DYNAMIC_STATUS_MASK(sr,scratch)
#define DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1)
#endif
#define LOG2_MIPS_LOCK_RAS_SIZE 8
#define MIPS_LOCK_RAS_SIZE 256
#define CPUVAR(off) _C_LABEL(cpu_info_store)+__CONCAT(CPU_INFO_,off)
#endif