else()
set(DISABLE_DLLMAP 1)
endif()
-if (TARGET_BROWSER)
- # sys/errno.h exists, but just emits a warning and includes errno.h
- unset(HAVE_SYS_ERRNO_H)
-endif()
### End of OS specific checks
include_directories("${CLR_SRC_NATIVE_DIR}")
/* Have mktemp */
#cmakedefine HAVE_MKTEMP 1
-/* Define to 1 if you have the <sys/errno.h> header file. */
-#cmakedefine HAVE_SYS_ERRNO_H 1
-
/* Define to 1 if you have the <sys/sendfile.h> header file. */
#cmakedefine HAVE_SYS_SENDFILE_H 1
/* Define to 1 if `st_atimespec' is a member of `struct stat'. */
#cmakedefine HAVE_STRUCT_STAT_ST_ATIMESPEC 1
-/* Define to 1 if `kp_proc' is a member of `struct kinfo_proc'. */
-#cmakedefine HAVE_STRUCT_KINFO_PROC_KP_PROC 1
-
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H 1
#cmakedefine TARGET_S390X 1
/* ... */
-#cmakedefine TARGET_MIPS 1
-
-/* ... */
-#cmakedefine TARGET_SPARC 1
-
-/* ... */
-#cmakedefine TARGET_SPARC64 1
-
-/* ... */
#cmakedefine HOST_WASM 1
/* ... */
/* ... */
#cmakedefine HOST_S390X 1
-/* ... */
-#cmakedefine HOST_MIPS 1
-
-/* ... */
-#cmakedefine HOST_SPARC 1
-
-/* ... */
-#cmakedefine HOST_SPARC64 1
-
/* Host is RISC-V */
#cmakedefine HOST_RISCV 1
sys/prctl.h sys/socket.h sys/utsname.h sys/select.h sys/poll.h sys/wait.h sys/resource.h
sys/ioctl.h sys/errno.h sys/sendfile.h sys/statvfs.h sys/statfs.h sys/mman.h sys/mount.h sys/time.h sys/random.h
strings.h stdint.h unistd.h signal.h setjmp.h syslog.h netdb.h utime.h semaphore.h alloca.h ucontext.h pwd.h elf.h
- gnu/lib-names.h netinet/tcp.h netinet/in.h link.h arpa/inet.h unwind.h poll.h wchar.h linux/magic.h
+ gnu/lib-names.h netinet/tcp.h netinet/in.h link.h arpa/inet.h unwind.h poll.h wchar.h
android/legacy_signal_inlines.h execinfo.h pthread.h pthread_np.h net/if.h dirent.h
CommonCrypto/CommonDigest.h dlfcn.h getopt.h pwd.h alloca.h
/usr/include/malloc.h)
gethrtime read_real_time gethostbyname gethostbyname2 getnameinfo getifaddrs
access inet_ntop Qp2getifaddrs getpid mktemp)
-if (HOST_LINUX)
- # sysctl is deprecated on Linux
+if (HOST_LINUX OR HOST_BROWSER)
+ # sysctl is deprecated on Linux and doesn't work on Browser
set(HAVE_SYS_SYSCTL_H 0)
else ()
check_include_files("sys/types.h;sys/sysctl.h" HAVE_SYS_SYSCTL_H)
check_symbol_exists(pthread_mutexattr_setprotocol "pthread.h" HAVE_DECL_PTHREAD_MUTEXATTR_SETPROTOCOL)
check_symbol_exists(CLOCK_MONOTONIC "time.h" HAVE_CLOCK_MONOTONIC)
check_symbol_exists(CLOCK_MONOTONIC_COARSE "time.h" HAVE_CLOCK_MONOTONIC_COARSE)
+
check_symbol_exists(sys_signame "signal.h" HAVE_SYSSIGNAME)
check_symbol_exists(pthread_jit_write_protect_np "pthread.h" HAVE_PTHREAD_JIT_WRITE_PROTECT_NP)
check_symbol_exists(getauxval sys/auxv.h HAVE_GETAUXVAL)
ac_check_type("struct ip_mreq" ip_mreq "netinet/in.h")
ac_check_type("clockid_t" clockid_t "sys/types.h")
-check_struct_has_member("struct kinfo_proc" kp_proc "sys/types.h;sys/param.h;sys/sysctl.h;sys/proc.h" HAVE_STRUCT_KINFO_PROC_KP_PROC)
check_struct_has_member("struct sockaddr_in" sin_len "netinet/in.h" HAVE_SOCKADDR_IN_SIN_LEN)
check_struct_has_member("struct sockaddr_in6" sin6_len "netinet/in.h" HAVE_SOCKADDR_IN6_SIN_LEN)
check_struct_has_member("struct stat" st_atim "sys/types.h;sys/stat.h;unistd.h" HAVE_STRUCT_STAT_ST_ATIM)
+++ /dev/null
-/
-/*.o
-/*.lo
-/.deps
+++ /dev/null
-#ifndef __MIPS_CODEGEN_H__
-#define __MIPS_CODEGEN_H__
-/*
- * Copyright (c) 2004 Novell, Inc
- * Author: Paolo Molaro (lupus@ximian.com)
- *
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-/* registers */
-enum {
- mips_zero,
- mips_at, /* assembler temp */
- mips_v0, /* return values */
- mips_v1,
- mips_a0, /* 4 - func arguments */
- mips_a1,
- mips_a2,
- mips_a3,
-#if _MIPS_SIM == _ABIO32
- mips_t0, /* 8 temporaries */
- mips_t1,
- mips_t2,
- mips_t3,
- mips_t4,
- mips_t5,
- mips_t6,
- mips_t7,
-#elif _MIPS_SIM == _ABIN32
- mips_a4, /* 4 more argument registers */
- mips_a5,
- mips_a6,
- mips_a7,
- mips_t0, /* 4 temporaries */
- mips_t1,
- mips_t2,
- mips_t3,
-#endif
- mips_s0, /* 16 calle saved */
- mips_s1,
- mips_s2,
- mips_s3,
- mips_s4,
- mips_s5,
- mips_s6,
- mips_s7,
- mips_t8, /* 24 temps */
- mips_t9, /* 25 temp / pic call-through register */
- mips_k0, /* 26 kernel-reserved */
- mips_k1,
- mips_gp, /* 28 */
- mips_sp, /* stack pointer */
- mips_fp, /* frame pointer */
- mips_ra /* return address */
-};
-
-/* we treat the register file as containing just doubles... */
-enum {
- mips_f0, /* return regs */
- mips_f1,
- mips_f2,
- mips_f3,
- mips_f4, /* temps */
- mips_f5,
- mips_f6,
- mips_f7,
- mips_f8,
- mips_f9,
- mips_f10,
- mips_f11,
- mips_f12, /* first arg */
- mips_f13,
- mips_f14, /* second arg */
- mips_f15,
- mips_f16, /* temps */
- mips_f17,
- mips_f18,
- mips_f19,
- mips_f20, /* callee saved */
- mips_f21,
- mips_f22,
- mips_f23,
- mips_f24,
- mips_f25,
- mips_f26,
- mips_f27,
- mips_f28,
- mips_f29,
- mips_f30,
- mips_f31
-};
-
-/* prefetch hints */
-enum {
- MIPS_FOR_LOAD,
- MIPS_FOR_STORE,
- MIPS_FOR_LOAD_STREAMED = 4,
- MIPS_FOR_STORE_STREAMED,
- MIPS_FOR_LOAD_RETAINED,
- MIPS_FOR_STORE_RETAINED
-};
-
-/* coprocessors */
-enum {
- MIPS_COP0,
- MIPS_COP1,
- MIPS_COP2,
- MIPS_COP3
-};
-
-enum {
- MIPS_FMT_SINGLE = 16,
- MIPS_FMT_DOUBLE = 17,
- MIPS_FMT_WORD = 20,
- MIPS_FMT_LONG = 21,
- MIPS_FMT3_SINGLE = 0,
- MIPS_FMT3_DOUBLE = 1
-};
-
-/* fpu rounding mode */
-enum {
- MIPS_ROUND_TO_NEAREST,
- MIPS_ROUND_TO_ZERO,
- MIPS_ROUND_TO_POSINF,
- MIPS_ROUND_TO_NEGINF,
- MIPS_ROUND_MASK = 3
-};
-
-/* fpu enable/cause flags, cc */
-enum {
- MIPS_FPU_C_MASK = 1 << 23,
- MIPS_INEXACT = 1,
- MIPS_UNDERFLOW = 2,
- MIPS_OVERFLOW = 4,
- MIPS_DIVZERO = 8,
- MIPS_INVALID = 16,
- MIPS_NOTIMPL = 32,
- MIPS_FPU_FLAGS_OFFSET = 2,
- MIPS_FPU_ENABLES_OFFSET = 7,
- MIPS_FPU_CAUSES_OFFSET = 12
-};
-
-/* fpu condition values - see manual entry for C.cond.fmt instructions */
-enum {
- MIPS_FPU_F,
- MIPS_FPU_UN,
- MIPS_FPU_EQ,
- MIPS_FPU_UEQ,
- MIPS_FPU_OLT,
- MIPS_FPU_ULT,
- MIPS_FPU_OLE,
- MIPS_FPU_ULE,
- MIPS_FPU_SF,
- MIPS_FPU_NGLE,
- MIPS_FPU_SEQ,
- MIPS_FPU_NGL,
- MIPS_FPU_LT,
- MIPS_FPU_NGE,
- MIPS_FPU_LE,
- MIPS_FPU_NGT
-};
-
-#if SIZEOF_REGISTER == 4
-
-#define MIPS_SW mips_sw
-#define MIPS_LW mips_lw
-#define MIPS_ADDU mips_addu
-#define MIPS_ADDIU mips_addiu
-#define MIPS_SWC1 mips_swc1
-#define MIPS_LWC1 mips_lwc1
-#define MIPS_MOVE mips_move
-
-#elif SIZEOF_REGISTER == 8
-
-#define MIPS_SW mips_sd
-#define MIPS_LW mips_ld
-#define MIPS_ADDU mips_daddu
-#define MIPS_ADDIU mips_daddiu
-#define MIPS_SWC1 mips_sdc1
-#define MIPS_LWC1 mips_ldc1
-#define MIPS_MOVE mips_dmove
-
-#else
-#error Unknown SIZEOF_REGISTER
-#endif
-
-#define mips_emit32(c,x) do { \
- *((guint32 *) (void *)(c)) = x; \
- (c) = (typeof(c))(((guint32 *)(void *)(c)) + 1); \
- } while (0)
-
-#define mips_format_i(code,op,rs,rt,imm) mips_emit32 ((code), (((op)<<26)|((rs)<<21)|((rt)<<16)|((imm)&0xffff)))
-#define mips_format_j(code,op,imm) mips_emit32 ((code), (((op)<<26)|((imm)&0x03ffffff)))
-#define mips_format_r(code,op,rs,rt,rd,sa,func) mips_emit32 ((code), (((op)<<26)|((rs)<<21)|((rt)<<16)|((rd)<<11)|((sa)<<6)|(func)))
-#define mips_format_divmul(code,op,src1,src2,fun) mips_emit32 ((code), (((op)<<26)|((src1)<<21)|((src2)<<16)|(fun)))
-
-#define mips_is_imm16(val) ((gint)(gshort)(gint)(val) == (gint)(val))
-
-/* Load always using lui/addiu pair (for later patching) */
-#define mips_load(c,D,v) do { \
- if (((guint32)(v)) & (1 << 15)) { \
- mips_lui ((c), (D), mips_zero, (((guint32)(v))>>16)+1); \
- } \
- else { \
- mips_lui ((c), (D), mips_zero, (((guint32)(v))>>16)); \
- } \
- mips_addiu ((c), (D), (D), ((guint32)(v)) & 0xffff); \
- } while (0)
-
-/* load constant - no patch-up */
-#define mips_load_const(c,D,v) do { \
- if (!mips_is_imm16 ((v))) { \
- if (((guint32)(v)) & (1 << 15)) { \
- mips_lui ((c), (D), mips_zero, (((guint32)(v))>>16)+1); \
- } \
- else { \
- mips_lui ((c), (D), mips_zero, (((guint32)(v))>>16)); \
- } \
- if (((guint32)(v)) & 0xffff) \
- mips_addiu ((c), (D), (D), ((guint32)(v)) & 0xffff); \
- } \
- else \
- mips_addiu ((c), (D), mips_zero, ((guint32)(v)) & 0xffff); \
- } while (0)
-
-/* arithmetric ops */
-#define mips_add(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,32)
-#define mips_addi(c,dest,src1,imm) mips_format_i(c,8,src1,dest,imm)
-#define mips_addu(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,33)
-#define mips_addiu(c,dest,src1,imm) mips_format_i(c,9,src1,dest,imm)
-#define mips_dadd(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,44)
-#define mips_daddi(c,dest,src1,imm) mips_format_i(c,24,src1,dest,imm)
-#define mips_daddu(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,45)
-#define mips_daddiu(c,dest,src1,imm) mips_format_i(c,25,src1,dest,imm)
-#define mips_dsub(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,46)
-#define mips_dsubu(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,47)
-#define mips_mul(c,dest,src1,src2) mips_format_r(c,28,src1,src2,dest,0,2)
-#define mips_sub(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,34)
-#define mips_subu(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,35)
-
-/* div and mul ops */
-#define mips_ddiv(c,src1,src2) mips_format_divmul(c,0,src1,src2,30)
-#define mips_ddivu(c,src1,src2) mips_format_divmul(c,0,src1,src2,31)
-#define mips_div(c,src1,src2) mips_format_divmul(c,0,src1,src2,26)
-#define mips_divu(c,src1,src2) mips_format_divmul(c,0,src1,src2,27)
-#define mips_dmult(c,src1,src2) mips_format_divmul(c,0,src1,src2,28)
-#define mips_dmultu(c,src1,src2) mips_format_divmul(c,0,src1,src2,29)
-#define mips_mult(c,src1,src2) mips_format_divmul(c,0,src1,src2,24)
-#define mips_multu(c,src1,src2) mips_format_divmul(c,0,src1,src2,25)
-
-/* shift ops */
-#define mips_dsll(c,dest,src1,imm) mips_format_r(c,0,0,src1,dest,imm,56)
-#define mips_dsll32(c,dest,src1,imm) mips_format_r(c,0,0,src1,dest,imm,60)
-#define mips_dsllv(c,dest,src1,src2) mips_format_r(c,0,src2,src1,dest,0,20)
-#define mips_dsra(c,dest,src1,imm) mips_format_r(c,0,0,src1,dest,imm,59)
-#define mips_dsra32(c,dest,src1,imm) mips_format_r(c,0,0,src1,dest,imm,63)
-#define mips_dsrav(c,dest,src1,src2) mips_format_r(c,0,src2,src1,dest,0,23)
-#define mips_dsrl(c,dest,src1,imm) mips_format_r(c,0,0,src1,dest,imm,58)
-#define mips_dsrl32(c,dest,src1,imm) mips_format_r(c,0,0,src1,dest,imm,62)
-#define mips_dsrlv(c,dest,src1,src2) mips_format_r(c,0,src2,src1,dest,0,22)
-#define mips_sll(c,dest,src1,imm) mips_format_r(c,0,0,src1,dest,imm,0)
-#define mips_sllv(c,dest,src1,src2) mips_format_r(c,0,src2,src1,dest,0,4)
-#define mips_sra(c,dest,src1,imm) mips_format_r(c,0,0,src1,dest,imm,3)
-#define mips_srav(c,dest,src1,src2) mips_format_r(c,0,src2,src1,dest,0,7)
-#define mips_srl(c,dest,src1,imm) mips_format_r(c,0,0,src1,dest,imm,2)
-#define mips_srlv(c,dest,src1,src2) mips_format_r(c,0,src2,src1,dest,0,6)
-
-/* logical ops */
-#define mips_and(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,36)
-#define mips_andi(c,dest,src1,imm) mips_format_i(c,12,src1,dest,imm)
-#define mips_nor(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,39)
-#define mips_or(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,37)
-#define mips_ori(c,dest,src1,uimm) mips_format_i(c,13,src1,dest,uimm)
-#define mips_xor(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,38)
-#define mips_xori(c,dest,src1,uimm) mips_format_i(c,14,src1,dest,uimm)
-
-/* compares */
-#define mips_slt(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,42)
-#define mips_slti(c,dest,src1,imm) mips_format_i(c,10,src1,dest,imm)
-#define mips_sltiu(c,dest,src1,imm) mips_format_i(c,11,src1,dest,imm)
-#define mips_sltu(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,43)
-/* missing traps: teq, teqi, tge, tgei, tgeiu, tgeu, tlt, tlti, tltiu, tltu, tne, tnei, */
-
-/* conditional branches */
-#define mips_beq(c,src1,src2,offset) mips_format_i(c,4,src1,src2,offset)
-#define mips_beql(c,src1,src2,offset) mips_format_i(c,20,src1,src2,offset)
-#define mips_bgez(c,src1,offset) mips_format_i(c,1,src1,1,offset)
-#define mips_bgezal(c,src1,offset) mips_format_i(c,1,src1,17,offset)
-#define mips_bgezall(c,src1,offset) mips_format_i(c,1,src1,19,offset)
-#define mips_bgezl(c,src1,offset) mips_format_i(c,1,src1,3,offset)
-#define mips_bgtz(c,src1,offset) mips_format_i(c,7,src1,0,offset)
-#define mips_bgtzl(c,src1,offset) mips_format_i(c,23,src1,0,offset)
-#define mips_blez(c,src1,offset) mips_format_i(c,6,src1,0,offset)
-#define mips_blezl(c,src1,offset) mips_format_i(c,22,src1,0,offset)
-#define mips_bltz(c,src1,offset) mips_format_i(c,1,src1,0,offset)
-#define mips_bltzal(c,src1,offset) mips_format_i(c,1,src1,16,offset)
-#define mips_bltzall(c,src1,offset) mips_format_i(c,1,src1,18,offset)
-#define mips_bltzl(c,src1,offset) mips_format_i(c,1,src1,2,offset)
-#define mips_bne(c,src1,src2,offset) mips_format_i(c,5,src1,src2,offset)
-#define mips_bnel(c,src1,src2,offset) mips_format_i(c,21,src1,src2,offset)
-
-/* uncond branches and calls */
-#define mips_jump(c,target) mips_format_j(c,2,target)
-#define mips_jumpl(c,target) mips_format_j(c,3,target)
-#define mips_jalr(c,src1,retreg) mips_format_r(c,0,src1,0,retreg,0,9)
-#define mips_jr(c,src1) mips_emit32(c,((src1)<<21)|8)
-
-/* loads and stores */
-#define mips_lb(c,dest,base,offset) mips_format_i(c,32,base,dest,offset)
-#define mips_lbu(c,dest,base,offset) mips_format_i(c,36,base,dest,offset)
-#define mips_ld(c,dest,base,offset) mips_format_i(c,55,base,dest,offset)
-#define mips_ldl(c,dest,base,offset) mips_format_i(c,26,base,dest,offset)
-#define mips_ldr(c,dest,base,offset) mips_format_i(c,27,base,dest,offset)
-#define mips_lh(c,dest,base,offset) mips_format_i(c,33,base,dest,offset)
-#define mips_lhu(c,dest,base,offset) mips_format_i(c,37,base,dest,offset)
-#define mips_ll(c,dest,base,offset) mips_format_i(c,48,base,dest,offset)
-#define mips_lld(c,dest,base,offset) mips_format_i(c,52,base,dest,offset)
-#define mips_lui(c,dest,base,uimm) mips_format_i(c,15,base,dest,uimm)
-#define mips_lw(c,dest,base,offset) mips_format_i(c,35,base,dest,offset)
-#define mips_lwl(c,dest,base,offset) mips_format_i(c,34,base,dest,offset)
-#define mips_lwr(c,dest,base,offset) mips_format_i(c,38,base,dest,offset)
-#define mips_lwu(c,dest,base,offset) mips_format_i(c,39,base,dest,offset)
-
-#define mips_sb(c,src,base,offset) mips_format_i(c,40,base,src,offset)
-#define mips_sc(c,src,base,offset) mips_format_i(c,56,base,src,offset)
-#define mips_scd(c,src,base,offset) mips_format_i(c,60,base,src,offset)
-#define mips_sd(c,src,base,offset) mips_format_i(c,63,base,src,offset)
-#define mips_sdl(c,src,base,offset) mips_format_i(c,44,base,src,offset)
-#define mips_sdr(c,src,base,offset) mips_format_i(c,45,base,src,offset)
-#define mips_sh(c,src,base,offset) mips_format_i(c,41,base,src,offset)
-#define mips_sw(c,src,base,offset) mips_format_i(c,43,base,src,offset)
-#define mips_swl(c,src,base,offset) mips_format_i(c,50,base,src,offset)
-#define mips_swr(c,src,base,offset) mips_format_i(c,54,base,src,offset)
-
-/* misc and coprocessor ops */
-#define mips_move(c,dest,src) mips_addu(c,dest,src,mips_zero)
-#define mips_dmove(c,dest,src) mips_daddu(c,dest,src,mips_zero)
-#define mips_nop(c) mips_or(c,mips_at,mips_at,0)
-#define mips_break(c,code) mips_emit32(c, ((code)<<6)|13)
-#define mips_mfhi(c,dest) mips_format_r(c,0,0,0,dest,0,16)
-#define mips_mflo(c,dest) mips_format_r(c,0,0,0,dest,0,18)
-#define mips_mthi(c,src) mips_format_r(c,0,src,0,0,0,17)
-#define mips_mtlo(c,src) mips_format_r(c,0,src,0,0,0,19)
-#define mips_movn(c,dest,src,test) mips_format_r(c,0,src,test,dest,0,11)
-#define mips_movz(c,dest,src,test) mips_format_r(c,0,src,test,dest,0,10)
-#define mips_pref(c,hint,base,offset) mips_format_i(c,51,base,hint,offset)
-#define mips_prefidx(c,hint,base,idx) mips_format_r(c,19,base,idx,hint,0,15)
-#define mips_sync(c,stype) mips_emit32(c, ((stype)<<6)|15)
-#define mips_syscall(c,code) mips_emit32(c, ((code)<<6)|12)
-
-#define mips_cop(c,cop,fun) mips_emit32(c, ((16|(cop))<<26)|(fun))
-#define mips_ldc(c,cop,dest,base,offset) mips_format_i(c,(52|(cop)),base,dest,offset)
-#define mips_lwc(c,cop,dest,base,offset) mips_format_i(c,(48|(cop)),base,dest,offset)
-#define mips_sdc(c,cop,src,base,offset) mips_format_i(c,(60|(cop)),base,src,offset)
-#define mips_swc(c,cop,src,base,offset) mips_format_i(c,(56|(cop)),base,src,offset)
-#define mips_cfc1(c,dest,src) mips_format_r(c,17,2,dest,src,0,0)
-#define mips_ctc1(c,dest,src) mips_format_r(c,17,6,dest,src,0,0)
-
-/* fpu ops */
-#define mips_fabss(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,5)
-#define mips_fabsd(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,5)
-#define mips_fadds(c,dest,src1,src2) mips_format_r(c,17,MIPS_FMT_SINGLE,src2,src1,dest,0)
-#define mips_faddd(c,dest,src1,src2) mips_format_r(c,17,MIPS_FMT_DOUBLE,src2,src1,dest,0)
-#define mips_fdivs(c,dest,src1,src2) mips_format_r(c,17,MIPS_FMT_SINGLE,src2,src1,dest,3)
-#define mips_fdivd(c,dest,src1,src2) mips_format_r(c,17,MIPS_FMT_DOUBLE,src2,src1,dest,3)
-#define mips_fmuls(c,dest,src1,src2) mips_format_r(c,17,MIPS_FMT_SINGLE,src2,src1,dest,2)
-#define mips_fmuld(c,dest,src1,src2) mips_format_r(c,17,MIPS_FMT_DOUBLE,src2,src1,dest,2)
-#define mips_fnegs(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,7)
-#define mips_fnegd(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,7)
-#define mips_fsqrts(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,4)
-#define mips_fsqrtd(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,4)
-#define mips_fsubs(c,dest,src1,src2) mips_format_r(c,17,MIPS_FMT_SINGLE,src2,src1,dest,1)
-#define mips_fsubd(c,dest,src1,src2) mips_format_r(c,17,MIPS_FMT_DOUBLE,src2,src1,dest,1)
-#define mips_madds(c,dest,src1,src2,srcadd) mips_format_r(c,19,srcadd,src2,src1,dest,32|MIPS_FMT_SINGLE)
-#define mips_maddd(c,dest,src1,src2,srcadd) mips_format_r(c,19,srcadd,src2,src1,dest,32|MIPS_FMT_DOUBLE)
-#define mips_nmadds(c,dest,src1,src2,srcadd) mips_format_r(c,19,srcadd,src2,src1,dest,48|MIPS_FMT_SINGLE)
-#define mips_nmaddd(c,dest,src1,src2,srcadd) mips_format_r(c,19,srcadd,src2,src1,dest,48|MIPS_FMT_DOUBLE)
-#define mips_msubs(c,dest,src1,src2,srcsub) mips_format_r(c,19,srcsub,src2,src1,dest,40|MIPS_FMT_SINGLE)
-#define mips_msubd(c,dest,src1,src2,srcsub) mips_format_r(c,19,srcsub,src2,src1,dest,40|MIPS_FMT_DOUBLE)
-#define mips_nmsubs(c,dest,src1,src2,srcsub) mips_format_r(c,19,srcsub,src2,src1,dest,56|MIPS_FMT_SINGLE)
-#define mips_nmsubd(c,dest,src1,src2,srcsub) mips_format_r(c,19,srcsub,src2,src1,dest,56|MIPS_FMT_DOUBLE)
-
-/* fp compare and branch */
-#define mips_fcmps(c,cond,src1,src2) mips_format_r(c,17,MIPS_FMT_SINGLE,src2,src1,0,(3<<4)|(cond))
-#define mips_fcmpd(c,cond,src1,src2) mips_format_r(c,17,MIPS_FMT_DOUBLE,src2,src1,0,(3<<4)|(cond))
-#define mips_fbfalse(c,offset) mips_format_i(c,17,8,0,offset)
-#define mips_fbfalsel(c,offset) mips_format_i(c,17,8,2,offset)
-#define mips_fbtrue(c,offset) mips_format_i(c,17,8,1,offset)
-#define mips_fbtruel(c,offset) mips_format_i(c,17,8,3,offset)
-
-/* fp convert */
-#define mips_ceills(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,10)
-#define mips_ceilld(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,10)
-#define mips_ceilws(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,14)
-#define mips_ceilwd(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,14)
-#define mips_cvtds(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,33)
-#define mips_cvtdw(c,dest,src) mips_format_r(c,17,MIPS_FMT_WORD,0,src,dest,33)
-#define mips_cvtdl(c,dest,src) mips_format_r(c,17,MIPS_FMT_LONG,0,src,dest,33)
-#define mips_cvtls(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,37)
-#define mips_cvtld(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,37)
-#define mips_cvtsd(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,32)
-#define mips_cvtsw(c,dest,src) mips_format_r(c,17,MIPS_FMT_WORD,0,src,dest,32)
-#define mips_cvtsl(c,dest,src) mips_format_r(c,17,MIPS_FMT_LONG,0,src,dest,32)
-#define mips_cvtws(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,36)
-#define mips_cvtwd(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,36)
-#define mips_floorls(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,11)
-#define mips_floorld(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,11)
-#define mips_floorws(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,15)
-#define mips_floorwd(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,15)
-#define mips_roundls(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,8)
-#define mips_roundld(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,8)
-#define mips_roundws(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,12)
-#define mips_roundwd(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,12)
-#define mips_truncls(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,9)
-#define mips_truncld(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,9)
-#define mips_truncws(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,13)
-#define mips_truncwd(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,13)
-
-/* fp moves, loads */
-#define mips_fmovs(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,6)
-#define mips_fmovd(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,6)
-#define mips_mfc1(c,dest,src) mips_format_r(c,17,0,dest,src,0,0)
-#define mips_mtc1(c,dest,src) mips_format_r(c,17,4,src,dest,0,0)
-#define mips_dmfc1(c,dest,src) mips_format_r(c,17,1,0,dest,src,0)
-#define mips_dmtc1(c,dest,src) mips_format_r(c,17,1,0,src,dest,0)
-#define mips_ldc1(c,dest,base,offset) mips_ldc(c,1,dest,base,offset)
-#define mips_ldxc1(c,dest,base,idx) mips_format_r(c,19,base,idx,0,dest,1)
-#define mips_lwc1(c,dest,base,offset) mips_lwc(c,1,dest,base,offset)
-#define mips_lwxc1(c,dest,base,idx) mips_format_r(c,19,base,idx,0,dest,0)
-#define mips_sdc1(c,src,base,offset) mips_sdc(c,1,src,base,offset)
-#define mips_sdxc1(c,src,base,idx) mips_format_r(c,19,base,idx,src,0,9)
-#define mips_swc1(c,src,base,offset) mips_swc(c,1,src,base,offset)
-#define mips_swxc1(c,src,base,idx) mips_format_r(c,19,base,idx,src,0,8)
-
-#endif /* __MIPS_CODEGEN_H__ */
-
+++ /dev/null
-#include "config.h"
-#include <stdlib.h>
-#include <string.h>
-
-#define NO_MIPS_JIT_DEBUG
-
-#include "mips-codegen.h"
-#include "mono/metadata/class.h"
-
-/* don't run the resulting program, it will destroy your computer,
- * just objdump -d it to inspect we generated the correct assembler.
- */
-
-int main (int argc, char *argv[]) {
- guint32 *code, * p;
-
- code = p = (guint32 *) malloc (sizeof (guint32) * 1024);
-
- mips_add (p, 3, 4, 5);
- mips_addi (p, 3, 4, 5);
- mips_addu (p, 3, 4, 5);
- mips_addiu (p, 3, 4, 5);
- mips_sub (p, 3, 4, 5);
- mips_subu (p, 3, 4, 5);
- mips_dadd (p, 3, 4, 5);
- mips_daddi (p, 3, 4, 5);
- mips_daddu (p, 3, 4, 5);
- mips_daddiu (p, 3, 4, 5);
- mips_dsub (p, 3, 4, 5);
- mips_dsubu (p, 3, 4, 5);
-
- mips_mult (p, 6, 7);
- mips_multu (p, 6, 7);
- mips_div (p, 6, 7);
- mips_divu (p, 6, 7);
- mips_dmult (p, 6, 7);
- mips_dmultu (p, 6, 7);
- mips_ddiv (p, 6, 7);
- mips_ddivu (p, 6, 7);
-
- mips_sll (p, 3, 4, 5);
- mips_sllv (p, 3, 4, 5);
- mips_sra (p, 3, 4, 5);
- mips_srav (p, 3, 4, 5);
- mips_srl (p, 3, 4, 5);
- mips_srlv (p, 3, 4, 5);
- mips_dsll (p, 3, 4, 5);
- mips_dsll32 (p, 3, 4, 5);
- mips_dsllv (p, 3, 4, 5);
- mips_dsra (p, 3, 4, 5);
- mips_dsra32 (p, 3, 4, 5);
- mips_dsrav (p, 3, 4, 5);
- mips_dsrl (p, 3, 4, 5);
- mips_dsrl32 (p, 3, 4, 5);
- mips_dsrlv (p, 3, 4, 5);
-
- mips_and (p, 8, 9, 10);
- mips_andi (p, 8, 9, 10);
- mips_nor (p, 8, 9, 10);
- mips_or (p, 8, 9, 10);
- mips_ori (p, 8, 9, 10);
- mips_xor (p, 8, 9, 10);
- mips_xori (p, 8, 9, 10);
-
- mips_slt (p, 8, 9, 10);
- mips_slti (p, 8, 9, 10);
- mips_sltu (p, 8, 9, 10);
- mips_sltiu (p, 8, 9, 10);
-
- mips_beq (p, 8, 9, 0xff1f);
- mips_beql (p, 8, 9, 0xff1f);
- mips_bne (p, 8, 9, 0xff1f);
- mips_bnel (p, 8, 9, 0xff1f);
- mips_bgez (p, 11, 0xff1f);
- mips_bgezal (p, 11, 0xff1f);
- mips_bgezall (p, 11, 0xff1f);
- mips_bgezl (p, 11, 0xff1f);
- mips_bgtz (p, 11, 0xff1f);
- mips_bgtzl (p, 11, 0xff1f);
- mips_blez (p, 11, 0xff1f);
- mips_blezl (p, 11, 0xff1f);
- mips_bltz (p, 11, 0xff1f);
- mips_bltzal (p, 11, 0xff1f);
- mips_bltzall (p, 11, 0xff1f);
- mips_bltzl (p, 11, 0xff1f);
-
- mips_jump (p, 0xff1f);
- mips_jumpl (p, 0xff1f);
- mips_jalr (p, 12, mips_ra);
- mips_jr (p, 12);
-
- mips_lb (p, 13, 14, 128);
- mips_lbu (p, 13, 14, 128);
- mips_ld (p, 13, 14, 128);
- mips_ldl (p, 13, 14, 128);
- mips_ldr (p, 13, 14, 128);
- mips_lh (p, 13, 14, 128);
- mips_lhu (p, 13, 14, 128);
- mips_ll (p, 13, 14, 128);
- mips_lld (p, 13, 14, 128);
- mips_lui (p, 13, 14, 128);
- mips_lw (p, 13, 14, 128);
- mips_lwl (p, 13, 14, 128);
- mips_lwr (p, 13, 14, 128);
- mips_lwu (p, 13, 14, 128);
- mips_sb (p, 13, 14, 128);
- mips_sc (p, 13, 14, 128);
- mips_scd (p, 13, 14, 128);
- mips_sd (p, 13, 14, 128);
- mips_sdl (p, 13, 14, 128);
- mips_sdr (p, 13, 14, 128);
- mips_sh (p, 13, 14, 128);
- mips_sw (p, 13, 14, 128);
- mips_swl (p, 13, 14, 128);
- mips_swr (p, 13, 14, 128);
-
- mips_move (p, 15, 16);
- mips_nop (p);
- mips_break (p, 0);
- mips_sync (p, 0);
- mips_mfhi (p, 17);
- mips_mflo (p, 17);
- mips_mthi (p, 17);
- mips_mtlo (p, 17);
-
- mips_fabsd (p, 16, 18);
- mips_fnegd (p, 16, 18);
- mips_fsqrtd (p, 16, 18);
- mips_faddd (p, 16, 18, 20);
- mips_fdivd (p, 16, 18, 20);
- mips_fmuld (p, 16, 18, 20);
- mips_fsubd (p, 16, 18, 20);
-
- mips_fcmpd (p, MIPS_FPU_EQ, 18, 20);
- mips_fbfalse (p, 0xff1f);
- mips_fbfalsel (p, 0xff1f);
- mips_fbtrue (p, 0xff1f);
- mips_fbtruel (p, 0xff1f);
-
- mips_ceilwd (p, 20, 22);
- mips_ceilld (p, 20, 22);
- mips_floorwd (p, 20, 22);
- mips_floorld (p, 20, 22);
- mips_roundwd (p, 20, 22);
- mips_roundld (p, 20, 22);
- mips_truncwd (p, 20, 22);
- mips_truncld (p, 20, 22);
- mips_cvtdw (p, 20, 22);
- mips_cvtds (p, 20, 22);
- mips_cvtdl (p, 20, 22);
- mips_cvtld (p, 20, 22);
- mips_cvtsd (p, 20, 22);
- mips_cvtwd (p, 20, 22);
-
- mips_fmovd (p, 20, 22);
- printf ("size: %d\n", p - code);
-
- return 0;
-}
+++ /dev/null
-#ifndef __SPARC_CODEGEN_H__
-#define __SPARC_CODEGEN_H__
-
-#if SIZEOF_VOID_P == 8
-#define SPARCV9 1
-#else
-#endif
-
-typedef enum {
- sparc_r0 = 0,
- sparc_r1 = 1,
- sparc_r2 = 2,
- sparc_r3 = 3,
- sparc_r4 = 4,
- sparc_r5 = 5,
- sparc_r6 = 6,
- sparc_r7 = 7,
- sparc_r8 = 8,
- sparc_r9 = 9,
- sparc_r10 = 10,
- sparc_r11 = 11,
- sparc_r12 = 12,
- sparc_r13 = 13,
- sparc_r14 = 14,
- sparc_r15 = 15,
- sparc_r16 = 16,
- sparc_r17 = 17,
- sparc_r18 = 18,
- sparc_r19 = 19,
- sparc_r20 = 20,
- sparc_r21 = 21,
- sparc_r22 = 22,
- sparc_r23 = 23,
- sparc_r24 = 24,
- sparc_r25 = 25,
- sparc_r26 = 26,
- sparc_r27 = 27,
- sparc_r28 = 28,
- sparc_r29 = 29,
- sparc_r30 = 30,
- sparc_r31 = 31,
- /* aliases */
- /* global registers */
- sparc_g0 = 0, sparc_zero = 0,
- sparc_g1 = 1,
- sparc_g2 = 2,
- sparc_g3 = 3,
- sparc_g4 = 4,
- sparc_g5 = 5,
- sparc_g6 = 6,
- sparc_g7 = 7,
- /* out registers */
- sparc_o0 = 8,
- sparc_o1 = 9,
- sparc_o2 = 10,
- sparc_o3 = 11,
- sparc_o4 = 12,
- sparc_o5 = 13,
- sparc_o6 = 14, sparc_sp = 14,
- sparc_o7 = 15, sparc_callsite = 15,
- /* local registers */
- sparc_l0 = 16,
- sparc_l1 = 17,
- sparc_l2 = 18,
- sparc_l3 = 19,
- sparc_l4 = 20,
- sparc_l5 = 21,
- sparc_l6 = 22,
- sparc_l7 = 23,
- /* in registers */
- sparc_i0 = 24,
- sparc_i1 = 25,
- sparc_i2 = 26,
- sparc_i3 = 27,
- sparc_i4 = 28,
- sparc_i5 = 29,
- sparc_i6 = 30, sparc_fp = 30,
- sparc_i7 = 31,
- sparc_nreg = 32,
- /* floating point registers */
- sparc_f0 = 0,
- sparc_f1 = 1,
- sparc_f2 = 2,
- sparc_f3 = 3,
- sparc_f4 = 4,
- sparc_f5 = 5,
- sparc_f6 = 6,
- sparc_f7 = 7,
- sparc_f8 = 8,
- sparc_f9 = 9,
- sparc_f10 = 10,
- sparc_f11 = 11,
- sparc_f12 = 12,
- sparc_f13 = 13,
- sparc_f14 = 14,
- sparc_f15 = 15,
- sparc_f16 = 16,
- sparc_f17 = 17,
- sparc_f18 = 18,
- sparc_f19 = 19,
- sparc_f20 = 20,
- sparc_f21 = 21,
- sparc_f22 = 22,
- sparc_f23 = 23,
- sparc_f24 = 24,
- sparc_f25 = 25,
- sparc_f26 = 26,
- sparc_f27 = 27,
- sparc_f28 = 28,
- sparc_f29 = 29,
- sparc_f30 = 30,
- sparc_f31 = 31,
-} SparcRegister;
-
-typedef enum {
- sparc_bn = 0, sparc_bnever = 0,
- sparc_be = 1,
- sparc_ble = 2,
- sparc_bl = 3,
- sparc_bleu = 4,
- sparc_bcs = 5, sparc_blu = 5,
- sparc_bneg = 6,
- sparc_bvs = 7, sparc_boverflow = 7,
- sparc_ba = 8, sparc_balways = 8,
- sparc_bne = 9,
- sparc_bg = 10,
- sparc_bge = 11,
- sparc_bgu = 12,
- sparc_bcc = 13, sparc_beu = 13,
- sparc_bpos = 14,
- sparc_bvc = 15
-} SparcCond;
-
-typedef enum {
- /* with fcmp */
- sparc_feq = 0,
- sparc_fl = 1,
- sparc_fg = 2,
- sparc_unordered = 3,
- /* branch ops */
- sparc_fba = 8,
- sparc_fbn = 0,
- sparc_fbu = 7,
- sparc_fbg = 6,
- sparc_fbug = 5,
- sparc_fbl = 4,
- sparc_fbul = 3,
- sparc_fblg = 2,
- sparc_fbne = 1,
- sparc_fbe = 9,
- sparc_fbue = 10,
- sparc_fbge = 11,
- sparc_fbuge = 12,
- sparc_fble = 13,
- sparc_fbule = 14,
- sparc_fbo = 15
-} SparcFCond;
-
-typedef enum {
- sparc_icc = 4,
- sparc_xcc = 6,
- sparc_fcc0 = 0,
- sparc_fcc1 = 1,
- sparc_fcc2 = 2,
- sparc_fcc3 = 3
-} SparcCC;
-
-typedef enum {
- sparc_icc_short = 0,
- sparc_xcc_short = 2
-} SparcCCShort;
-
-typedef enum {
- /* fop1 format */
- sparc_fitos_val = 196,
- sparc_fitod_val = 200,
- sparc_fitoq_val = 204,
- sparc_fxtos_val = 132,
- sparc_fxtod_val = 136,
- sparc_fxtoq_val = 140,
- sparc_fstoi_val = 209,
- sparc_fdtoi_val = 210,
- sparc_fqtoi_val = 211,
- sparc_fstod_val = 201,
- sparc_fstoq_val = 205,
- sparc_fdtos_val = 198,
- sparc_fdtoq_val = 206,
- sparc_fqtos_val = 199,
- sparc_fqtod_val = 203,
- sparc_fmovs_val = 1,
- sparc_fmovd_val = 2,
- sparc_fnegs_val = 5,
- sparc_fnegd_val = 6,
- sparc_fabss_val = 9,
- sparc_fabsd_val = 10,
- sparc_fsqrts_val = 41,
- sparc_fsqrtd_val = 42,
- sparc_fsqrtq_val = 43,
- sparc_fadds_val = 65,
- sparc_faddd_val = 66,
- sparc_faddq_val = 67,
- sparc_fsubs_val = 69,
- sparc_fsubd_val = 70,
- sparc_fsubq_val = 71,
- sparc_fmuls_val = 73,
- sparc_fmuld_val = 74,
- sparc_fmulq_val = 75,
- sparc_fsmuld_val = 105,
- sparc_fdmulq_val = 111,
- sparc_fdivs_val = 77,
- sparc_fdivd_val = 78,
- sparc_fdivq_val = 79,
- /* fop2 format */
- sparc_fcmps_val = 81,
- sparc_fcmpd_val = 82,
- sparc_fcmpq_val = 83,
- sparc_fcmpes_val = 85,
- sparc_fcmped_val = 86,
- sparc_fcmpeq_val = 87
-} SparcFOp;
-
-typedef enum {
- sparc_membar_load_load = 0x1,
- sparc_membar_store_load = 0x2,
- sparc_membar_load_store = 0x4,
- sparc_membar_store_store = 0x8,
-
- sparc_membar_lookaside = 0x10,
- sparc_membar_memissue = 0x20,
- sparc_membar_sync = 0x40,
-
- sparc_membar_all = 0x4f
-} SparcMembarFlags;
-
-typedef struct {
- unsigned int op : 2; /* always 1 */
- unsigned int disp : 30;
-} sparc_format1;
-
-typedef struct {
- unsigned int op : 2; /* always 0 */
- unsigned int rd : 5;
- unsigned int op2 : 3;
- unsigned int disp : 22;
-} sparc_format2a;
-
-typedef struct {
- unsigned int op : 2; /* always 0 */
- unsigned int a : 1;
- unsigned int cond : 4;
- unsigned int op2 : 3;
- unsigned int disp : 22;
-} sparc_format2b;
-
-typedef struct {
- unsigned int op : 2; /* always 0 */
- unsigned int a : 1;
- unsigned int cond : 4;
- unsigned int op2 : 3;
- unsigned int cc01 : 2;
- unsigned int p : 1;
- unsigned int d19 : 19;
-} sparc_format2c;
-
-typedef struct {
- unsigned int op : 2; /* always 0 */
- unsigned int a : 1;
- unsigned int res : 1;
- unsigned int rcond: 3;
- unsigned int op2 : 3;
- unsigned int d16hi: 2;
- unsigned int p : 1;
- unsigned int rs1 : 5;
- unsigned int d16lo: 14;
-} sparc_format2d;
-
-typedef struct {
- unsigned int op : 2; /* 2 or 3 */
- unsigned int rd : 5;
- unsigned int op3 : 6;
- unsigned int rs1 : 5;
- unsigned int i : 1;
- unsigned int asi : 8;
- unsigned int rs2 : 5;
-} sparc_format3a;
-
-typedef struct {
- unsigned int op : 2; /* 2 or 3 */
- unsigned int rd : 5;
- unsigned int op3 : 6;
- unsigned int rs1 : 5;
- unsigned int i : 1;
- unsigned int x : 1;
- unsigned int asi : 7;
- unsigned int rs2 : 5;
-} sparc_format3ax;
-
-typedef struct {
- unsigned int op : 2; /* 2 or 3 */
- unsigned int rd : 5;
- unsigned int op3 : 6;
- unsigned int rs1 : 5;
- unsigned int i : 1;
- unsigned int imm : 13;
-} sparc_format3b;
-
-typedef struct {
- unsigned int op : 2; /* 2 or 3 */
- unsigned int rd : 5;
- unsigned int op3 : 6;
- unsigned int rs1 : 5;
- unsigned int i : 1;
- unsigned int x : 1;
- unsigned int imm : 12;
-} sparc_format3bx;
-
-typedef struct {
- unsigned int op : 2; /* 2 or 3 */
- unsigned int rd : 5;
- unsigned int op3 : 6;
- unsigned int rs1 : 5;
- unsigned int opf : 9;
- unsigned int rs2 : 5;
-} sparc_format3c;
-
-typedef struct {
- unsigned int op : 2;
- unsigned int rd : 5;
- unsigned int op3 : 6;
- unsigned int rs1 : 5;
- unsigned int i : 1;
- unsigned int cc01 : 2;
- unsigned int res : 6;
- unsigned int rs2 : 5;
-} sparc_format4a;
-
-typedef struct {
- unsigned int op : 2;
- unsigned int rd : 5;
- unsigned int op3 : 6;
- unsigned int rs1 : 5;
- unsigned int i : 1;
- unsigned int cc01 : 2;
- unsigned int simm : 11;
-} sparc_format4b;
-
-typedef struct {
- unsigned int op : 2;
- unsigned int rd : 5;
- unsigned int op3 : 6;
- unsigned int cc2 : 1;
- unsigned int cond : 4;
- unsigned int i : 1;
- unsigned int cc01 : 2;
- unsigned int res : 6;
- unsigned int rs2 : 5;
-} sparc_format4c;
-
-typedef struct {
- unsigned int op : 2;
- unsigned int rd : 5;
- unsigned int op3 : 6;
- unsigned int cc2 : 1;
- unsigned int cond : 4;
- unsigned int i : 1;
- unsigned int cc01 : 2;
- unsigned int simm : 11;
-} sparc_format4d;
-
-/* for use in logical ops, use 0 to not set flags */
-#define sparc_cc 16
-
-#define sparc_is_imm13(val) ((glong)val >= (glong)-(1<<12) && (glong)val <= (glong)((1<<12)-1))
-#define sparc_is_imm22(val) ((glong)val >= (glong)-(1<<21) && (glong)val <= (glong)((1<<21)-1))
-#define sparc_is_imm16(val) ((glong)val >= (glong)-(1<<15) && (glong)val <= (glong)((1<<15)-1))
-#define sparc_is_imm19(val) ((glong)val >= (glong)-(1<<18) && (glong)val <= (glong)((1<<18)-1))
-#define sparc_is_imm30(val) ((glong)val >= (glong)-(1<<29) && (glong)val <= (glong)((1<<29)-1))
-
-/* disassembly */
-#define sparc_inst_op(inst) ((inst) >> 30)
-#define sparc_inst_op2(inst) (((inst) >> 22) & 0x7)
-#define sparc_inst_rd(inst) (((inst) >> 25) & 0x1f)
-#define sparc_inst_op3(inst) (((inst) >> 19) & 0x3f)
-#define sparc_inst_i(inst) (((inst) >> 13) & 0x1)
-#define sparc_inst_rs1(inst) (((inst) >> 14) & 0x1f)
-#define sparc_inst_rs2(inst) (((inst) >> 0) & 0x1f)
-#define sparc_inst_imm(inst) (((inst) >> 13) & 0x1)
-#define sparc_inst_imm13(inst) (((inst) >> 0) & 0x1fff)
-
-#define sparc_encode_call(ins,addr) \
- do { \
- sparc_format1 *__f = (sparc_format1*)(ins); \
- __f->op = 1; \
- __f->disp = ((unsigned int)(addr) >> 2); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format2a(ins,val,oper,dest) \
- do { \
- sparc_format2a *__f = (sparc_format2a*)(ins); \
- __f->op = 0; \
- __f->rd = (dest); \
- __f->op2 = (oper); \
- __f->disp = (val) & 0x3fffff; \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format2b(ins,aval,bcond,oper,disp22) \
- do { \
- sparc_format2b *__f = (sparc_format2b*)(ins); \
- __f->op = 0; \
- __f->a = (aval); \
- __f->cond = (bcond); \
- __f->op2 = (oper); \
- __f->disp = (disp22); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format2c(ins,aval,bcond,oper,xcc,predict,disp19) \
- do { \
- sparc_format2c *__f = (sparc_format2c*)(ins); \
- __f->op = 0; \
- __f->a = (aval); \
- __f->cond = (bcond); \
- __f->op2 = (oper); \
- __f->cc01 = (xcc); \
- __f->p = (predict); \
- __f->d19 = (disp19); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format2d(ins,aval,bcond,oper,predict,r1,disp16) \
- do { \
- sparc_format2d *__f = (sparc_format2d*)(ins); \
- __f->op = 0; \
- __f->a = (aval); \
- __f->res = 0; \
- __f->rcond = (bcond); \
- __f->op2 = (oper); \
- __f->d16hi = ((disp16) >> 14); \
- __f->p = (predict); \
- __f->rs1 = (r1); \
- __f->d16lo = ((disp16) & 0x3fff); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format3a(ins,opval,asival,r1,r2,oper,dest) \
- do { \
- sparc_format3a *__f = (sparc_format3a*)(ins); \
- __f->op = (opval); \
- __f->asi = (asival); \
- __f->i = 0; \
- __f->rd = (dest); \
- __f->rs1 = (r1); \
- __f->rs2 = (r2); \
- __f->op3 = (oper); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format3ax(ins,opval,asival,r1,r2,oper,dest) \
- do { \
- sparc_format3ax *__f = (sparc_format3ax*)(ins); \
- __f->op = (opval); \
- __f->asi = (asival); \
- __f->i = 0; \
- __f->x = 1; \
- __f->rd = (dest); \
- __f->rs1 = (r1); \
- __f->rs2 = (r2); \
- __f->op3 = (oper); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format3b(ins,opval,r1,val,oper,dest) \
- do { \
- sparc_format3b *__f = (sparc_format3b*)(ins); \
- __f->op = (opval); \
- __f->imm = (val); \
- __f->i = 1; \
- __f->rd = (dest); \
- __f->rs1 = (r1); \
- __f->op3 = (oper); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format3bx(ins,opval,r1,val,oper,dest) \
- do { \
- sparc_format3bx *__f = (sparc_format3bx*)(ins); \
- __f->op = (opval); \
- __f->imm = (val); \
- __f->i = 1; \
- __f->x = 1; \
- __f->rd = (dest); \
- __f->rs1 = (r1); \
- __f->op3 = (oper); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format3c(ins,opval,opfval,r1,oper,r2,dest) \
- do { \
- sparc_format3c *__f = (sparc_format3c*)(ins); \
- __f->op = (opval); \
- __f->opf = (opfval); \
- __f->rd = (dest); \
- __f->rs1 = (r1); \
- __f->rs2 = (r2); \
- __f->op3 = (oper); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format4a(ins,opval,oper,cc,r1,r2,dest) \
- do { \
- sparc_format4a *__f = (sparc_format4a*)(ins); \
- __f->op = (opval); \
- __f->rd = (dest); \
- __f->op3 = (oper); \
- __f->rs1 = (r1); \
- __f->i = 0; \
- __f->cc01= (cc) & 0x3; \
- __f->res = 0; \
- __f->rs2 = (r2); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format4b(ins,opval,oper,cc,r1,imm,dest) \
- do { \
- sparc_format4b *__f = (sparc_format4b*)(ins); \
- __f->op = (opval); \
- __f->rd = (dest); \
- __f->op3 = (oper); \
- __f->rs1 = (r1); \
- __f->i = 1; \
- __f->cc01= (cc) & 0x3; \
- __f->simm = (imm); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format4c(ins,opval,oper,cc,bcond,r2,dest) \
- do { \
- sparc_format4c *__f = (sparc_format4c*)(ins); \
- __f->op = (opval); \
- __f->rd = (dest); \
- __f->op3 = (oper); \
- __f->cc2 = ((xcc) >> 2) & 0x1; \
- __f->cond = bcond; \
- __f->i = 0; \
- __f->cc01= (xcc) & 0x3; \
- __f->res = 0; \
- __f->rs2 = (r2); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-#define sparc_encode_format4d(ins,opval,oper,xcc,bcond,imm,dest) \
- do { \
- sparc_format4d *__f = (sparc_format4d*)(ins); \
- __f->op = (opval); \
- __f->rd = (dest); \
- __f->op3 = (oper); \
- __f->cc2 = ((xcc) >> 2) & 0x1; \
- __f->cond = bcond; \
- __f->i = 1; \
- __f->cc01= (xcc) & 0x3; \
- __f->simm = (imm); \
- (ins) = (unsigned int*)__f + 1; \
- } while (0)
-
-/* is it useful to provide a non-default value? */
-#define sparc_asi 0x0
-
-/* load */
-#define sparc_ldsb(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),9,(dest))
-#define sparc_ldsb_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),9,(dest))
-
-#define sparc_ldsh(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),10,(dest))
-#define sparc_ldsh_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),10,(dest))
-
-#define sparc_ldub(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),1,(dest))
-#define sparc_ldub_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),1,(dest))
-
-#define sparc_lduh(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),2,(dest))
-#define sparc_lduh_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),2,(dest))
-
-#define sparc_ld(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),0,(dest))
-#define sparc_ld_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),0,(dest))
-
-/* Sparc V9 */
-#define sparc_ldx(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),11,(dest))
-#define sparc_ldx_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),11,(dest))
-
-#define sparc_ldsw(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),8,(dest))
-#define sparc_ldsw_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),8,(dest))
-
-#define sparc_ldd(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),3,(dest))
-#define sparc_ldd_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),3,(dest))
-
-#define sparc_ldf(ins,base,disp,dest) sparc_encode_format3a((ins),3,0,(base),(disp),32,(dest))
-#define sparc_ldf_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),32,(dest))
-
-#define sparc_lddf(ins,base,disp,dest) sparc_encode_format3a((ins),3,0,(base),(disp),35,(dest))
-#define sparc_lddf_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),35,(dest))
-
-/* store */
-#define sparc_stb(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),5,(src))
-#define sparc_stb_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),5,(src))
-
-#define sparc_sth(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),6,(src))
-#define sparc_sth_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),6,(src))
-
-#define sparc_st(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),4,(src))
-#define sparc_st_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),4,(src))
-
-/* Sparc V9 */
-#define sparc_stx(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),14,(src))
-#define sparc_stx_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),14,(src))
-
-#define sparc_std(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),7,(src))
-#define sparc_std_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),7,(src))
-
-#define sparc_stf(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),36,(src))
-#define sparc_stf_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),36,(src))
-
-#define sparc_stdf(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),39,(src))
-#define sparc_stdf_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),39,(src))
-
-/* swap */
-#define sparc_ldstub(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),13,(dest))
-#define sparc_ldstub_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),13,(dest))
-
-#define sparc_swap(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),15,(dest))
-#define sparc_swap_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),15,(dest))
-
-/* misc */
-/* note: with sethi val is the full 32 bit value (think of it as %hi(val)) */
-#define sparc_sethi(ins,val,dest) sparc_encode_format2a((ins),((val)>>10),4,(dest))
-
-#define sparc_nop(ins) sparc_sethi((ins),0,sparc_zero)
-
-#define sparc_save(ins,src,disp,dest) sparc_encode_format3a((ins),2,0,(src),(disp),60,(dest))
-#define sparc_save_imm(ins,src,disp,dest) sparc_encode_format3b((ins),2,(src),(disp),60,(dest))
-
-#define sparc_restore(ins,src,disp,dest) sparc_encode_format3a((ins),2,0,(src),(disp),61,(dest))
-#define sparc_restore_imm(ins,src,disp,dest) sparc_encode_format3b((ins),2,(src),(disp),61,(dest))
-
-#define sparc_rett(ins,src,disp) sparc_encode_format3a((ins),2,0,(src),(disp),0x39,0)
-#define sparc_rett_imm(ins,src,disp) sparc_encode_format3b((ins),2,(src),(disp),0x39,0)
-
-#define sparc_jmpl(ins,base,disp,dest) sparc_encode_format3a((ins),2,0,(base),(disp),56,(dest))
-#define sparc_jmpl_imm(ins,base,disp,dest) sparc_encode_format3b((ins),2,(base),(disp),56,(dest))
-
-#define sparc_call_simple(ins,disp) sparc_encode_call((ins),((unsigned int)(disp)))
-
-#define sparc_rdy(ins,dest) sparc_encode_format3a((ins),2,0,0,0,40,(dest))
-
-#define sparc_wry(ins,base,disp) sparc_encode_format3a((ins),2,0,(base),(disp),48,0)
-#define sparc_wry_imm(ins,base,disp) sparc_encode_format3b((ins),2,(base),(disp),48,0)
-
-/* stbar, unimp, flush */
-#define sparc_stbar(ins) sparc_encode_format3a((ins),2,0,15,0,40,0)
-#define sparc_unimp(ins,val) sparc_encode_format2b((ins),0,0,0,(val))
-
-#define sparc_flush(ins,base,disp) sparc_encode_format3a((ins),2,0,(base),(disp),59,0)
-#define sparc_flush_imm(ins,base,disp) sparc_encode_format3b((ins),2,(base),(disp),59,0)
-
-#define sparc_flushw(ins) sparc_encode_format3a((ins),2,0,0,0,43,0)
-
-#define sparc_membar(ins,flags) sparc_encode_format3b ((ins), 2, 0xf, (flags), 0x28, 0)
-
-/* trap */
-
-#define sparc_ta(ins,tt) sparc_encode_format3b((ins),2,0,(tt),58,0x8)
-
-/* alu fop */
-/* provide wrappers for: fitos, fitod, fstoi, fdtoi, fstod, fdtos, fmov, fneg, fabs */
-
-#define sparc_fop(ins,r1,op,r2,dest) sparc_encode_format3c((ins),2,(op),(r1),52,(r2),(dest))
-#define sparc_fcmp(ins,r1,op,r2) sparc_encode_format3c((ins),2,(op),(r1),53,(r2),0)
-
-/* format 1 fops */
-#define sparc_fadds(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_fadds_val, r2, dest )
-#define sparc_faddd(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_faddd_val, r2, dest )
-#define sparc_faddq(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_faddq_val, r2, dest )
-
-#define sparc_fsubs(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_fsubs_val, r2, dest )
-#define sparc_fsubd(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_fsubd_val, r2, dest )
-#define sparc_fsubq(ins, r1, r2, dest) sparc_fop( ins, r1, sparc_fsubq_val, r2, dest )
-
-#define sparc_fmuls( ins, r1, r2, dest ) sparc_fop( ins, r1, sparc_fmuls_val, r2, dest )
-#define sparc_fmuld( ins, r1, r2, dest ) sparc_fop( ins, r1, sparc_fmuld_val, r2, dest )
-#define sparc_fmulq( ins, r1, r2, dest ) sparc_fop( ins, r1, sparc_fmulq_val, r2, dest )
-
-#define sparc_fsmuld( ins, r1, r2, dest ) sparc_fop( ins, r1, sparc_fsmuld_val, r2, dest )
-#define sparc_fdmulq( ins, r1, r2, dest ) sparc_fop( ins, r1, sparc_fdmulq_val, r2, dest )
-
-#define sparc_fdivs( ins, r1, r2, dest ) sparc_fop( ins, r1, sparc_fdivs_val, r2, dest )
-#define sparc_fdivd( ins, r1, r2, dest ) sparc_fop( ins, r1, sparc_fdivd_val, r2, dest )
-#define sparc_fdivq( ins, r1, r2, dest ) sparc_fop( ins, r1, sparc_fdivq_val, r2, dest )
-
-#define sparc_fitos( ins, r2, dest ) sparc_fop( ins, 0, sparc_fitos_val, r2, dest )
-#define sparc_fitod( ins, r2, dest ) sparc_fop( ins, 0, sparc_fitod_val, r2, dest )
-#define sparc_fitoq( ins, r2, dest ) sparc_fop( ins, 0, sparc_fitoq_val, r2, dest )
-
-#define sparc_fxtos( ins, r2, dest) sparc_fop( ins, 0, sparc_fxtos_val, r2, dest )
-#define sparc_fxtod( ins, r2, dest) sparc_fop( ins, 0, sparc_fxtod_val, r2, dest )
-#define sparc_fxtoq( ins, r2, dest) sparc_fop( ins, 0, sparc_fxtoq_val, r2, dest )
-
-#define sparc_fstoi( ins, r2, dest ) sparc_fop( ins, 0, sparc_fstoi_val, r2, dest )
-#define sparc_fdtoi( ins, r2, dest ) sparc_fop( ins, 0, sparc_fdtoi_val, r2, dest )
-#define sparc_fqtoi( ins, r2, dest ) sparc_fop( ins, 0, sparc_fqtoi_val, r2, dest )
-
-#define sparc_fstod( ins, r2, dest ) sparc_fop( ins, 0, sparc_fstod_val, r2, dest )
-#define sparc_fstoq( ins, r2, dest ) sparc_fop( ins, 0, sparc_fstoq_val, r2, dest )
-
-#define sparc_fdtos( ins, r2, dest ) sparc_fop( ins, 0, sparc_fdtos_val, r2, dest )
-#define sparc_fdtoq( ins, r2, dest ) sparc_fop( ins, 0, sparc_fdtoq_val, r2, dest )
-
-#define sparc_fqtos( ins, r2, dest ) sparc_fop( ins, 0, sparc_fqtos_val, r2, dest )
-#define sparc_fqtod( ins, r2, dest ) sparc_fop( ins, 0, sparc_fqtod_val, r2, dest )
-
-#define sparc_fmovs( ins, r2, dest ) sparc_fop( ins, 0, sparc_fmovs_val, r2, dest )
-#define sparc_fnegs( ins, r2, dest ) sparc_fop( ins, 0, sparc_fnegs_val, r2, dest )
-#define sparc_fabss( ins, r2, dest ) sparc_fop( ins, 0, sparc_fabss_val, r2, dest )
-
-#define sparc_fmovd( ins, r2, dest) sparc_fop (ins, 0, sparc_fmovd_val, r2, dest);
-#define sparc_fnegd( ins, r2, dest) sparc_fop (ins, 0, sparc_fnegd_val, r2, dest);
-#define sparc_fabsd( ins, r2, dest) sparc_fop (ins, 0, sparc_fabsd_val, r2, dest);
-
-#define sparc_fsqrts( ins, r2, dest ) sparc_fop( ins, 0, sparc_fsqrts_val, r2, dest )
-#define sparc_fsqrtd( ins, r2, dest ) sparc_fop( ins, 0, sparc_fsqrtd_val, r2, dest )
-#define sparc_fsqrtq( ins, r2, dest ) sparc_fop( ins, 0, sparc_fsqrtq_val, r2, dest )
-
-/* format 2 fops */
-
-#define sparc_fcmps( ins, r1, r2 ) sparc_fcmp( ins, r1, sparc_fcmps_val, r2 )
-#define sparc_fcmpd( ins, r1, r2 ) sparc_fcmp( ins, r1, sparc_fcmpd_val, r2 )
-#define sparc_fcmpq( ins, r1, r2 ) sparc_fcmp( ins, r1, sparc_fcmpq_val, r2 )
-#define sparc_fcmpes( ins, r1, r2 ) sparc_fcmpes( ins, r1, sparc_fcmpes_val, r2 )
-#define sparc_fcmped( ins, r1, r2 ) sparc_fcmped( ins, r1, sparc_fcmped_val, r2 )
-#define sparc_fcmpeq( ins, r1, r2 ) sparc_fcmpeq( ins, r1, sparc_fcmpeq_val, r2 )
-
-/* logical */
-
-/* FIXME: condense this using macros */
-/* FIXME: the setcc stuff is wrong in lots of places */
-
-#define sparc_logic(ins,op,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),((setcc) ? 0x10 : 0) | (op), (dest))
-#define sparc_logic_imm(ins,op,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),((setcc) ? 0x10 : 0) | (op), (dest))
-
-#define sparc_and(ins,setcc,r1,r2,dest) sparc_logic(ins,1,setcc,r1,r2,dest)
-#define sparc_and_imm(ins,setcc,r1,imm,dest) sparc_logic_imm(ins,1,setcc,r1,imm,dest)
-
-#define sparc_andn(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|5,(dest))
-#define sparc_andn_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|5,(dest))
-
-#define sparc_or(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|2,(dest))
-#define sparc_or_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|2,(dest))
-
-#define sparc_orn(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|6,(dest))
-#define sparc_orn_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|6,(dest))
-
-#define sparc_xor(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|3,(dest))
-#define sparc_xor_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm), (setcc)|3,(dest))
-
-#define sparc_xnor(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|7,(dest))
-#define sparc_xnor_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|7,(dest))
-
-/* shift */
-#define sparc_sll(ins,src,disp,dest) sparc_encode_format3a((ins),2,0,(src),(disp),37,(dest))
-#define sparc_sll_imm(ins,src,disp,dest) sparc_encode_format3b((ins),2,(src),(disp),37,(dest))
-
-/* Sparc V9 */
-#define sparc_sllx(ins,src,disp,dest) sparc_encode_format3ax((ins),2,0,(src),(disp),37,(dest))
-#define sparc_sllx_imm(ins,src,disp,dest) sparc_encode_format3bx((ins),2,(src),(disp),37,(dest))
-
-#define sparc_srl(ins,src,disp,dest) sparc_encode_format3a((ins),2,0,(src),(disp),38,(dest))
-#define sparc_srl_imm(ins,src,disp,dest) sparc_encode_format3b((ins),2,(src),(disp),38,(dest))
-
-/* Sparc V9 */
-#define sparc_srlx(ins,src,disp,dest) sparc_encode_format3ax((ins),2,0,(src),(disp),38,(dest))
-#define sparc_srlx_imm(ins,src,disp,dest) sparc_encode_format3bx((ins),2,(src),(disp),38,(dest))
-
-#define sparc_sra(ins,src,disp,dest) sparc_encode_format3a((ins),2,0,(src),(disp),39,(dest))
-#define sparc_sra_imm(ins,src,disp,dest) sparc_encode_format3b((ins),2,(src),(disp),39,(dest))
-
-/* Sparc V9 */
-#define sparc_srax(ins,src,disp,dest) sparc_encode_format3ax((ins),2,0,(src),(disp),39,(dest))
-#define sparc_srax_imm(ins,src,disp,dest) sparc_encode_format3bx((ins),2,(src),(disp),39,(dest))
-
-/* alu */
-
-#define sparc_alu_reg(ins,op,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),op|((setcc) ? 0x10 : 0),(dest))
-#define sparc_alu_imm(ins,op,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),op|((setcc) ? 0x10 : 0),(dest))
-
-#define sparc_add(ins,setcc,r1,r2,dest) sparc_alu_reg((ins),0,(setcc),(r1),(r2),(dest))
-#define sparc_add_imm(ins,setcc,r1,imm,dest) sparc_alu_imm((ins),0,(setcc),(r1),(imm),(dest))
-
-#define sparc_addx(ins,setcc,r1,r2,dest) sparc_alu_reg((ins),0x8,(setcc),(r1),(r2),(dest))
-#define sparc_addx_imm(ins,setcc,r1,imm,dest) sparc_alu_imm((ins),0x8,(setcc),(r1),(imm),(dest))
-
-#define sparc_sub(ins,setcc,r1,r2,dest) sparc_alu_reg((ins),0x4,(setcc),(r1),(r2),(dest))
-#define sparc_sub_imm(ins,setcc,r1,imm,dest) sparc_alu_imm((ins),0x4,(setcc),(r1),(imm),(dest))
-
-#define sparc_subx(ins,setcc,r1,r2,dest) sparc_alu_reg((ins),0xc,(setcc),(r1),(r2),(dest))
-#define sparc_subx_imm(ins,setcc,r1,imm,dest) sparc_alu_imm((ins),0xc,(setcc),(r1),(imm),(dest))
-
-#define sparc_muls(ins,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),36,(dest))
-#define sparc_muls_imm(ins,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),36,(dest))
-
-#define sparc_umul(ins,setcc,r1,r2,dest) sparc_alu_reg((ins),0xa,(setcc),(r1),(r2),(dest))
-#define sparc_umul_imm(ins,setcc,r1,imm,dest) sparc_alu_imm((ins),0xa,(setcc),(r1),(imm),(dest))
-
-#define sparc_smul(ins,setcc,r1,r2,dest) sparc_alu_reg((ins),0xb,(setcc),(r1),(r2),(dest))
-#define sparc_smul_imm(ins,setcc,r1,imm,dest) sparc_alu_imm((ins),0xb,(setcc),(r1),(imm),(dest))
-
-#define sparc_udiv(ins,setcc,r1,r2,dest) sparc_alu_reg((ins),0xe,(setcc),(r1),(r2),(dest))
-#define sparc_udiv_imm(ins,setcc,r1,imm,dest) sparc_alu_imm((ins),0xe,(setcc),(r1),(imm),(dest))
-
-#define sparc_sdiv(ins,setcc,r1,r2,dest) sparc_alu_reg((ins),0xf,(setcc),(r1),(r2),(dest))
-#define sparc_sdiv_imm(ins,setcc,r1,imm,dest) sparc_alu_imm((ins),0xf,(setcc),(r1),(imm),(dest))
-
-
-/* branch */
-#define sparc_branch(ins,aval,condval,displ) sparc_encode_format2b((ins),(aval),(condval),2,(displ))
-/* FIXME: float condition codes are different: unify. */
-#define sparc_fbranch(ins,aval,condval,displ) sparc_encode_format2b((ins),(aval),(condval),6,(displ))
-#define sparc_branchp(ins,aval,condval,xcc,predict,displ) sparc_encode_format2c((ins),(aval),(condval),0x1,(xcc),(predict),(displ))
-
-#define sparc_brz(ins,aval,predict,rs1,disp) sparc_encode_format2d((ins), (aval),0x1,0x3,(predict),(rs1),(disp))
-#define sparc_brlez(ins,aval,predict,rs1,disp) sparc_encode_format2d((ins), (aval),0x2,0x3,(predict),(rs1),(disp))
-#define sparc_brlz(ins,aval,predict,rs1,disp) sparc_encode_format2d((ins), (aval),0x3,0x3,(predict),(rs1),(disp))
-#define sparc_brnz(ins,aval,predict,rs1,disp) sparc_encode_format2d((ins), (aval),0x5,0x3,(predict),(rs1),(disp))
-#define sparc_brgz(ins,aval,predict,rs1,disp) sparc_encode_format2d((ins), (aval),0x6,0x3,(predict),(rs1),(disp))
-#define sparc_brgez(ins,aval,predict,rs1,disp) sparc_encode_format2d((ins), (aval),0x7,0x3,(predict),(rs1),(disp))
-
-/* conditional moves */
-#define sparc_movcc(ins,cc,condval,r1,dest) sparc_encode_format4c((ins), 0x2, 0x2c, cc, condval, r1, dest)
-
-#define sparc_movcc_imm(ins,cc,condval,imm,dest) sparc_encode_format4d((ins), 0x2, 0x2c, cc, condval, imm, dest)
-
-/* synthetic instructions */
-#define sparc_cmp(ins,r1,r2) sparc_sub((ins),sparc_cc,(r1),(r2),sparc_g0)
-#define sparc_cmp_imm(ins,r1,imm) sparc_sub_imm((ins),sparc_cc,(r1),(imm),sparc_g0)
-#define sparc_jmp(ins,base,disp) sparc_jmpl((ins),(base),(disp),sparc_g0)
-#define sparc_jmp_imm(ins,base,disp) sparc_jmpl_imm((ins),(base),(disp),sparc_g0)
-#define sparc_call(ins,base,disp) sparc_jmpl((ins),(base),(disp),sparc_o7)
-#define sparc_call_imm(ins,base,disp) sparc_jmpl_imm((ins),(base),(disp),sparc_o7)
-
-#define sparc_test(ins,reg) sparc_or ((ins),sparc_cc,sparc_g0,(reg),sparc_g0)
-
-#define sparc_ret(ins) sparc_jmpl_imm((ins),sparc_i7,8,sparc_g0)
-#define sparc_retl(ins) sparc_jmpl_imm((ins),sparc_o7,8,sparc_g0)
-#define sparc_restore_simple(ins) sparc_restore((ins),sparc_g0,sparc_g0,sparc_g0)
-#define sparc_rett_simple(ins) sparc_rett_imm((ins),sparc_i7,8)
-
-#define sparc_set32(ins,val,reg) \
- do { \
- if ((val) == 0) \
- sparc_clr_reg((ins),(reg)); \
- else if (((guint32)(val) & 0x3ff) == 0) \
- sparc_sethi((ins),(guint32)(val),(reg)); \
- else if (((gint32)(val) >= -4096) && ((gint32)(val) <= 4095)) \
- sparc_or_imm((ins),FALSE,sparc_g0,(gint32)(val),(reg)); \
- else { \
- sparc_sethi((ins),(guint32)(val),(reg)); \
- sparc_or_imm((ins),FALSE,(reg),(guint32)(val)&0x3ff,(reg)); \
- } \
- } while (0)
-
-#ifdef SPARCV9
-#define SPARC_SET_MAX_SIZE (6 * 4)
-#else
-#define SPARC_SET_MAX_SIZE (2 * 4)
-#endif
-
-#if SPARCV9
-#define sparc_set(ins,ptr,reg) \
- do { \
- g_assert ((reg) != sparc_g1); \
- gint64 val = (gint64)ptr; \
- guint32 top_word = (val) >> 32; \
- guint32 bottom_word = (val) & 0xffffffff; \
- if (val == 0) \
- sparc_clr_reg ((ins), reg); \
- else if ((val >= -4096) && ((val) <= 4095)) \
- sparc_or_imm((ins),FALSE,sparc_g0,bottom_word,(reg)); \
- else if ((val >= 0) && (val <= 4294967295L)) { \
- sparc_sethi((ins),bottom_word,(reg)); \
- if (bottom_word & 0x3ff) \
- sparc_or_imm((ins),FALSE,(reg),bottom_word&0x3ff,(reg)); \
- } \
- else if ((val >= 0) && (val <= (1L << 44) - 1)) { \
- sparc_sethi ((ins), (val >> 12), (reg)); \
- sparc_or_imm ((ins), FALSE, (reg), (val >> 12) & 0x3ff, (reg)); \
- sparc_sllx_imm ((ins),(reg), 12, (reg)); \
- sparc_or_imm ((ins), FALSE, (reg), (val) & 0xfff, (reg)); \
- } \
- else if (top_word == 0xffffffff) { \
- sparc_xnor ((ins), FALSE, sparc_g0, sparc_g0, sparc_g1); \
- sparc_sethi((ins),bottom_word,(reg)); \
- sparc_sllx_imm((ins),sparc_g1,32,sparc_g1); \
- sparc_or_imm((ins),FALSE,(reg),bottom_word&0x3ff,(reg)); \
- sparc_or((ins),FALSE,(reg),sparc_g1,(reg)); \
- } \
- else { \
- sparc_sethi((ins),top_word,sparc_g1); \
- sparc_sethi((ins),bottom_word,(reg)); \
- sparc_or_imm((ins),FALSE,sparc_g1,top_word&0x3ff,sparc_g1); \
- sparc_or_imm((ins),FALSE,(reg),bottom_word&0x3ff,(reg)); \
- sparc_sllx_imm((ins),sparc_g1,32,sparc_g1); \
- sparc_or((ins),FALSE,(reg),sparc_g1,(reg)); \
- } \
- } while (0)
-#else
-#define sparc_set(ins,val,reg) \
- do { \
- if ((val) == 0) \
- sparc_clr_reg((ins),(reg)); \
- else if (((guint32)(val) & 0x3ff) == 0) \
- sparc_sethi((ins),(guint32)(val),(reg)); \
- else if (((gint32)(val) >= -4096) && ((gint32)(val) <= 4095)) \
- sparc_or_imm((ins),FALSE,sparc_g0,(gint32)(val),(reg)); \
- else { \
- sparc_sethi((ins),(guint32)(val),(reg)); \
- sparc_or_imm((ins),FALSE,(reg),(guint32)(val)&0x3ff,(reg)); \
- } \
- } while (0)
-#endif
-
-#define sparc_set_ptr(ins,val,reg) sparc_set(ins,val,reg)
-
-#ifdef SPARCV9
-#define sparc_set_template(ins,reg) sparc_set (ins,0x7fffffff7fffffff, reg)
-#else
-#define sparc_set_template(ins,reg) sparc_set (ins,0x7fffffff, reg)
-#endif
-
-#define sparc_not(ins,reg) sparc_xnor((ins),FALSE,(reg),sparc_g0,(reg))
-#define sparc_neg(ins,reg) sparc_sub((ins),FALSE,sparc_g0,(reg),(reg))
-#define sparc_clr_reg(ins,reg) sparc_or((ins),FALSE,sparc_g0,sparc_g0,(reg))
-
-#define sparc_mov_reg_reg(ins,src,dest) sparc_or((ins),FALSE,sparc_g0,(src),(dest))
-
-#ifdef SPARCV9
-#define sparc_sti_imm sparc_stx_imm
-#define sparc_ldi_imm sparc_ldx_imm
-#define sparc_sti sparc_stx
-#define sparc_ldi sparc_ldx
-#else
-#define sparc_sti_imm sparc_st_imm
-#define sparc_ldi_imm sparc_ld_imm
-#define sparc_sti sparc_st
-#define sparc_ldi sparc_ld
-#endif
-
-#endif /* __SPARC_CODEGEN_H__ */
-
+++ /dev/null
-#include <glib.h>
-#include "sparc-codegen.h"
-
-/* don't run the resulting program, it will destroy your computer,
- * just objdump -d it to inspect we generated the correct assembler.
- */
-
-int
-main ()
-{
- guint32 *p;
- guint32 code_buffer [500];
- guint32 local_size = 0, stack_size = 0, code_size = 6;
- guint32 arg_pos, simpletype;
- unsigned char *ins;
- int i, stringp, cur_out_reg, size;
-
- p = code_buffer;
-
- printf (".text\n.align 4\n.globl main\n.type main,@function\nmain:\n");
-
- /*
- * Standard function prolog.
- */
- sparc_save_imm (p, sparc_sp, -112-stack_size, sparc_sp);
- cur_out_reg = sparc_o0;
- arg_pos = 0;
-
- if (1) {
- sparc_mov_reg_reg (p, sparc_i2, cur_out_reg);
- ++cur_out_reg;
- }
-
- sparc_ld_imm (p, sparc_i3, arg_pos, cur_out_reg);
- ++cur_out_reg;
- sparc_ld_imm (p, sparc_i3, arg_pos+4, cur_out_reg);
- ++cur_out_reg;
- /*
- * Insert call to function
- */
- sparc_jmpl (p, sparc_i0, 0, sparc_callsite);
- sparc_nop (p);
-
- sparc_jmpl_imm (p, sparc_i7, 8, sparc_zero);
- sparc_restore (p, sparc_zero, sparc_zero, sparc_zero);
-
- sparc_ldsb (p, sparc_i3, sparc_l0, sparc_o5);
- sparc_ldsb_imm (p, sparc_i3, 2, sparc_o5);
-
- sparc_ldsh (p, sparc_i3, sparc_l0, sparc_o5);
- sparc_ldsh_imm (p, sparc_i3, 2, sparc_o5);
-
- sparc_ldub (p, sparc_i3, sparc_l0, sparc_o5);
- sparc_ldub_imm (p, sparc_i3, 2, sparc_o5);
-
- sparc_lduh (p, sparc_i3, sparc_l0, sparc_o5);
- sparc_lduh_imm (p, sparc_i3, 2, sparc_o5);
-
- sparc_ldf (p, sparc_i3, sparc_l0, sparc_o5);
- sparc_ldf_imm (p, sparc_i3, 2, sparc_o5);
-
- sparc_stb (p, sparc_i3, sparc_l0, sparc_l2);
- sparc_stb_imm (p, sparc_i3, sparc_o5, 2);
-
- sparc_sethi (p, 0xff000000, sparc_o2);
- sparc_rdy (p, sparc_l0);
- sparc_wry (p, sparc_l0, sparc_l1);
- sparc_wry_imm (p, sparc_l0, 16);
- sparc_stbar (p);
- sparc_unimp (p, 24);
- sparc_flush (p, sparc_l4, 0);
-
- sparc_and (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
- sparc_and_imm (p, FALSE, sparc_l0, 0xff, sparc_o1);
- sparc_andn (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
- sparc_or (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
- sparc_orn (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
- sparc_xor (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
- sparc_xnor (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
-
- sparc_sll (p, sparc_l0, sparc_l1, sparc_o1);
- sparc_sll_imm (p, sparc_l0, 2, sparc_o1);
- sparc_srl (p, sparc_l0, sparc_l1, sparc_o1);
- sparc_srl_imm (p, sparc_l0, 2, sparc_o1);
- sparc_sra (p, sparc_l0, sparc_l1, sparc_o1);
- sparc_sra_imm (p, sparc_l0, 2, sparc_o1);
-
- sparc_add (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
- sparc_add_imm (p, FALSE, sparc_l0, 0xff, sparc_o1);
- sparc_addx (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
- sparc_sub (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
- sparc_subx (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
-
- sparc_muls (p, sparc_l0, sparc_l1, sparc_o1);
- sparc_umul (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
- sparc_smul (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
- sparc_udiv (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
- sparc_sdiv (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
-
- sparc_branch (p, FALSE, sparc_bne, -12);
- sparc_ret (p);
- sparc_retl (p);
- sparc_test (p, sparc_l4);
- sparc_cmp (p, sparc_l4, sparc_l6);
- sparc_cmp_imm (p, sparc_l4, 4);
- sparc_restore_simple (p);
-
- sparc_set (p, 0xff000000, sparc_l7);
- sparc_set (p, 1, sparc_l7);
- sparc_set (p, 0xff0000ff, sparc_l7);
-
- sparc_not (p, sparc_g2);
- sparc_neg (p, sparc_g3);
- sparc_clr_reg (p, sparc_g4);
-
-
- size = (p-code_buffer)*4;
- ins = (gchar*)code_buffer;
- for (i = 0; i < size; ++i)
- printf (".byte %d\n", (unsigned int) ins [i]);
- return 0;
-}
-
return mono_atomic_dec_i32 (&assembly->ref_count);
}
-/*
- * CAUTION: This table must be kept in sync with
- * ivkm/reflect/Fusion.cs
- */
-
-#define SILVERLIGHT_KEY "7cec85d7bea7798e"
-#define WINFX_KEY "31bf3856ad364e35"
-#define ECMA_KEY "b77a5c561934e089"
-#define MSFINAL_KEY "b03f5f7f11d50a3a"
-#define COMPACTFRAMEWORK_KEY "969db8053d3322ac"
-
-typedef struct {
- const char *name;
- const char *from;
- const char *to;
-} KeyRemapEntry;
-
-static KeyRemapEntry key_remap_table[] = {
- { "CustomMarshalers", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
- { "Microsoft.CSharp", WINFX_KEY, MSFINAL_KEY },
- { "Microsoft.VisualBasic", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
- { "System", SILVERLIGHT_KEY, ECMA_KEY },
- { "System", COMPACTFRAMEWORK_KEY, ECMA_KEY },
- { "System.ComponentModel.Composition", WINFX_KEY, ECMA_KEY },
- { "System.ComponentModel.DataAnnotations", "ddd0da4d3e678217", WINFX_KEY },
- { "System.Core", SILVERLIGHT_KEY, ECMA_KEY },
- { "System.Core", COMPACTFRAMEWORK_KEY, ECMA_KEY },
- { "System.Data", COMPACTFRAMEWORK_KEY, ECMA_KEY },
- { "System.Data.DataSetExtensions", COMPACTFRAMEWORK_KEY, ECMA_KEY },
- { "System.Drawing", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
- { "System.Messaging", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
- // FIXME: MS uses MSFINAL_KEY for .NET 4.5
- { "System.Net", SILVERLIGHT_KEY, MSFINAL_KEY },
- { "System.Numerics", WINFX_KEY, ECMA_KEY },
- { "System.Runtime.Serialization", SILVERLIGHT_KEY, ECMA_KEY },
- { "System.Runtime.Serialization", COMPACTFRAMEWORK_KEY, ECMA_KEY },
- { "System.ServiceModel", WINFX_KEY, ECMA_KEY },
- { "System.ServiceModel", COMPACTFRAMEWORK_KEY, ECMA_KEY },
- { "System.ServiceModel.Web", SILVERLIGHT_KEY, WINFX_KEY },
- { "System.Web.Services", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
- { "System.Windows", SILVERLIGHT_KEY, MSFINAL_KEY },
- { "System.Windows.Forms", COMPACTFRAMEWORK_KEY, ECMA_KEY },
- { "System.Xml", SILVERLIGHT_KEY, ECMA_KEY },
- { "System.Xml", COMPACTFRAMEWORK_KEY, ECMA_KEY },
- { "System.Xml.Linq", WINFX_KEY, ECMA_KEY },
- { "System.Xml.Linq", COMPACTFRAMEWORK_KEY, ECMA_KEY },
- { "System.Xml.Serialization", WINFX_KEY, ECMA_KEY }
-};
-
-static void
-remap_keys (MonoAssemblyName *aname)
-{
- int i;
- for (i = 0; i < G_N_ELEMENTS (key_remap_table); i++) {
- const KeyRemapEntry *entry = &key_remap_table [i];
-
- if (strcmp (aname->name, entry->name) ||
- !mono_public_tokens_are_equal (aname->public_key_token, (const unsigned char*) entry->from))
- continue;
-
- memcpy (aname->public_key_token, entry->to, MONO_PUBLIC_KEY_TOKEN_LENGTH);
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY,
- "Remapped public key token of retargetable assembly %s from %s to %s",
- aname->name, entry->from, entry->to);
- return;
- }
-}
-
static MonoAssemblyName *
mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_aname)
{
if (!strcmp (aname->name, "System.Net"))
dest_aname->name = g_strdup ("System");
- remap_keys (dest_aname);
-
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY,
"The request to load the retargetable assembly %s v%d.%d.%d.%d was remapped to %s v%d.%d.%d.%d",
aname->name,
return NULL;
}
- if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
- if (!strncmp (name, "Vector", 6))
- klass->simd_type = !strcmp (name + 6, "2d") || !strcmp (name + 6, "2ul") || !strcmp (name + 6, "2l") || !strcmp (name + 6, "4f") || !strcmp (name + 6, "4ui") || !strcmp (name + 6, "4i") || !strcmp (name + 6, "8s") || !strcmp (name + 6, "8us") || !strcmp (name + 6, "16b") || !strcmp (name + 6, "16sb");
- } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
+#if 0 // FIXME this causes an issue when AOT compiling using llvm:
+ if (mono_is_corlib_image (klass->image) && !strcmp (nspace, "System.Numerics")) {
/* The JIT can't handle SIMD types with != 16 size yet */
//if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
if (!strcmp (name, "Vector4"))
klass->simd_type = 1;
}
+#endif
// compute is_byreflike
if (m_class_is_valuetype (klass))
klass->enumtype = gklass->enumtype;
klass->valuetype = gklass->valuetype;
- if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
- g_assert (gclass->context.class_inst);
- g_assert (gclass->context.class_inst->type_argc > 0);
- if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
- klass->simd_type = 1;
- }
-
if (mono_is_corlib_image (gklass->image) &&
(!strcmp (gklass->name, "Vector`1") || !strcmp (gklass->name, "Vector64`1") || !strcmp (gklass->name, "Vector128`1") || !strcmp (gklass->name, "Vector256`1"))) {
MonoType *etype = gclass->context.class_inst->type_argv [0];
*/
MonoObject* mono_gc_alloc_fixed (size_t size, MonoGCDescriptor descr, MonoGCRootSource source, void *key, const char *msg);
-// C++ callers outside of metadata (mini/tasklets.c) must use mono_gc_alloc_fixed_no_descriptor
+// C++ callers outside of metadata must use mono_gc_alloc_fixed_no_descriptor
// instead of mono_gc_alloc_fixed, or else compile twice -- boehm and sgen.
MonoObject*
mono_gc_alloc_fixed_no_descriptor (size_t size, MonoGCRootSource source, void *key, const char *msg);
* ARM has no definition for some atomic functions in gc_locks.h and
* support is also disabled in libgc/configure.ac.
*/
-# if !defined(__sparc__) && !defined(__sun) && !defined(__arm__) && !defined(__mips__)
+# if !defined(__sun) && !defined(__arm__)
# define GC_REDIRECT_TO_LOCAL
# endif
# endif
res->type = iter->sig->params [i];
res->klass = mono_class_from_mono_type_internal (res->type);
arg_size = mono_type_stack_size (res->type, &align);
-#if defined(__arm__) || defined(__mips__)
+#if defined(__arm__)
iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
#endif
res->value = iter->args;
res->klass = mono_class_from_mono_type_internal (res->type);
/* FIXME: endianess issue... */
arg_size = mono_type_stack_size (res->type, &align);
-#if defined(__arm__) || defined(__mips__)
+#if defined(__arm__)
iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
#endif
res->value = iter->args;
typedef struct { gpointer i; } gpointer_struct;
#endif
-static int
-dump_arch (void)
-{
-#if defined (TARGET_X86)
- g_print ("#ifdef TARGET_X86\n");
-#elif defined (TARGET_AMD64)
- g_print ("#ifdef TARGET_AMD64\n");
-#elif defined (TARGET_ARM)
- g_print ("#ifdef TARGET_ARM\n");
-#elif defined (TARGET_ARM64)
- g_print ("#ifdef TARGET_ARM64\n");
-#elif defined (TARGET_RISCV32)
- g_print ("#ifdef TARGET_RISCV32\n");
-#elif defined (TARGET_RISCV64)
- g_print ("#ifdef TARGET_RISCV64\n");
-#else
- return 0;
-#endif
- return 1;
-}
-
-static int
-dump_os (void)
-{
-#if defined (HOST_WIN32)
- g_print ("#ifdef TARGET_WIN32\n");
-#elif defined (HOST_ANDROID)
- g_print ("#ifdef TARGET_ANDROID\n");
-#elif defined (HOST_DARWIN)
- g_print ("#ifdef TARGET_OSX\n");
-#elif defined (PLATFORM_IOS)
- g_print ("#ifdef TARGET_IOS\n");
-#else
- return 0;
-#endif
- return 1;
-}
-
-void
-mono_dump_metadata_offsets (void);
-
-void
-mono_dump_metadata_offsets (void)
-{
-#ifdef USED_CROSS_COMPILER_OFFSETS
- g_print ("not using native offsets\n");
-#else
- g_print ("#ifndef USED_CROSS_COMPILER_OFFSETS\n");
-
- if (!dump_arch ()) {
- g_print ("#error failed to figure out the current arch\n");
- return;
- }
-
- if (!dump_os ()) {
- g_print ("#error failed to figure out the current OS\n");
- return;
- }
-
-#ifdef HAVE_SGEN_GC
- g_print ("#ifndef HAVE_BOEHM_GC\n");
-#elif HAVE_BOEHM_GC
- g_print ("#ifndef HAVE_SGEN_GC\n");
-#else
- g_print ("#error no gc conf not supported\n");
- return;
-#endif
-
- g_print ("#define HAS_CROSS_COMPILER_OFFSETS\n");
- g_print ("#if defined (USE_CROSS_COMPILE_OFFSETS) || defined (MONO_CROSS_COMPILE)\n");
- g_print ("#if !defined (DISABLE_METADATA_OFFSETS)\n");
- g_print ("#define USED_CROSS_COMPILER_OFFSETS\n");
-
-#define DISABLE_JIT_OFFSETS
-#define DECL_OFFSET2(struct,field,offset) this_should_not_happen
-#define DECL_ALIGN2(type,size) this_should_not_happen
-
-#define DECL_OFFSET(struct,field) g_print ("DECL_OFFSET2(%s,%s,%d)\n", #struct, #field, (int)MONO_STRUCT_OFFSET (struct, field));
-#define DECL_ALIGN(type) g_print ("DECL_ALIGN2(%s,%d)\n", #type, (int)MONO_ABI_ALIGNOF (type));
-#define DECL_SIZE(type) g_print ("DECL_SIZE2(%s,%d)\n", #type, (int)MONO_ABI_SIZEOF (type));
-#include <mono/metadata/object-offsets.h>
-
- g_print ("#endif //disable metadata check\n");
- g_print ("#endif //gc check\n");
-#endif
-}
-
void
mono_metadata_cross_helpers_run (void);
#elif defined(__x86_64__) || defined(_M_X64) || defined(TARGET_AMD64)
#define CONFIG_CPU "x86-64"
#define CONFIG_WORDSIZE "64"
-#elif defined(sparc) || defined(__sparc__)
-#define CONFIG_CPU "sparc"
-#define CONFIG_WORDSIZE "32"
#elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_64) || defined(TARGET_POWERPC)
#define CONFIG_WORDSIZE "64"
#ifdef __mono_ppc_ilp32__
#elif defined(__aarch64__) || defined(TARGET_ARM64)
#define CONFIG_CPU "armv8"
#define CONFIG_WORDSIZE "64"
-#elif defined(mips) || defined(__mips) || defined(_mips)
-#define CONFIG_CPU "mips"
-#define CONFIG_WORDSIZE "32"
#elif defined (TARGET_RISCV32)
#define CONFIG_CPU "riscv32"
#define CONFIG_WORDSIZE "32"
+++ /dev/null
-<plist version="1.0">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>English</string>
- <key>CFBundleIdentifier</key>
- <string>com.novell.mono</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>mono</string>
- <key>CFBundleVersion</key>
- <string>0.3</string>
- <key>SecTaskAccess</key>
- <string>allowed</string>
-</dict>
-</plist>
#define AS_OPTIONS "--64"
#elif defined(TARGET_POWERPC64)
#define AS_OPTIONS "-a64 -mppc64"
-#elif defined(sparc) && TARGET_SIZEOF_VOID_P == 8
-#define AS_OPTIONS "-xarch=v9"
#elif defined(TARGET_X86) && defined(TARGET_MACH)
#define AS_OPTIONS "-arch i386"
#elif defined(TARGET_X86) && !defined(TARGET_MACH)
#define AS_OBJECT_FILE_SUFFIX "o"
#endif
-#if defined(sparc)
-#define LD_NAME "ld"
-#define LD_OPTIONS "-shared -G -Bsymbolic"
-#elif defined(__ppc__) && defined(TARGET_MACH)
+#if defined(__ppc__) && defined(TARGET_MACH)
#define LD_NAME "gcc"
#define LD_OPTIONS "-dynamiclib -Wl,-Bsymbolic"
#elif defined(TARGET_AMD64) && defined(TARGET_MACH)
+++ /dev/null
-using System;
-using Mono.Simd;
-
-public class SimdTests {
- static int ddd;
- static void InitByRef (out Vector4i v) {
- v = new Vector4i (99);
- if (ddd > 10)
- throw new Exception ("ddd");
- }
-
- static int test_0_vector4i_one_element_ctor_with_byref ()
- {
- Vector4i a;
- InitByRef (out a);
- if (a.X != 99)
- return 1;
- if (a.Y != 99)
- return 2;
- if (a.Z != 99)
- return 3;
- if (a.W != 99)
- return 4;
- return 0;
- }
-
- static int test_0_vector2d_one_element_ctor () {
- Vector2d a = new Vector2d (99);
- if (a.X != 99)
- return 1;
- if (a.Y != 99)
- return 2;
- return 0;
- }
-
- static int test_0_vector2ul_one_element_ctor () {
- Vector2ul a = new Vector2ul (99);
-
- if (a.X != 99)
- return 1;
- if (a.Y != 99)
- return 2;
- return 0;
- }
-
- static int test_0_vector2l_one_element_ctor () {
- Vector2l a = new Vector2l (99);
-
- if (a.X != 99)
- return 1;
- if (a.Y != 99)
- return 2;
- return 0;
- }
-
- static int test_0_vector4f_one_element_ctor () {
- Vector4f a = new Vector4f (99);
-
- if (a.X != 99)
- return 1;
- if (a.Y != 99)
- return 2;
- if (a.Z != 99)
- return 3;
- if (a.W != 99)
- return 4;
- return 0;
- }
-
- static int test_0_vector4ui_one_element_ctor () {
- Vector4ui a = new Vector4ui (99);
-
- if (a.X != 99)
- return 1;
- if (a.Y != 99)
- return 2;
- if (a.Z != 99)
- return 3;
- if (a.W != 99)
- return 4;
- return 0;
- }
-
- static int test_0_vector4i_one_element_ctor () {
- Vector4i a = new Vector4i (99);
-
- if (a.X != 99)
- return 1;
- if (a.Y != 99)
- return 2;
- if (a.Z != 99)
- return 3;
- if (a.W != 99)
- return 4;
- return 0;
- }
-
- static int test_0_vector8us_one_element_ctor () {
- Vector8us a = new Vector8us (99);
-
- if (a.V0 != 99)
- return 1;
- if (a.V1 != 99)
- return 2;
- if (a.V2 != 99)
- return 3;
- if (a.V3 != 99)
- return 4;
- if (a.V4 != 99)
- return 5;
- if (a.V5 != 99)
- return 6;
- if (a.V6 != 99)
- return 7;
- if (a.V7 != 99)
- return 8;
- return 0;
- }
-
- static int test_0_vector8s_one_element_ctor () {
- Vector8s a = new Vector8s (99);
-
- if (a.V0 != 99)
- return 1;
- if (a.V1 != 99)
- return 2;
- if (a.V2 != 99)
- return 3;
- if (a.V3 != 99)
- return 4;
- if (a.V4 != 99)
- return 5;
- if (a.V5 != 99)
- return 6;
- if (a.V6 != 99)
- return 7;
- if (a.V7 != 99)
- return 8;
- return 0;
- }
-
- static int test_0_vector16sb_one_element_ctor () {
- Vector16sb a = new Vector16sb (99);
-
- if (a.V0 != 99)
- return 1;
- if (a.V1 != 99)
- return 2;
- if (a.V2 != 99)
- return 3;
- if (a.V3 != 99)
- return 4;
- if (a.V4 != 99)
- return 5;
- if (a.V5 != 99)
- return 6;
- if (a.V6 != 99)
- return 7;
- if (a.V7 != 99)
- return 8;
- if (a.V8 != 99)
- return 9;
- if (a.V9 != 99)
- return 10;
- if (a.V10 != 99)
- return 11;
- if (a.V11 != 99)
- return 12;
- if (a.V12 != 99)
- return 13;
- if (a.V13 != 99)
- return 14;
- if (a.V14 != 99)
- return 15;
- if (a.V15 != 99)
- return 16;
- return 0;
- }
-
- static int test_0_vector16b_one_element_ctor () {
- Vector16b a = new Vector16b (99);
-
- if (a.V0 != 99)
- return 1;
- if (a.V1 != 99)
- return 2;
- if (a.V2 != 99)
- return 3;
- if (a.V3 != 99)
- return 4;
- if (a.V4 != 99)
- return 5;
- if (a.V5 != 99)
- return 6;
- if (a.V6 != 99)
- return 7;
- if (a.V7 != 99)
- return 8;
- if (a.V8 != 99)
- return 9;
- if (a.V9 != 99)
- return 10;
- if (a.V10 != 99)
- return 11;
- if (a.V11 != 99)
- return 12;
- if (a.V12 != 99)
- return 13;
- if (a.V13 != 99)
- return 14;
- if (a.V14 != 99)
- return 15;
- if (a.V15 != 99)
- return 16;
- return 0;
- }
-
- public static unsafe int test_0_sizeof_returns_16_2d ()
- {
- double[] array = new double[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- fixed (double *ptr = &array [0]) {
- Vector2d *f = (Vector2d*)ptr;
- Vector2d a = *f++;
- Vector2d b = *f++;
- Vector2d c = *f++;
- Vector2d d = *f++;
-
- if (a.X != 1 || a.Y != 2)
- return 1;
- if (b.X != 3 || b.Y != 4)
- return 2;
- if (c.X != 5 || c.Y != 6)
- return 3;
- if (d.X != 7 || d.Y != 8)
- return 4;
- }
- return 0;
- }
-
- public static unsafe int test_0_sizeof_returns_16_4f ()
- {
- float[] array = new float[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
- fixed (float *ptr = &array [0]) {
- Vector4f *f = (Vector4f*)ptr;
- Vector4f a = *f++;
- Vector4f b = *f++;
- Vector4f c = *f++;
- Vector4f d = *f++;
-
- if (a.X != 1 || a.W != 4)
- return 1;
- if (b.X != 5 || b.W != 8)
- return 2;
- if (c.X != 9 || c.W != 12)
- return 3;
- if (d.X != 13 || d.W != 16)
- return 4;
- }
- return 0;
- }
-
- public static unsafe int test_0_sizeof_returns_16_8d ()
- {
- short[] array = new short[40];
- for (int i = 0; i < 40; ++i)
- array [i] = (short) (i + 1);
-
- fixed (short *ptr = &array [0]) {
- Vector8s *f = (Vector8s*)ptr;
- Vector8s a = *f++;
- Vector8s b = *f++;
- Vector8s c = *f++;
- Vector8s d = *f++;
-
- if (a.V0 != 1 || a.V7 != 8)
- return 1;
- if (b.V0 != 9 || b.V7 != 16)
- return 2;
- if (c.V0 != 17 || c.V7 != 24)
- return 3;
- if (d.V0 != 25 || d.V7 != 32)
- return 4;
- }
- return 0;
- }
-
- public static unsafe int test_0_sizeof_returns_16_16b ()
- {
- byte[] array = new byte[80];
- for (int i = 0; i < 80; ++i)
- array [i] = (byte) (i + 1);
-
- fixed (byte *ptr = &array [0]) {
- Vector16b *f = (Vector16b*)ptr;
- Vector16b a = *f++;
- Vector16b b = *f++;
- Vector16b c = *f++;
- Vector16b d = *f++;
-
- if (a.V0 != 1 || a.V15 != 16)
- return 1;
- if (b.V0 != 17 || b.V15 != 32)
- return 2;
- if (c.V0 != 33 || c.V15 != 48)
- return 3;
- if (d.V0 != 49 || d.V15 != 64)
- return 4;
- }
- return 0;
- }
- public static int test_0_bug_462457 ()
- {
- Vector4f sum = new Vector4f(0,0,0,0);
- Vector4f add = new Vector4f(1.0F,1.0F,1.0F,1.0F);
-
- for (int i = 0; i < 10; ++i)
- sum = sum + add;
-
- if (sum.X != 10f)
- return 1;
- return 0;
- }
-
- public static int test_0_vector16b_operator_neq () {
- Vector16b a = new Vector16b(1,2,3,5,5,6,7,8,1,2,3,5,5,6,7,8);
- Vector16b b = new Vector16b(1,2,3,5,5,6,7,8,1,2,3,5,5,6,7,8);
- if (a != b)
- return 1;
- b.V0 = 99;
- if (!(a != b))
- return 2;
- return 0;
- }
-
- public static int test_0_vector16b_operator_eq () {
- Vector16b a = new Vector16b(1,2,3,5,5,6,7,8,1,2,3,5,5,6,7,8);
- Vector16b b = new Vector16b(1,2,3,5,5,6,7,8,1,2,3,5,5,6,7,8);
- if (!(a == b))
- return 1;
- b.V0 = 99;
- if (a == b)
- return 2;
- return 0;
- }
-
- public static int test_0_vector8us_operator_neq () {
- Vector8us a = new Vector8us(1, 2, 3, 4, 5, 6, 7, 8);
- Vector8us b = new Vector8us(1, 2, 3, 4, 5, 6, 7, 8);
- if (a != b)
- return 1;
- b.V0 = 99;
- if (!(a != b))
- return 2;
- return 0;
- }
-
- public static int test_0_vector8us_operator_eq () {
- Vector8us a = new Vector8us(1, 2, 3, 4, 5, 6, 7, 8);
- Vector8us b = new Vector8us(1, 2, 3, 4, 5, 6, 7, 8);
- if (!(a == b))
- return 1;
- b.V0 = 99;
- if (a == b)
- return 2;
- return 0;
- }
-
- public static int test_0_set_vector4f_operator_neq () {
- Vector4f a = new Vector4f(1, 2, 3, 4);
- Vector4f b = new Vector4f(1, 2, 3, 4);
- if (a != b)
- return 1;
-
- a = new Vector4f(1, 2, float.NaN, 4);
- b = new Vector4f(1, 2, float.NaN, 4);
- if (!(a != b)) //NaN is always !=
- return 2;
-
- a = new Vector4f(1, 2, float.NaN, 4);
- b = new Vector4f(1, 2, 10, 4);
- if (!(a != b))
- return 3;
-
- a = new Vector4f(1, 2, float.PositiveInfinity, 4);
- b = new Vector4f(1, 2, float.PositiveInfinity, 4);
- if (a != b)
- return 4;
-
- a = new Vector4f(1, 2, 20, 4);
- b = new Vector4f(1, 2, 30, 4);
- if (!(a != b))
- return 5;
-
- return 0;
- }
-
- public static int test_0_set_vector4f_operator_eq () {
- Vector4f a = new Vector4f(1, 2, 3, 4);
- Vector4f b = new Vector4f(1, 2, 3, 4);
- if (!(a == b))
- return 1;
-
- a = new Vector4f(1, 2, float.NaN, 4);
- b = new Vector4f(1, 2, float.NaN, 4);
- if (a == b)
- return 2;
-
- a = new Vector4f(1, 2, 10, 4);
- b = new Vector4f(1, 2, float.NaN, 4);
- if (a == b)
- return 3;
-
- a = new Vector4f(1, 2, float.PositiveInfinity, 4);
- b = new Vector4f(1, 2, float.PositiveInfinity, 4);
- if (!(a == b))
- return 4;
- return 0;
- }
-
- public static int test_1_set_vector4ui_operator_neq () {
- Vector4ui a = new Vector4ui(1, 2, 3, 4);
- Vector4ui b = new Vector4ui(1, 2, 3, 4);
- if (a != b)
- return 0;
- return 1;
- }
-
- public static int test_0_set_vector4ui_operator_neq () {
- Vector4ui a = new Vector4ui(1, 2, 3, 4);
- Vector4ui b = new Vector4ui(111, 2, 3, 4);
- if (a != b)
- return 0;
- return 1;
- }
-
- public static int test_0_set_vector4ui_operator_eq () {
- Vector4ui a = new Vector4ui(1, 2, 3, 4);
- Vector4ui b = new Vector4ui(1, 2, 3, 4);
- if (a == b)
- return 0;
- return 1;
- }
-
- public static int test_1_set_vector4ui_operator_eq () {
- Vector4ui a = new Vector4ui(1, 2, 3, 4);
- Vector4ui b = new Vector4ui(111, 2, 3, 4);
- if (a == b)
- return 0;
- return 1;
- }
-
- public static int test_0_set_vector_small_array () {
- uint[] array = new uint[3];
-
- try {
- array.SetVector (new Vector4ui (), 0);
- return 1;
- } catch (IndexOutOfRangeException) {
- }
- return 0;
- }
-
- public static int test_0_set_vector_negative_index () {
- uint[] array = new uint[4];
-
- try {
- array.SetVector (new Vector4ui (), -1);
- return 1;
- } catch (IndexOutOfRangeException) {
- }
- return 0;
- }
-
- public static int test_0_set_vector_bounds_error () {
- uint[] array = new uint[4];
-
- try {
- array.SetVector (new Vector4ui (), 1);
- return 1;
- } catch (IndexOutOfRangeException) {
- }
- return 0;
- }
-
- public static int test_0_set_vector () {
- uint[] array = new uint[10];
- Vector4ui a = new Vector4ui (11, 22, 33, 44);
-
- array.SetVector (a, 1);
-
- if (array [1] != 11)
- return 1;
- if (array [2] != 22)
- return 2;
- if (array [3] != 33)
- return 3;
- if (array [4] != 44)
- return 4;
- return 0;
- }
-
- public static int test_0_get_vector_small_array () {
- uint[] array = new uint[3];
-
- try {
- Vector4ui res = array.GetVector (0);
- return 1;
- } catch (IndexOutOfRangeException) {
- }
- return 0;
- }
-
- public static int test_0_get_vector_negative_index () {
- uint[] array = new uint[4];
-
- try {
- Vector4ui res = array.GetVector (-1);
- return 1;
- } catch (IndexOutOfRangeException) {
- }
- return 0;
- }
-
- public static int test_0_get_vector_bounds_error () {
- uint[] array = new uint[4];
-
- try {
- Vector4ui res = array.GetVector (1);
- return 1;
- } catch (IndexOutOfRangeException) {
- }
- return 0;
- }
-
- public static int test_0_get_vector () {
- uint[] array = new uint[] { 11, 22, 33, 44, 55, 66, 77, 88, 99, 111 };
-
- Vector4ui res = array.GetVector (1);
-
- if (res.X != 22)
- return 1;
- if (res.Y != 33)
- return 2;
- if (res.Z != 44)
- return 3;
- if (res.W != 55)
- return 4;
-
- return 0;
- }
-
- public static int test_0_accessor_vecto2l () {
- Vector2l a = new Vector2l (3, 2);
-
- if (a.X != 3)
- return 1;
- if (a.Y != 2)
- return 2;
-
- a.X = 500000000000055L;
- a.Y = -12345678900L;
-
- if (a.X != 500000000000055L)
- return 3;
- if (a.Y != -12345678900L)
- return 4;
- return 0;
- }
-
- public static int test_0_accessor_vecto2d () {
- Vector2d a = new Vector2d (3, 2);
-
- if (a.X != 3)
- return 1;
- if (a.Y != 2)
- return 2;
-
- a.X = 5000000000000;
- a.Y = -0.5;
-
- if (a.X != 5000000000000)
- return 3;
- if (a.Y != -0.5)
- return 4;
- return 0;
- }
-
- public static int test_0_accessor_vecto4f () {
- Vector4f a = new Vector4f (1,2,3,4);
-
- if (a.X != 1)
- return 1;
- if (a.Y != 2)
- return 2;
- if (a.Z != 3)
- return 3;
- if (a.W != 4)
- return 4;
-
- a.X = 128f;
- a.Y = 256f;
- a.Z = -0.5f;
- a.W = 0.125f;
-
- if (a.X != 128)
- return 5;
- if (a.Y != 256)
- return 6;
- if (a.Z != -0.5)
- return 7;
- if (a.W != 0.125)
- return 8;
- return 0;
- }
-
- public static int test_0_accessor_vecto4i () {
- Vector4i a = new Vector4i (0x70000000, -1, 3, 4);
-
- if (a.X != 0x70000000)
- return 1;
- if (a.Y != -1)
- return 2;
- if (a.Z != 3)
- return 3;
- if (a.W != 4)
- return 4;
-
- a.X = 11;
- a.Y = 22;
- a.Z = 33333344;
- a.W = -44444444;
-
- if (a.X != 11)
- return 5;
- if (a.Y != 22)
- return 6;
- if (a.Z != 33333344)
- return 7;
- if (a.W != -44444444)
- return 8;
- return 0;
- }
-
- public static int test_0_accessor_vecto4ui () {
- Vector4ui a = new Vector4ui (0xF0000000, 0xF0000, 3, 4);
-
- if (a.X != 0xF0000000)
- return 1;
- if (a.Y != 0xF0000)
- return 2;
- if (a.Z != 3)
- return 3;
- if (a.W != 4)
- return 4;
-
- a.X = 11;
- a.Y = 22;
- a.Z = 33333344;
- a.W = 44444444;
-
- if (a.X != 11)
- return 5;
- if (a.Y != 22)
- return 6;
- if (a.Z != 33333344)
- return 7;
- if (a.W != 44444444)
- return 8;
- return 0;
- }
-
- static float use_getter_with_byref (ref Vector4f a) {
- return a.W;
- }
-
- public static int test_0_accessor_and_byref_var () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- if (use_getter_with_byref (ref a) != 4)
- return 1;
- return 0;
- }
-
- public static unsafe int test_0_vector2ul_slr () {
- Vector2ul a = new Vector2ul (1, 6);
-
- Vector2ul c = a >> 1;
- if (c.X != 0)
- return 1;
- if (c.Y != 3)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2l_cmp_gt () {
- Vector2l a = new Vector2l (10, 5);
- Vector2l b = new Vector2l (-1, 5);
-
- Vector2l c = a.CompareGreaterThan (b);
-
- if (c.X != -1)
- return 1;
- if (c.Y != 0)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2l_cmp_eq () {
- Vector2l a = new Vector2l (0xFF, 5);
- Vector2l b = new Vector2l (0xFF000000FFL, 5);
-
- Vector2l c = a.CompareEqual (b);
-
- if (c.X != 0)
- return 1;
- if (c.Y != -1)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2l_srl () {
- Vector2l a = new Vector2l (1, 6);
-
- Vector2l c = a.LogicalRightShift (1);
-
- if (c.X != 0)
- return 1;
- if (c.Y != 3)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2l_unpack_high () {
- Vector2l a = new Vector2l (1, 6);
- Vector2l b = new Vector2l (3, 4);
-
- Vector2l c = a.UnpackHigh (b);
-
- if (c.X != 6)
- return 1;
- if (c.Y != 4)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2l_unpack_low () {
- Vector2l a = new Vector2l (1, 6);
- Vector2l b = new Vector2l (3, 4);
-
- Vector2l c = a.UnpackLow (b);
-
- if (c.X != 1)
- return 1;
- if (c.Y != 3)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2l_xor () {
- Vector2l a = new Vector2l (1, 6);
- Vector2l b = new Vector2l (3, 4);
-
- Vector2l c = a ^ b;
-
- if (c.X != 2)
- return 1;
- if (c.Y != 2)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2l_or () {
- Vector2l a = new Vector2l (1, 6);
- Vector2l b = new Vector2l (3, 4);
-
- Vector2l c = a | b;
-
- if (c.X != 3)
- return 1;
- if (c.Y != 6)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2l_and () {
- Vector2l a = new Vector2l (1, 6);
- Vector2l b = new Vector2l (3, 4);
-
- Vector2l c = a & b;
-
- if (c.X != 1)
- return 1;
- if (c.Y != 4)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2l_shl() {
- Vector2l a = new Vector2l (1, 6);
-
- Vector2l c = a << 3;
-
- if (c.X != 8)
- return 1;
- if (c.Y != 48)
- return 2;
- return 0;
- }
- public static unsafe int test_0_vector2l_sub() {
- Vector2l a = new Vector2l (1, 6);
- Vector2l b = new Vector2l (3, 4);
-
- Vector2l c = a - b;
-
- if (c.X != -2)
- return 1;
- if (c.Y != 2)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2l_add () {
- Vector2l a = new Vector2l (1, 2);
- Vector2l b = new Vector2l (3, 4);
-
- Vector2l c = a + b;
-
- if (c.X != 4)
- return 1;
- if (c.Y != 6)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2d_dup () {
- Vector2d a = new Vector2d (3, 2);
-
- Vector2d c = a.Duplicate ();
-
- if (c.X != 3)
- return 1;
- if (c.Y != 3)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2d_cmp_eq () {
- Vector2d a = new Vector2d (3, 2);
- Vector2d b = new Vector2d (3, 4);
-
- Vector4ui c = (Vector4ui)a.CompareEqual (b);
-
- if (c.X != 0xFFFFFFFF)
- return 1;
- if (c.Y != 0xFFFFFFFF)
- return 2;
- if (c.Z != 0)
- return 3;
- if (c.W != 0)
- return 4;
- return 0;
- }
-
- public static unsafe int test_0_vector2d_unpack_low () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (4, 5);
-
- Vector2d c = a.InterleaveLow (b);
-
- if (c.X != 1)
- return 1;
- if (c.Y != 4)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2d_unpack_high () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (4, 5);
-
- Vector2d c = a.InterleaveHigh (b);
-
- if (c.X != 2)
- return 1;
- if (c.Y != 5)
- return 2;
- return 0;
- }
- public static unsafe int test_0_vector2d_addsub () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (4, 1);
-
- Vector2d c = a.AddSub (b);
-
- if (c.X != -3)
- return 1;
- if (c.Y != 3)
- return 2;
- return 0;
- }
- public static unsafe int test_0_vector2d_hsub () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (4, 1);
-
- Vector2d c = a.HorizontalSub (b);
-
- if (c.X != -1)
- return 1;
- if (c.Y != 3)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2d_hadd () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (4, 0);
-
- Vector2d c = a.HorizontalAdd (b);
-
- if (c.X != 3)
- return 1;
- if (c.Y != 4)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2d_min () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (4, 0);
-
- Vector2d c = a.Min (b);
-
- if (c.X != 1)
- return 1;
- if (c.Y != 0)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2d_max () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (4, 0);
-
- Vector2d c = a.Max (b);
-
- if (c.X != 4)
- return 1;
- if (c.Y != 2)
- return 2;
- return 0;
- }
-
-
- public static unsafe int test_0_vector2d_andnot () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (3, 4);
-
- Vector4ui c = (Vector4ui)a.AndNot (b);
- Vector4ui ta = (Vector4ui)a;
- Vector4ui tb = (Vector4ui)b;
-
- if (c.X != (~ta.X & tb.X))
- return 1;
- if (c.Y != (~ta.Y & tb.Y))
- return 2;
- if (c.Z != (~ta.Z & tb.Z))
- return 3;
- if (c.W != (~ta.W & tb.W))
- return 4;
- return 0;
- }
-
- public static unsafe int test_0_vector2d_div () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (4, 5);
-
- Vector2d c = a / b;
-
- if (c.X != 0.25)
- return 1;
- if (c.Y != 0.4)
- return 2;
- return 0;
- }
-
- public static unsafe int test_0_vector2d_mul () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (3, 5);
-
- Vector2d c = a * b;
-
- if (c.X != 3)
- return 1;
- if (c.Y != 10)
- return 2;
- return 0;
- }
- public static unsafe int test_0_vector2d_sub () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (3, 5);
-
- Vector2d c = a - b;
-
- if (c.X != -2)
- return 1;
- if (c.Y != -3)
- return 2;
- return 0;
- }
- public static unsafe int test_0_vector2d_add () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (3, 4);
-
- Vector2d c = a + b;
-
- if (c.X != 4)
- return 1;
- if (c.Y != 6)
- return 2;
- return 0;
- }
- public static unsafe int test_0_vector2d_xor () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (3, 4);
-
- Vector4ui c = (Vector4ui)(a ^ b);
- Vector4ui ta = (Vector4ui)a;
- Vector4ui tb = (Vector4ui)b;
-
- if (c.X != (ta.X ^ tb.X))
- return 1;
- if (c.Y != (ta.Y ^ tb.Y))
- return 2;
- if (c.Z != (ta.Z ^ tb.Z))
- return 3;
- if (c.W != (ta.W ^ tb.W))
- return 4;
- return 0;
- }
-
- public static unsafe int test_0_vector2d_or () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (3, 4);
-
- Vector4ui c = (Vector4ui)(a | b);
- Vector4ui ta = (Vector4ui)a;
- Vector4ui tb = (Vector4ui)b;
-
- if (c.X != (ta.X | tb.X))
- return 1;
- if (c.Y != (ta.Y | tb.Y))
- return 2;
- if (c.Z != (ta.Z | tb.Z))
- return 3;
- if (c.W != (ta.W | tb.W))
- return 4;
- return 0;
- }
-
- public static unsafe int test_0_vector2d_and () {
- Vector2d a = new Vector2d (1, 2);
- Vector2d b = new Vector2d (3, 4);
-
- Vector4ui c = (Vector4ui)(a & b);
- Vector4ui ta = (Vector4ui)a;
- Vector4ui tb = (Vector4ui)b;
-
- if (c.X != (ta.X & tb.X))
- return 1;
- if (c.Y != (ta.Y & tb.Y))
- return 2;
- if (c.Z != (ta.Z & tb.Z))
- return 3;
- if (c.W != (ta.W & tb.W))
- return 4;
- return 0;
- }
-
- public static unsafe int test_0_vector8s_pack_signed_sat () {
- Vector8s a = new Vector8s (-200, 200, 3, 0, 5, 6, 5, 4);
- Vector8s b = new Vector8s (9, 2, 1, 2, 3, 6, 5, 6);
-
- Vector16sb c = a.PackWithSignedSaturation (b);
-
- if (c.V0 != -128)
- return 1;
- if (c.V1 != 127)
- return 2;
-
- return 0;
- }
-
- public static unsafe int test_0_vector16sb_sub_sat () {
- Vector16sb a = new Vector16sb (100,-100,11,12,13,14,15,0,1,2,3,4,5,6,7,8);
- Vector16sb b = new Vector16sb (-100, 100,11,12,4,5,6,7,8,9,10,11,12,13,14,15);
-
- Vector16sb c = a.SubtractWithSaturation (b);
-
- if (c.V0 != 127)
- return 1;
- if (c.V1 != -128)
- return 2;
- if (c.V2 != 0)
- return 3;
- if (c.V3 != 0)
- return 4;
- if (c.V4 != 9)
- return 5;
- if (c.V5 != 9)
- return 6;
- if (c.V6 != 9)
- return 7;
- if (c.V7 != -7)
- return 8;
- return 0;
- }
-
- public static unsafe int test_0_vector16sb_add_sat () {
- Vector16sb a = new Vector16sb (100,-100,11,12,13,14,15,0,1,2,3,4,5,6,7,8);
- Vector16sb b = new Vector16sb (100, -100,11,12,4,5,6,7,8,9,10,11,12,13,14,15);
-
- Vector16sb c = a.AddWithSaturation (b);
-
- if (c.V0 != 127)
- return 1;
- if (c.V1 != -128)
- return 2;
- if (c.V2 != 22)
- return 3;
- if (c.V3 != 24)
- return 4;
- if (c.V4 != 17)
- return 5;
- if (c.V5 != 19)
- return 6;
- if (c.V6 != 21)
- return 7;
- if (c.V7 != 7)
- return 8;
- return 0;
- }
-
- public static unsafe int test_0_vector16sb_cmp_gt () {
- Vector16sb a = new Vector16sb (100,-100,11,12,13,14,15,0,1,2,3,4,5,6,7,8);
- Vector16sb b = new Vector16sb (-100, 100,11,12,4,5,6,7,8,9,10,11,12,13,14,15);
-
- Vector16sb c = a.CompareGreaterThan (b);
-
- if (c.V0 != -1)
- return 1;
- if (c.V1 != 0)
- return 2;
- if (c.V2 != 0)
- return 3;
- if (c.V3 != 0)
- return 4;
- if (c.V4 != -1)
- return 5;
- if (c.V5 != -1)
- return 6;
- if (c.V6 != -1)
- return 7;
- return 0;
- }
-
-
- public static int test_0_vector4ui_pack_with_sat () {
- Vector4ui a = new Vector4ui (0xF0000000,0xF0000,3,4);
- Vector4ui b = new Vector4ui (5,6,7,8);
-
- Vector8us c = a.SignedPackWithUnsignedSaturation (b);
-
- if (c.V0 != 0)
- return 1;
- if (c.V1 != 0xFFFF)
- return 2;
- if (c.V2 != 3)
- return 3;
- if (c.V3 != 4)
- return 4;
- if (c.V4 != 5)
- return 5;
- if (c.V5 != 6)
- return 6;
- if (c.V6 != 7)
- return 7;
- if (c.V7 != 8)
- return 8;
- return 0;
- }
-
- public static int test_0_vector8us_pack_with_sat () {
- Vector8us a = new Vector8us (0xFF00,1,2,3,4,5,6,7);
- Vector8us b = new Vector8us (3,4,5,6,7,8,9,10);
- Vector16b c = a.SignedPackWithUnsignedSaturation (b);
-
- if (c.V0 != 0)
- return 1;
- if (c.V1 != 1)
- return 2;
- if (c.V2 != 2)
- return 3;
- if (c.V8 != 3)
- return 4;
- if (c.V15 != 10)
- return 5;
- return 0;
- }
-
- public static int test_0_vector8us_mul_high () {
- Vector8us a = new Vector8us (0xFF00, 2, 3, 0, 5, 6, 5, 4);
- Vector8us b = new Vector8us (0xFF00, 2, 1, 2, 3, 6, 5, 6);
- Vector8us c = a.MultiplyStoreHigh (b);
-
- if (c.V0 != 0xFE01)
- return 1;
- if (c.V1 != 0)
- return 2;
- if (c.V2 != 0)
- return 3;
- if (c.V3 != 0)
- return 4;
- if (c.V4 != 0)
- return 5;
- if (c.V5 != 0)
- return 6;
- if (c.V6 != 0)
- return 7;
- if (c.V7 != 0)
- return 8;
- return 0;
- }
-
- public static int test_0_vector8us_cmpeq () {
- Vector8us a = new Vector8us (1, 2, 3, 0, 5, 6, 5, 4);
- Vector8us b = new Vector8us (9, 2, 1, 2, 3, 6, 5, 6);
- Vector8us c = a.CompareEqual (b);
-
- if (c.V0 != 0)
- return 1;
- if (c.V1 != 0xFFFF)
- return 2;
- if (c.V2 != 0)
- return 3;
- if (c.V3 != 0)
- return 4;
- if (c.V4 != 0)
- return 5;
- if (c.V5 != 0xFFFF)
- return 6;
- if (c.V6 != 0xFFFF)
- return 7;
- if (c.V7 != 0)
- return 8;
- return 0;
- }
-
-
- public static int test_0_vector4ui_cmpeq () {
- Vector4ui a = new Vector4ui (6,1,6,3);
- Vector4ui b = new Vector4ui (3,4,6,7);
- Vector4ui c = a.CompareEqual (b);
-
- if (c.X != 0)
- return 1;
- if (c.Y != 0)
- return 2;
- if (c.Z != 0xFFFFFFFF)
- return 3;
- if (c.W != 0)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_shuffle () {
- Vector4ui a = new Vector4ui (1,2,3,4);
- Vector4ui c = a.Shuffle (ShuffleSel.XFromY | ShuffleSel.YFromW | ShuffleSel.ZFromX | ShuffleSel.WFromZ);
-
- if (c.X != 2)
- return 1;
- if (c.Y != 4)
- return 2;
- if (c.Z != 1)
- return 3;
- if (c.W != 3)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_min () {
- Vector4ui a = new Vector4ui (6,1,6,3);
- Vector4ui b = new Vector4ui (3,4,6,7);
- Vector4ui c = a.Min (b);
-
- if (c.X != 3)
- return 1;
- if (c.Y != 1)
- return 2;
- if (c.Z != 6)
- return 3;
- if (c.W != 3)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_max () {
- Vector4ui a = new Vector4ui (6,1,6,3);
- Vector4ui b = new Vector4ui (3,4,6,7);
- Vector4ui c = a.Max (b);
-
- if (c.X != 6)
- return 1;
- if (c.Y != 4)
- return 2;
- if (c.Z != 6)
- return 3;
- if (c.W != 7)
- return 4;
- return 0;
- }
-
- public static int vector16b_cmpeq () {
- Vector16b a = new Vector16b (1,0,9,0,0,0,0,0,0,0,0,0,0,0,0,1);
- Vector16b b = new Vector16b (0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
- Vector16b c = a.CompareEqual (b);
-
- if (c.V0 != 0)
- return 1;
- if (c.V1 != 0)
- return 2;
- if (c.V2 != 0)
- return 3;
- if (c.V3 != 0xff)
- return 4;
- if (c.V4 != 0xff)
- return 5;
- if (c.V5 != 0xff)
- return 6;
- if (c.V6 != 0xff)
- return 7;
- if (c.V7 != 0xff)
- return 8;
- if (c.V8 != 0xff)
- return 9;
- if (c.V9 != 0xff)
- return 10;
- if (c.V10 != 0xff)
- return 11;
- if (c.V11 != 0xff)
- return 12;
- if (c.V12 != 0xff)
- return 13;
- if (c.V13 != 0xff)
- return 14;
- if (c.V14 != 0xff)
- return 15;
- if (c.V15 != 0)
- return 16;
- return 0;
- }
-
-
- public static int vector16b_sum_abs_diff () {
- Vector16b a = new Vector16b (100,20,20,20,0,0,0,0,0,0,0,0,0,0, 0, 0);
- Vector16sb b = new Vector16sb (0, 10,10,10,0,0,0,0,0,0,0,0,0,0,10,10);
- Vector8us c = a.SumOfAbsoluteDifferences (b);
-
- if (c.V0 != 130)
- return 1;
- if (c.V1 != 0)
- return 2;
- if (c.V2 != 0)
- return 3;
- if (c.V3 != 0)
- return 4;
- if (c.V4 != 20)
- return 5;
- if (c.V5 != 0)
- return 6;
- if (c.V6 != 0)
- return 7;
- if (c.V7 != 0)
- return 8;
- return 0;
- }
-
-
- public static int test_0_vector16b_extract_mask () {
- Vector16b a = new Vector16b (0xF0,0,0xF0,0,0,0,0xF0,0xAA,0x0F,0,0xFF,0,0,0,0,0);
- int c = a.ExtractByteMask ();
-
- if (c != 0x4C5)
- return 1;
- return 0;
- }
-
- public static int test_0_vector16b_min () {
- Vector16b a = new Vector16b (0,12,20,12,4,5,6,7,8,9,10,11,12,13,14,15);
- Vector16b b = new Vector16b (9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8);
- Vector16b c = a.Min (b);
-
- if (c.V0 != 0)
- return 1;
- if (c.V1 != 10)
- return 2;
- if (c.V2 != 11)
- return 3;
- if (c.V3 != 12)
- return 4;
- if (c.V4 != 4)
- return 5;
- if (c.V5 != 5)
- return 6;
- if (c.V6 != 6)
- return 7;
- if (c.V7 != 0)
- return 8;
- if (c.V8 != 1)
- return 9;
- if (c.V9 != 2)
- return 10;
- if (c.V10 != 3)
- return 11;
- if (c.V11 != 4)
- return 12;
- if (c.V12 != 5)
- return 13;
- if (c.V13 != 6)
- return 14;
- if (c.V14 != 7)
- return 15;
- if (c.V15 != 8)
- return 16;
- return 0;
- }
-
- public static int test_0_vector16b_max () {
- Vector16b a = new Vector16b (0,12,20,12,4,5,6,7,8,9,10,11,12,13,14,15);
- Vector16b b = new Vector16b (9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8);
- Vector16b c = a.Max (b);
-
- if (c.V0 != 9)
- return 1;
- if (c.V1 != 12)
- return 2;
- if (c.V2 != 20)
- return 3;
- if (c.V3 != 12)
- return 4;
- if (c.V4 != 13)
- return 5;
- if (c.V5 != 14)
- return 6;
- if (c.V6 != 15)
- return 7;
- if (c.V7 != 7)
- return 8;
- if (c.V8 != 8)
- return 9;
- if (c.V9 != 9)
- return 10;
- if (c.V10 != 10)
- return 11;
- if (c.V11 != 11)
- return 12;
- if (c.V12 != 12)
- return 13;
- if (c.V13 != 13)
- return 14;
- if (c.V14 != 14)
- return 15;
- if (c.V15 != 15)
- return 16;
- return 0;
- }
- public static int test_0_vector16b_avg () {
- Vector16b a = new Vector16b (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,120);
- Vector16b b = new Vector16b (9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,180);
- Vector16b c = a.Average (b);
-
- if (c.V0 != 5)
- return 1;
- if (c.V1 != 6)
- return 2;
- if (c.V2 != 7)
- return 3;
- if (c.V3 != 8)
- return 4;
- if (c.V4 != 9)
- return 5;
- if (c.V5 != 10)
- return 6;
- if (c.V6 != 11)
- return 7;
- if (c.V7 != 4)
- return 8;
- if (c.V8 != 5)
- return 9;
- if (c.V9 != 6)
- return 10;
- if (c.V10 != 7)
- return 11;
- if (c.V11 != 8)
- return 12;
- if (c.V12 != 9)
- return 13;
- if (c.V13 != 10)
- return 14;
- if (c.V14 != 11)
- return 15;
- if (c.V15 != 150)
- return 16;
- return 0;
- }
-
-
- static unsafe Vector8us bad_method_regression_2 (Vector16b va, Vector16b vb) {
- Vector8us res = new Vector8us ();
- byte *a = (byte*)&va;
- byte *b = (byte*)&vb;
-
- int tmp = 0;
- for (int i = 0; i < 8; ++i)
- tmp += System.Math.Abs ((int)*a++ - (int)*b++);
- res.V0 = (ushort)tmp;
-
- tmp = 0;
- for (int i = 0; i < 8; ++i)
- tmp += System.Math.Abs ((int)*a++ - (int)*b++);
- res.V4 = (ushort)tmp;
- return res;
- }
-
- /*This bug was caused the simplifier not taking notice of LDADDR on the remaining blocks.*/
- public static int test_2_local_simplifier_regression_other_blocks () {
- Vector16b a = new Vector16b (1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1);
- Vector16b b = new Vector16b (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
- Vector8us res = bad_method_regression_2 (a,b);
- return (int)res.V0 + res.V4;
- }
-
- static unsafe Vector8us bad_method_regression (Vector16b va, Vector16b vb) {
- Vector8us res = new Vector8us ();
- byte *a = (byte*)&va;
- byte *b = (byte*)&vb;
- *((ushort*)&res) = 10;
-
- int tmp = 0;
- if (*b != 0)
- tmp++;
-
- Vector8us dd = res;
- dd = dd + dd - dd;
- return dd;
- }
-
- /*This bug was caused the simplifier not taking notice of LDADDR on the first block.*/
- public static int test_10_local_simplifier_regression_first_block () {
- Vector16b a = new Vector16b ();
- Vector16b b = new Vector16b ();
- Vector8us res = bad_method_regression (a,b);
- return (int)res.V0;
- }
-
- public static int test_0_vecto8us_shuffle_low () {
- Vector8us a = new Vector8us (1, 2, 3, 4, 5, 6, 7, 8);
- Vector8us c = a.ShuffleLow (ShuffleSel.XFromY | ShuffleSel.YFromW | ShuffleSel.ZFromX | ShuffleSel.WFromZ);
-
- if (c.V0 != 2)
- return 1;
- if (c.V1 != 4)
- return 2;
- if (c.V2 != 1)
- return 3;
- if (c.V3 != 3)
- return 4;
- if (c.V4 != 5)
- return 5;
- if (c.V5 != 6)
- return 6;
- if (c.V6 != 7)
- return 7;
- if (c.V7 != 8)
- return 8;
- return 0;
- }
-
- public static int test_0_vecto8us_shuffle_high () {
- Vector8us a = new Vector8us (1, 2, 3, 4, 5, 6, 7, 8);
- Vector8us c = a.ShuffleHigh (ShuffleSel.XFromY | ShuffleSel.YFromW | ShuffleSel.ZFromX | ShuffleSel.WFromZ);
-
- if (c.V0 != 1)
- return 1;
- if (c.V1 != 2)
- return 2;
- if (c.V2 != 3)
- return 3;
- if (c.V3 != 4)
- return 4;
- if (c.V4 != 6)
- return 5;
- if (c.V5 != 8)
- return 6;
- if (c.V6 != 5)
- return 7;
- if (c.V7 != 7)
- return 8;
-
- return 0;
- }
-
- public static int test_0_vecto8us_max () {
- Vector8us a = new Vector8us (1, 2, 3, 4, 5, 6, 7, 8);
- Vector8us b = new Vector8us (9, 1, 1, 2, 9, 6, 5, 1000);
- Vector8us c = a.Max (b);
-
- if (c.V0 != 9)
- return 1;
- if (c.V1 != 2)
- return 2;
- if (c.V2 != 3)
- return 3;
- if (c.V3 != 4)
- return 4;
- if (c.V4 != 9)
- return 5;
- if (c.V5 != 6)
- return 6;
- if (c.V6 != 7)
- return 7;
- if (c.V7 != 1000)
- return 0;
-
- return 0;
- }
-
- public static int test_0_vecto8us_min () {
- Vector8us a = new Vector8us (1, 2, 3, 0, 5, 6, 5, 4);
- Vector8us b = new Vector8us (9, 1, 1, 2, 3, 4, 5, 6);
- Vector8us c = a.Min (b);
-
- if (c.V0 != 1)
- return 1;
- if (c.V1 != 1)
- return 2;
- if (c.V2 != 1)
- return 3;
- if (c.V3 != 0)
- return 4;
- if (c.V4 != 3)
- return 5;
- if (c.V5 != 4)
- return 6;
- if (c.V6 != 5)
- return 7;
- if (c.V7 != 4)
- return 8;
- return 0;
- }
-
- public static int test_0_vecto8us_avg () {
- Vector8us a = new Vector8us (1, 2, 3, 4, 5, 6, 7, 30000);
- Vector8us b = new Vector8us (9, 1, 1, 2, 3, 4, 5, 40000);
- Vector8us c = a.Average (b);
-
- if (c.V0 != 5)
- return 1;
- if (c.V1 != 2)
- return 2;
- if (c.V2 != 2)
- return 3;
- if (c.V3 != 3)
- return 4;
- if (c.V4 != 4)
- return 5;
- if (c.V5 != 5)
- return 6;
- if (c.V6 != 6)
- return 7;
- if (c.V7 != 35000)
- return 8;
- return 0;
- }
-
- static void store_helper (ref Vector4f x) {
- Vector4f k;
- k = new Vector4f(9,9,9,9);
- x = k;
- }
-
- public static int test_0_vector4f_byref_store ()
- {
- Vector4f k;
- k = new Vector4f(1,2,3,4);
- store_helper (ref k);
- if (k.X != 9)
- return 1;
- return 0;
- }
-
- public static int test_0_vector4f_init_array_element ()
- {
- Vector4f[] v = new Vector4f[1];
- v[0] = new Vector4f(9,9,9,9);
- if (v [0].X != 9)
- return 1;
- return 0;
- }
-
- public static int test_0_vector4f_dup_high () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f c = a.DuplicateHigh();
-
- if (c.X != 2)
- return 1;
- if (c.Y != 2)
- return 2;
- if (c.Z != 4)
- return 3;
- if (c.W != 4)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_dup_low () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f c = a.DuplicateLow ();
-
- if (c.X != 1)
- return 1;
- if (c.Y != 1)
- return 2;
- if (c.Z != 3)
- return 3;
- if (c.W != 3)
- return 4;
- return 0;
- }
-
-
- public static int test_0_vector4f_interleave_high () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = new Vector4f (5, 6, 7, 8);
- Vector4f c = a.InterleaveHigh (b);
-
- if (c.X != 3)
- return 1;
- if (c.Y != 7)
- return 2;
- if (c.Z != 4)
- return 3;
- if (c.W != 8)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_interleave_low () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = new Vector4f (5, 6, 7, 8);
- Vector4f c = a.InterleaveLow (b);
-
- if (c.X != 1)
- return 1;
- if (c.Y != 5)
- return 2;
- if (c.Z != 2)
- return 3;
- if (c.W != 6)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_rcp () {
- Vector4f a = new Vector4f (1, 2, 4, 8);
- Vector4f c = a.Reciprocal ();
-
- //Test with ranges due to the terrible precision.
- if (c.X < (1 - 0.01f) || c.X > (1 + 0.01f))
- return 1;
- if (c.Y < (0.5 - 0.01f) || c.Y > (0.5 + 0.01f))
- return 2;
- if (c.Z < (0.25 - 0.01f) || c.Z > (0.25 + 0.01f))
- return 3;
- if (c.W < (0.125 - 0.01f) || c.W > (0.125 + 0.01f))
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_xor () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = new Vector4f (1, 3, 3, 8);
- Vector4f c = a ^ b;
-
- if (((Vector4ui)c).X != 0)
- return 1;
- if (((Vector4ui)c).Y != 0x400000)
- return 2;
- if (((Vector4ui)c).Z != 0)
- return 3;
- if (((Vector4ui)c).W != 0x1800000)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_or () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = new Vector4f (1, 3, 3, 8);
- Vector4f c = a | b;
-
- if (((Vector4ui)c).X != 0x3F800000)
- return 1;
- if (((Vector4ui)c).Y != 0x40400000)
- return 2;
- if (((Vector4ui)c).Z != 0x40400000)
- return 3;
- if (((Vector4ui)c).W != 0x41800000)
- return 4;
- return 0;
- }
- public static int test_0_vector4f_andn () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = new Vector4f (1, 3, 3, 8);
- Vector4f c = a.AndNot (b);
-
- if (((Vector4ui)c).X != 0)
- return 1;
- if (((Vector4ui)c).Y != 0x400000)
- return 2;
- if (((Vector4ui)c).Z != 0)
- return 3;
- if (((Vector4ui)c).W != 0x1000000)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_and () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = new Vector4f (1, 3, 3, 8);
- Vector4f c = a & b;
-
- if (((Vector4ui)c).X != 0x3F800000)
- return 1;
- if (((Vector4ui)c).Y != 0x40000000)
- return 2;
- if (((Vector4ui)c).Z != 0x40400000)
- return 3;
- if (((Vector4ui)c).W != 0x40000000)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_cmpord () {
- Vector4f a = new Vector4f (float.NaN, 2, 3, 4);
- Vector4f b = new Vector4f (1, float.NaN, 3, 6);
- Vector4f c = a.CompareOrdered (b);
-
- if (((Vector4ui)c).X != 0)
- return 1;
- if (((Vector4ui)c).Y != 0)
- return 2;
- if (((Vector4ui)c).Z != 0xFFFFFFFF)
- return 3;
- if (((Vector4ui)c).W != 0xFFFFFFFF)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_cmpnle () {
- Vector4f a = new Vector4f (float.NaN, 2, 3, 4);
- Vector4f b = new Vector4f (1, float.NaN, 3, 6);
- Vector4f c = a.CompareNotLessEqual (b);
-
- if (((Vector4ui)c).X != 0xFFFFFFFF)
- return 1;
- if (((Vector4ui)c).Y != 0xFFFFFFFF)
- return 2;
- if (((Vector4ui)c).Z != 0)
- return 3;
- if (((Vector4ui)c).W != 0)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_cmpnlt () {
- Vector4f a = new Vector4f (float.NaN, 2, 3, 4);
- Vector4f b = new Vector4f (1, float.NaN, 3, 6);
- Vector4f c = a.CompareNotLessThan (b);
-
- if (((Vector4ui)c).X != 0xFFFFFFFF)
- return 1;
- if (((Vector4ui)c).Y != 0xFFFFFFFF)
- return 2;
- if (((Vector4ui)c).Z != 0xFFFFFFFF)
- return 3;
- if (((Vector4ui)c).W != 0)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_cmpneq () {
- Vector4f a = new Vector4f (float.NaN, 2, 3, 4);
- Vector4f b = new Vector4f (1, float.NaN, 3, 6);
- Vector4f c = a.CompareNotEqual (b);
-
- if (((Vector4ui)c).X != 0xFFFFFFFF)
- return 1;
- if (((Vector4ui)c).Y != 0xFFFFFFFF)
- return 2;
- if (((Vector4ui)c).Z != 0)
- return 3;
- if (((Vector4ui)c).W != 0xFFFFFFFF)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_cmpunord () {
- Vector4f a = new Vector4f (float.NaN, 2, 3, 4);
- Vector4f b = new Vector4f (1, float.NaN, 3, 6);
- Vector4f c = a.CompareUnordered (b);
-
- if (((Vector4ui)c).X != 0xFFFFFFFF)
- return 1;
- if (((Vector4ui)c).Y != 0xFFFFFFFF)
- return 2;
- if (((Vector4ui)c).Z != 0)
- return 3;
- if (((Vector4ui)c).W != 0)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_cmple () {
- Vector4f a = new Vector4f (float.NaN, 2, 3, 4);
- Vector4f b = new Vector4f (1, float.NaN, 3, 6);
- Vector4f c = a.CompareLessEqual (b);
-
- if (((Vector4ui)c).X != 0)
- return 1;
- if (((Vector4ui)c).Y != 0)
- return 2;
- if (((Vector4ui)c).Z != 0xFFFFFFFF)
- return 3;
- if (((Vector4ui)c).W != 0xFFFFFFFF)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_cmplt () {
- Vector4f a = new Vector4f (float.NaN, 2, 3, 4);
- Vector4f b = new Vector4f (1, float.NaN, 3, 6);
- Vector4f c = a.CompareLessThan (b);
-
- if (((Vector4ui)c).X != 0)
- return 1;
- if (((Vector4ui)c).Y != 0)
- return 2;
- if (((Vector4ui)c).Z != 0)
- return 3;
- if (((Vector4ui)c).W != 0xFFFFFFFF)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4f_cmpeq () {
- Vector4f a = new Vector4f (float.NaN, 2, 3, 6);
- Vector4f b = new Vector4f (1, float.NaN, 3, 4);
- Vector4f c = a.CompareEqual (b);
-
- if (((Vector4ui)c).X != 0)
- return 1;
- if (((Vector4ui)c).Y != 0)
- return 2;
- if (((Vector4ui)c).Z != 0xFFFFFFFF)
- return 3;
- if (((Vector4ui)c).W != 0)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_sar () {
- Vector4ui a = new Vector4ui (0xF0000000u,20,3,40);
-
- Vector4ui c = a.ArithmeticRightShift (2);
-
- if (c.X != 0xFC000000)
- return 1;
- if (c.Y != 5)
- return 2;
- if (c.Z != 0)
- return 3;
- if (c.W != 10)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_unpack_high () {
- Vector4ui a = new Vector4ui (1,2,3,4);
- Vector4ui b = new Vector4ui (5,6,7,8);
-
- Vector4ui c = a.UnpackHigh(b);
-
- if (c.X != 3)
- return 1;
- if (c.Y != 7)
- return 2;
- if (c.Z != 4)
- return 3;
- if (c.W != 8)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_unpack_low () {
- Vector4ui a = new Vector4ui (1,2,3,4);
- Vector4ui b = new Vector4ui (5,6,7,8);
-
- Vector4ui c = a.UnpackLow (b);
-
- if (c.X != 1)
- return 1;
- if (c.Y != 5)
- return 2;
- if (c.Z != 2)
- return 3;
- if (c.W != 6)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_xor () {
- Vector4ui a = new Vector4ui (1,2,3,4);
- Vector4ui b = new Vector4ui (7,5,3,1);
-
- Vector4ui c = a ^ b;
-
- if (c.X != 6)
- return 1;
- if (c.Y != 7)
- return 2;
- if (c.Z != 0)
- return 3;
- if (c.W != 5)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_or () {
- Vector4ui a = new Vector4ui (1,2,3,4);
- Vector4ui b = new Vector4ui (7,5,3,1);
-
- Vector4ui c = a | b;
-
- if (c.X != 7)
- return 1;
- if (c.Y != 7)
- return 2;
- if (c.Z != 3)
- return 3;
- if (c.W != 5)
- return 4;
- return 0;
- }
- public static int test_0_vector4ui_and () {
- Vector4ui a = new Vector4ui (1,2,3,4);
- Vector4ui b = new Vector4ui (7,5,3,1);
-
- Vector4ui c = a & b;
-
- if (c.X != 1)
- return 1;
- if (c.Y != 0)
- return 2;
- if (c.Z != 3)
- return 3;
- if (c.W != 0)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_shr () {
- Vector4ui a = new Vector4ui (0xF0000000u,20,3,40);
-
- Vector4ui c = a >> 2;
-
- if (c.X != 0x3C000000)
- return 1;
- if (c.Y != 5)
- return 2;
- if (c.Z != 0)
- return 3;
- if (c.W != 10)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_shl () {
- Vector4ui a = new Vector4ui (10,20,3,40);
-
- Vector4ui c = a << 2;
-
- if (c.X != 40)
- return 1;
- if (c.Y != 80)
- return 2;
- if (c.Z != 12)
- return 3;
- if (c.W != 160)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_mul () {
- Vector4ui a = new Vector4ui (0x8888,20,3,40);
- Vector4ui b = new Vector4ui (0xFF00FF00u,2,3,4);
-
- Vector4ui c = a * b;
-
- if (c.X != 0xffff7800)
- return 1;
- if (c.Y != 40)
- return 2;
- if (c.Z != 9)
- return 3;
- if (c.W != 160)
- return 4;
- return 0;
- }
- public static int test_0_vector4ui_sub () {
- Vector4ui a = new Vector4ui (1,20,3,40);
- Vector4ui b = new Vector4ui (0xFF00FF00u,2,3,4);
-
- Vector4ui c = a - b;
-
- if (c.X != 0xff0101)
- return 1;
- if (c.Y != 18)
- return 2;
- if (c.Z != 0)
- return 3;
- if (c.W != 36)
- return 4;
- return 0;
- }
-
- public static int test_0_vector4ui_add () {
- Vector4ui a = new Vector4ui (0xFF00FF00u,2,3,4);
- Vector4ui b = new Vector4ui (0xFF00FF00u,2,3,4);
-
- Vector4ui c = a + b;
-
- if (c.X != 0xfe01fe00)
- return 1;
- if (c.Y != 4)
- return 2;
- if (c.Z != 6)
- return 3;
- if (c.W != 8)
- return 4;
- return 0;
- }
-
-
- static int test_0_vector4ui_accessors () {
- Vector4ui a = new Vector4ui (1,2,3,4);
-
- if (a.X != 1)
- return 1;
- if (a.Y != 2)
- return 2;
- if (a.Z != 3)
- return 3;
- if (a.W != 4)
- return 4;
- a.X = 10;
- a.Y = 20;
- a.Z = 30;
- a.W = 40;
-
- if (a.X != 10)
- return 5;
- if (a.Y != 20)
- return 6;
- if (a.Z != 30)
- return 7;
- if (a.W != 40)
- return 8;
- return 0;
- }
-
- static int test_0_vector8us_sub_sat () {
- Vector8us a = new Vector8us (0xF000,1,20,3,4,5,6,7);
- Vector8us b = new Vector8us (0xFF00,4,5,6,7,8,9,10);
- Vector8us c = a.SubtractWithSaturation (b);
-
- if (c.V0 != 0)
- return 1;
- if (c.V1 != 0)
- return 2;
- if (c.V2 != 15)
- return 3;
- if (c.V3 != 0)
- return 4;
- if (c.V4 != 0)
- return 5;
- if (c.V5 != 0)
- return 6;
- if (c.V6 != 0)
- return 7;
- if (c.V7 != 0)
- return 8;
- return 0;
- }
-
- static int test_0_vector8us_add_sat () {
- Vector8us a = new Vector8us (0xFF00,1,2,3,4,5,6,7);
- Vector8us b = new Vector8us (0xFF00,4,5,6,7,8,9,10);
- Vector8us c = a.AddWithSaturation (b);
-
- if (c.V0 != 0xFFFF)
- return 1;
- if (c.V1 != 5)
- return 2;
- if (c.V2 != 7)
- return 3;
- if (c.V3 != 9)
- return 4;
- if (c.V4 != 11)
- return 5;
- if (c.V5 != 13)
- return 6;
- if (c.V6 != 15)
- return 7;
- if (c.V7 != 17)
- return 8;
- return 0;
- }
-
- static int test_0_vector8us_unpack_low () {
- Vector8us a = new Vector8us (0,1,2,3,4,5,6,7);
- Vector8us b = new Vector8us (3,4,5,6,7,8,9,10);
- Vector8us c = a.UnpackLow (b);
-
- if (c.V0 != 0)
- return 1;
- if (c.V1 != 3)
- return 2;
- if (c.V2 != 1)
- return 3;
- if (c.V3 != 4)
- return 4;
- if (c.V4 != 2)
- return 5;
- if (c.V5 != 5)
- return 6;
- if (c.V6 != 3)
- return 7;
- if (c.V7 != 6)
- return 8;
- return 0;
- }
-
-
- static int test_0_vector8us_shift_left () {
- Vector8us a = new Vector8us (0xFF00,1,2,3,4,5,6,7);
- int amt = 2;
- Vector8us c = a << amt;
-
- if (c.V0 != 0xFC00)
- return 1;
- if (c.V1 != 4)
- return 2;
- if (c.V7 != 28)
- return 3;
- return 0;
- }
-
- static int test_0_vector8us_shift_right_arithmetic () {
- Vector8us a = new Vector8us (0xFF00,1,2,3,4,5,6,7);
- int amt = 2;
- Vector8us c = a.ArithmeticRightShift (amt);
-
- if (c.V0 != 0xFFC0)
- return 1;
- if (c.V1 != 0)
- return 2;
- if (c.V7 != 1)
- return 3;
- return 0;
- }
-
- static int test_0_vector8us_shift_variable_offset () {
- int off = 2;
- Vector8us a = new Vector8us (0xF000,1,2,3,4,5,6,7);
- Vector8us b = a;
- Vector8us c = b >> off;
- a = b + b;
-
- if (c.V0 != 0x3C00)
- return 1;
- if (c.V1 != 0)
- return 2;
- if (c.V7 != 1)
- return 3;
- if (a.V1 != 2)
- return 4;
- if (a.V7 != 14)
- return 5;
- return 0;
- }
-
-
- static int test_0_vector8us_shift_operand_is_live_after_op () {
- Vector8us a = new Vector8us (0xF000,1,2,3,4,5,6,7);
- Vector8us b = a;
- Vector8us c = b >> 2;
- a = b + b;
-
- if (c.V0 != 0x3C00)
- return 1;
- if (c.V1 != 0)
- return 2;
- if (c.V7 != 1)
- return 3;
- if (a.V1 != 2)
- return 4;
- if (a.V7 != 14)
- return 5;
- return 0;
- }
-
- static int test_0_vector8us_shr_constant () {
- Vector8us a = new Vector8us (0xF000,1,2,3,4,5,6,7);
- Vector8us c = a >> 2;
-
- if (c.V0 != 0x3C00)
- return 1;
- if (c.V1 != 0)
- return 2;
- if (c.V7 != 1)
- return 3;
- return 0;
- }
-
- static int test_0_vector8us_mul () {
- Vector8us a = new Vector8us (0x0F00,4,5,6,7,8,9,10);
- Vector8us b = new Vector8us (0x0888,1,2,3,4,5,6,8);
-
- Vector8us c = a * b;
- if (c.V0 != 63488)
- return 1;
- if (c.V1 != 4)
- return 2;
- if (c.V7 != 80)
- return 3;
- return 0;
- }
-
- static int test_0_vector8us_add () {
- Vector8us a = new Vector8us (0xFF00,4,5,6,7,8,9,10);
- Vector8us b = new Vector8us (0x8888,1,2,3,4,5,6,8);
-
- Vector8us c = a + b;
- if (c.V0 != 34696)
- return 1;
- if (c.V1 != 5)
- return 2;
- if (c.V7 != 18)
- return 3;
- return 0;
- }
-
-
- static int test_0_vector8us_sub () {
- Vector8us a = new Vector8us (3,4,5,6,7,8,9,10);
- Vector8us b = new Vector8us (10,1,2,3,4,5,6,8);
-
- Vector8us c = a - b;
-
- if (c.V0 != 65529)
- return 1;
- if (c.V1 != 3)
- return 2;
- if (c.V7 != 2)
- return 3;
- return 0;
- }
-
-
- static int test_0_vector8us_accessors () {
- Vector8us a = new Vector8us (0,1,2,3,4,5,6,7);
-
- if (a.V0 != 0)
- return 1;
- if (a.V1 != 1)
- return 2;
- if (a.V2 != 2)
- return 3;
- if (a.V3 != 3)
- return 4;
- if (a.V4 != 4)
- return 5;
- if (a.V5 != 5)
- return 6;
- if (a.V6 != 6)
- return 7;
- if (a.V7 != 7)
- return 8;
- a.V0 = 10;
- a.V1 = 20;
- a.V2 = 30;
- a.V3 = 40;
- a.V4 = 50;
- a.V5 = 60;
- a.V6 = 70;
- a.V7 = 80;
-
- if (a.V0 != 10)
- return 17;
- if (a.V1 != 20)
- return 18;
- if (a.V2 != 30)
- return 19;
- if (a.V3 != 40)
- return 20;
- if (a.V4 != 50)
- return 21;
- if (a.V5 != 60)
- return 22;
- if (a.V6 != 70)
- return 23;
- if (a.V7 != 80)
- return 24;
-
- return 0;
- }
-
-
- static int test_0_vector16b_unpack_high () {
- Vector16b a = new Vector16b (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
- Vector16b b = new Vector16b (9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8);
- Vector16b c = a.UnpackHigh (b);
-
- if (c.V0 != 8)
- return 1;
- if (c.V1 != 1)
- return 2;
- if (c.V2 != 9)
- return 3;
- if (c.V3 != 2)
- return 4;
- if (c.V4 != 10)
- return 5;
- if (c.V5 != 3)
- return 6;
- if (c.V14 != 15)
- return 7;
- if (c.V15 != 8)
- return 8;
- return 0;
- }
-
- static int test_0_vector16b_unpack_low () {
- Vector16b a = new Vector16b (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
- Vector16b b = new Vector16b (9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8);
- Vector16b c = a.UnpackLow (b);
-
- if (c.V0 != 0)
- return 1;
- if (c.V1 != 9)
- return 2;
- if (c.V2 != 1)
- return 3;
- if (c.V3 != 10)
- return 4;
- if (c.V4 != 2)
- return 5;
- if (c.V5 != 11)
- return 6;
- if (c.V14 != 7)
- return 7;
- if (c.V15 != 0)
- return 8;
- return 0;
- }
-
- static int test_0_vector16b_sub_sat () {
- Vector16b a = new Vector16b (100,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8);
- Vector16b b = new Vector16b (200,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
- Vector16b c = a.SubtractWithSaturation (b);
-
- if (c.V0 != 0)
- return 1;
- if (c.V1 != 9)
- return 2;
- if (c.V15 != 0)
- return 3;
- return 0;
- }
-
- static int test_0_vector16b_add_sat () {
- Vector16b a = new Vector16b (200,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
- Vector16b b = new Vector16b (200,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8);
- Vector16b c = a.AddWithSaturation (b);
-
- if (c.V0 != 255)
- return 1;
- if (c.V1 != 11)
- return 2;
- if (c.V15 != 23)
- return 3;
- return 0;
- }
-
- static int test_0_vector16b_add_ovf () {
- Vector16b a = new Vector16b (200,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
- Vector16b b = new Vector16b (200,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8);
- Vector16b c = a + b;
-
- if (c.V0 != 144)
- return 1;
- if (c.V1 != 11)
- return 2;
- if (c.V15 != 23)
- return 3;
- return 0;
- }
-
- static int test_0_vector16b_accessors () {
- Vector16b a = new Vector16b (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
-
- if (a.V0 != 0)
- return 1;
- if (a.V1 != 1)
- return 2;
- if (a.V2 != 2)
- return 3;
- if (a.V3 != 3)
- return 4;
- if (a.V4 != 4)
- return 5;
- if (a.V5 != 5)
- return 6;
- if (a.V6 != 6)
- return 7;
- if (a.V7 != 7)
- return 8;
- if (a.V8 != 8)
- return 9;
- if (a.V9 != 9)
- return 10;
- if (a.V10 != 10)
- return 11;
- if (a.V11 != 11)
- return 12;
- if (a.V12 != 12)
- return 13;
- if (a.V13 != 13)
- return 14;
- if (a.V14 != 14)
- return 15;
- if (a.V15 != 15)
- return 16;
-
- a.V0 = 10;
- a.V1 = 20;
- a.V2 = 30;
- a.V3 = 40;
- a.V4 = 50;
- a.V5 = 60;
- a.V6 = 70;
- a.V7 = 80;
- a.V8 = 90;
- a.V9 = 100;
- a.V10 = 110;
- a.V11 = 120;
- a.V12 = 130;
- a.V13 = 140;
- a.V14 = 150;
- a.V15 = 160;
-
- if (a.V0 != 10)
- return 17;
- if (a.V1 != 20)
- return 18;
- if (a.V2 != 30)
- return 19;
- if (a.V3 != 40)
- return 20;
- if (a.V4 != 50)
- return 21;
- if (a.V5 != 60)
- return 22;
- if (a.V6 != 70)
- return 23;
- if (a.V7 != 80)
- return 24;
- if (a.V8 != 90)
- return 25;
- if (a.V9 != 100)
- return 26;
- if (a.V10 != 110)
- return 27;
- if (a.V11 != 120)
- return 28;
- if (a.V12 != 130)
- return 29;
- if (a.V13 != 140)
- return 30;
- if (a.V14 != 150)
- return 31;
- if (a.V15 != 160)
- return 32;
- return 0;
- }
-
- public static int test_0_accessors () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- if (a.X != 1f)
- return 1;
- if (a.Y != 2f)
- return 2;
- if (a.Z != 3f)
- return 3;
- if (a.W != 4f)
- return 4;
- return 0;
- }
-
- public static int test_0_packed_add_with_stack_tmp () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = new Vector4f (5, 6, 7, 8);
- Vector4f c = new Vector4f (-1, -3, -4, -5);
- Vector4f d = a + b + c;
- if (d.X != 5f)
- return 1;
- if (d.Y != 5f)
- return 2;
- if (d.Z != 6f)
- return 3;
- if (d.W != 7f)
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_add () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = new Vector4f (5, 6, 7, 8);
- Vector4f c;
- c = a + b;
- if (c.X != 6f)
- return 1;
- if (c.Y != 8f)
- return 2;
- if (c.Z != 10f)
- return 3;
- if (c.W != 12f)
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_sub () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = new Vector4f (5, 6, 7, 8);
- Vector4f c = b - a;
- if (c.X != 4f)
- return 1;
- if (c.Y != 4f)
- return 2;
- if (c.Z != 4f)
- return 3;
- if (c.W != 4f)
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_mul () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = new Vector4f (5, 6, 7, 8);
- Vector4f c = b * a;
- if (c.X != 5f)
- return 1;
- if (c.Y != 12f)
- return 2;
- if (c.Z != 21f)
- return 3;
- if (c.W != 32f)
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_div () {
- Vector4f a = new Vector4f (2, 2, 3, 4);
- Vector4f b = new Vector4f (20, 10, 33, 12);
- Vector4f c = b / a;
- if (c.X != 10f)
- return 1;
- if (c.Y != 5f)
- return 2;
- if (c.Z != 11f)
- return 3;
- if (c.W != 3f)
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_sqrt () {
- Vector4f a = new Vector4f (16, 4, 9, 25);
- a = a.Sqrt ();
- if (a.X != 4f)
- return 1;
- if (a.Y != 2f)
- return 2;
- if (a.Z != 3f)
- return 3;
- if (a.W != 5f)
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_invsqrt () {
- Vector4f a = new Vector4f (16, 4, 100, 25);
- //this function has VERY low precision
- a = a.InvSqrt ();
- if (a.X < (1/4f - 0.01f) || a.X > (1/4f + 0.01f))
- return 1;
- if (a.Y < (1/2f - 0.01f) || a.Y > (1/2f + 0.01f))
- return 2;
- if (a.Z < (1/10f - 0.01f) || a.Z > (1/10f + 0.01f))
- return 3;
- if (a.W < (1/5f - 0.01f) || a.W > (1/5f + 0.01f))
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_min () {
- Vector4f a = new Vector4f (16, -4, 9, 25);
- Vector4f b = new Vector4f (5, 3, 9, 0);
- Vector4f c = a.Min (b);
- if (c.X != 5f)
- return 1;
- if (c.Y != -4f)
- return 2;
- if (c.Z != 9f)
- return 3;
- if (c.W != 0f)
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_max () {
- Vector4f a = new Vector4f (16, -4, 9, 25);
- Vector4f b = new Vector4f (5, 3, 9, 0);
- Vector4f c = a.Max (b);
- if (c.X != 16f)
- return 1;
- if (c.Y != 3f)
- return 2;
- if (c.Z != 9f)
- return 3;
- if (c.W != 25f)
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_hadd () {
- Vector4f a = new Vector4f (5, 5, 6, 6);
- Vector4f b = new Vector4f (7, 7, 8, 8);
- Vector4f c = a.HorizontalAdd (b);
- if (c.X != 10f)
- return 1;
- if (c.Y != 12f)
- return 2;
- if (c.Z != 14f)
- return 3;
- if (c.W != 16f)
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_hsub () {
- Vector4f a = new Vector4f (5, 2, 6, 1);
- Vector4f b = new Vector4f (7, 0, 8, 3);
- Vector4f c = a.HorizontalSub (b);
- if (c.X != 3f)
- return 1;
- if (c.Y != 5f)
- return 2;
- if (c.Z != 7f)
- return 3;
- if (c.W != 5f)
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_addsub () {
- Vector4f a = new Vector4f (5, 2, 6, 1);
- Vector4f b = new Vector4f (7, 0, 8, 3);
- Vector4f c = a.AddSub (b);
- if (c.X != -2f)
- return 1;
- if (c.Y != 2f)
- return 2;
- if (c.Z != -2f)
- return 3;
- if (c.W != 4f)
- return 4;
- return 0;
- }
-
- public static int test_0_simple_packed_shuffle () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- a = a.Shuffle(ShuffleSel.XFromY | ShuffleSel.YFromW | ShuffleSel.ZFromX | ShuffleSel.WFromZ);
- if (a.X != 2f)
- return 1;
- if (a.Y != 4f)
- return 2;
- if (a.Z != 1f)
- return 3;
- if (a.W != 3f)
- return 4;
- return 0;
- }
-
- public static int test_0_packed_shuffle_with_reg_pressure () {
- Vector4f v = new Vector4f (1, 2, 3, 4);
- Vector4f m0 = v + v, m1 = v - v, m2 = v * v, m3 = v + v + v;
- if (ff) v = v + v -v ;
-
- Vector4f r0 = v.Shuffle (ShuffleSel.XFromY | ShuffleSel.YFromW | ShuffleSel.ZFromX | ShuffleSel.WFromZ);
- Vector4f r1 = v.Shuffle (ShuffleSel.XFromY | ShuffleSel.YFromW | ShuffleSel.ZFromX | ShuffleSel.WFromZ);
- Vector4f x = v.Shuffle (ShuffleSel.XFromY | ShuffleSel.YFromW | ShuffleSel.ZFromX | ShuffleSel.WFromZ);
- Vector4f r2 = v.Shuffle (ShuffleSel.XFromY | ShuffleSel.YFromW | ShuffleSel.ZFromX | ShuffleSel.WFromZ);
- Vector4f r3 = v.Shuffle (ShuffleSel.XFromY | ShuffleSel.YFromW | ShuffleSel.ZFromX | ShuffleSel.WFromZ);
- Vector4f a = x;
-
- r0 = r0 * m0 + x;
- r1 = r1 * m1 + x;
- x = x - v + v;
- r2 = r2 * m2 + x;
- r3 = r3 * m3 + x;
- Vector4f result = r0 + r1 + r2 + r3;
-
- if (a.X != 2f)
- return 1;
- if (a.Y != 4f)
- return 2;
- if (a.Z != 1f)
- return 3;
- if (a.W != 3f)
- return 4;
- if (result.Y != result.Y)
- return 0;
- return 0;
- }
-
- public static int test_0_double_packed_sqrt () {
- Vector2d a = new Vector2d (16, 4);
- a = a.Sqrt ();
- if (a.X != 4f)
- return 1;
- if (a.Y != 2f)
- return 2;
- return 0;
- }
-
- public static int test_24_regs_pressure_a () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = a + a;
- Vector4f c = b * a;
- Vector4f d = a - b;
- c = a + b + c + d;
- return (int)c.Z;
- }
-
- public static int test_54_regs_pressure_b () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = a + a;
- Vector4f c = b - a;
- Vector4f d = c - a;
- Vector4f e = a + b + c;
- Vector4f f = d - b + a - c;
- Vector4f g = a - d * f - c + b;
- Vector4f h = a * b - c + e;
- Vector4f i = h - g - f - e - d - c - b - a;
- Vector4f j = a + b + c + d + e + f + g + h + i;
- return (int)j.Z;
- }
-
- public static int test_8_regs_pressure_c () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = a + a;
- Vector4f c = b - a;
- Vector4f d = c - a;
- Vector4f e = a + b + c;
- Vector4f f = d - b + a - c;
- Vector4f g = a - d * f - c + b;
- Vector4f h = a * b - c + e;
- Vector4f i = h - g - f - e - d - c - b - a;
- Vector4f j = a + b + c + d + e + f + g + h + i;
- Vector4f k = j - i - h + e + d - a + b - f + g;
- Vector4f l = k * c - j * b - i * e + f - g;
- Vector4f m = l - k + j - i + e + f;
- Vector4f n = m - j + g - i + e * b + a * d;
- Vector4f o = k + j + i * b;
- Vector4f p = m + j + i + e + l;
- Vector4f q = l * m + j + k;
- Vector4f r = p * a + o * b + j * c + m * d + l * e;
- Vector4f s = a - b - c - d - e - f - g - h - i - j - k - l - m - p - o - q - r;
- Vector4f t = a + b + c + d + e + f + g + h + i + j + k + l + m + p + o + q + r + s;
- return (int)t.W;
- }
-
- public static int test_0_regs_pressure_fp_and_simd_share_bank_1 () {
- Vector4f a = new Vector4f (4, 3, 2, 1);
- float aF = 10f;
- Vector4f b = a + a;
- float bF = aF + aF;
- Vector4f c = b - a;
- float cF = bF - aF;
- Vector4f d = c - a;
- float dF = cF - aF;
- Vector4f e = a + b + c;
- float eF = aF + bF + cF;
- Vector4f f = d - b + a - c;
- float fF = dF - bF + aF - cF;
- Vector4f g = a - d * f - c + b;
- float gF = aF - dF * fF - cF + bF;
- Vector4f h = a * b - c + e;
- float hF = aF * bF - cF + eF;
- Vector4f i = h - g - f - e - d - c - b - a;
- float iF = hF - gF - fF - eF - dF - cF - bF - aF;
- Vector4f j = a + b + c + d + e + f + g + h + i;
- float jF = aF + bF + cF + dF + eF + fF + gF + hF + iF;
-
- if (j.X != 88f)
- return 1;
-
- if(jF != 460f)
- return 2;
-
- return 0;
- }
-
-#if FALSE
- // Fails with -O=float32
- public static int test_0_regs_pressure_fp_and_simd_share_bank_2 () {
- Vector4f a = new Vector4f (4, 3, 2, 1);
- float aF = 10f;
- Vector4f b = a + a;
- float bF = aF + aF;
- Vector4f c = b - a;
- float cF = bF - aF;
- Vector4f d = c - a;
- float dF = cF - aF;
- Vector4f e = a + b + c;
- float eF = aF + bF + cF;
- Vector4f f = d - b + a - c;
- float fF = dF - bF + aF - cF;
- Vector4f g = a - d * f - c + b;
- float gF = aF - dF * fF - cF + bF;
- Vector4f h = a * b - c + e;
- float hF = aF * bF - cF + eF;
- Vector4f i = h - g - f - e - d - c - b - a;
- float iF = hF - gF - fF - eF - dF - cF - bF - aF;
- Vector4f j = a + b + c + d + e + f + g + h + i;
- float jF = aF + bF + cF + dF + eF + fF + gF + hF + iF;
- Vector4f k = j - i - h + e + d - a + b - f + g;
- float kF = jF - iF - hF + eF + dF - aF + bF - fF + gF;
- Vector4f l = k * c - j * b - i * e + f - g;
- float lF = kF * cF - jF * bF - iF * eF + fF - gF;
- Vector4f m = l - k + j - i + e + f;
- float mF = lF - kF + jF - iF + eF + fF;
- Vector4f n = m - j + g - i + e * b + a * d;
- float nF = mF - jF + gF - iF + eF * bF + aF * dF;
- Vector4f o = k + j + i * b;
- float oF = kF + jF + iF * bF;
- Vector4f p = m + j + i + e + l;
- float pF = mF + jF + iF + eF + lF;
- Vector4f q = l * m + j + k;
- float qF = lF * mF + jF + kF;
- Vector4f r = p * a + o * b + j * c + m * d + l * e;
- float rF = pF * aF + oF * bF + jF * cF + mF * dF + lF * eF;
- Vector4f s = a - b - c - d - e - f - g - h - i - j - k - l - m - p - o - q - r;
- float sF = aF - bF - cF - dF - eF - fF - gF - hF - iF - jF - kF - lF - mF - pF - oF - qF - rF;
- Vector4f t = a + b + c + d + e + f + g + h + i + j + k + l + m + p + o + q + r + s;
- float tF = aF + bF + cF + dF + eF + fF + gF + hF + iF + jF + kF + lF + mF + pF + oF + qF + rF + sF;
-
- if (t.X != 8f)
- return 1;
-
- if(tF != 14f)
- return 2;
-
- return 0;
- }
-#endif
-
- public static void call_simd_fp () {
- Vector4f a = new Vector4f (20f, 22f, 23f, 24f);
- float b = 25f;
- Vector4f c = new Vector4f (26f, 27f, 28f, 29f);
- float d = 30f;
-
- b += d;
- a += c;
- }
- public static int test_0_call_fp_and_simd_share_bank () {
-
- float a = 1f;
- Vector4f b = new Vector4f (2f, 3f, 4f, 5f);
- float c = 6f;
- Vector4f d = new Vector4f (7f, 8f, 9f, 10f);
-
- a += c;
-
- b += d;
-
- call_simd_fp ();
- if (a != 7f)
- return 1;
- if (b.X != 9f)
- return 2;
- if (c != 6f)
- return 3;
- if (d.X != 7f)
- return 4;
- if (b.W != 15f)
- return 5;
- if (d.W != 10f)
- return 6;
-
-
- return 0;
- }
-
-
- static bool ff;
- public static int test_3_single_block_var_is_properly_promoted () {
- Vector4f a = new Vector4f (4, 5, 6, 7);
- if (ff)
- a = a - a;
- else {
- Vector4f b = new Vector4f (1, 2, 3, 4);
- Vector4f c = b;
- a = a - b;
- if (ff) {
- c = a;
- a = c;
- }
- }
- return (int)a.X;
- }
-
- static float float_val = 45f;
-
- public static int test_0_sse2_opt_and_simd_intrinsic_proper_regalloc () {
- Vector4f v = new Vector4f (1, 2, 3, 4);
- float f = float_val;
- int x = (int)f;
- if (v.X != 1f)
- return 1;
- if (x != 45f)
- return 2;
- return 0;
- }
-
- public static int test_0_sse41_vector8s_min () {
- Vector8s v = new Vector8s(2);
- Vector8s v2 = new Vector8s(1);
- v = v.Min(v2);
- if (v.V0 != 1 || v.V1 != 1 || v.V2 != 1 || v.V3 != 1 || v.V4 != 1 || v.V5 != 1 || v.V6 != 1 || v.V7 != 1)
- return 1;
- return 0;
- }
-
- public static int test_0_simd_const_indexer_simple () {
- Vector4f v = new Vector4f (1, 2, 3, 4);
-
- if (v[0] != 1)
- return 1;
- if (v[1] != 2)
- return 2;
- if (v[2] != 3)
- return 3;
- if (v[3] != 4)
- return 4;
- return 0;
- }
-
- public static int test_0_simd_var_indexer_simple () {
- Vector4f v = new Vector4f (1, 2, 3, 4);
-
- int index = 0;
-
- if (v[index++] != 1)
- return 1;
- if (v[index++] != 2)
- return 2;
- if (v[index++] != 3)
- return 3;
- if (v[index] != 4)
- return 4;
- return 0;
- }
-
- public static int test_0_simd_const_indexer_double () {
- Vector2d v = new Vector2d (1, 2);
-
- if (v[0] != 1)
- return 1;
- if (v[1] != 2)
- return 2;
- return 0;
- }
-
- public static int test_0_simd_var_indexer_double () {
- Vector2d v = new Vector2d (1, 2);
-
- int index = 0;
-
- if (v[index++] != 1)
- return 1;
- if (v[index] != 2)
- return 2;
- return 0;
- }
-
-
- public static int test_0_scala_vector4f_mul () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = 2 * a;
- Vector4f c = a * 3;
-
- if (b.X != 2f || b.Y != 4f || b.Z != 6f || b.W != 8f )
- return 1;
- if (c.X != 3f || c.Y != 6f || c.Z != 9f || c.W != 12f )
- return 1;
-
- return 0;
- }
-
- static void CallMethodThatClobbersRegs () {
- Vector4f a = new Vector4f (9,9,9,9);
- Vector4f b = new Vector4f (9,9,9,9);
- a = a + b;
- }
-
- public static int test_0_call_spills_regs_correctly () {
- Vector4f a = new Vector4f (1,2,3,4);
- Vector4f b = new Vector4f (5,6,7,8);
-
- CallMethodThatClobbersRegs ();
-
- bool b0 = a.X == 1f;
- bool b1 = b.X == 5f;
- if (!b0 || !b1)
- return 1;
- return 0;
- }
-
- public static int test_0_shuffle_with_two_args_pd () {
- Vector2d a = new Vector2d (1,2);
- Vector2d b = new Vector2d (5,6);
-
- Vector2d c = a.Shuffle (b, 0x2);
- if (c.X != 1)
- return 1;
- if (c.Y != 6)
- return 2;
- return 0;
- }
-
- public static int test_0_shuffle_with_two_args_ps () {
- Vector4f a = new Vector4f (1, 2, 3, 4);
- Vector4f b = new Vector4f (5, 6, 7, 8);
-
- Vector4f c = a.Shuffle (b, ShuffleSel.ExpandY);
- if (c.X != 2)
- return 1;
- if (c.Y != 2)
- return 2;
- if (c.Z != 6)
- return 3;
- if (c.W != 6)
- return 4;
- return 0;
- }
-
- public static int test_0_i_to_d () {
- var a = new Vector4i (1, 2, 3, 4);
- var b = a.ConvertToDouble ();
- if (b.X != 1)
- return 1;
- if (b.Y != 2)
- return 2;
- return 0;
- }
-
- public static int test_0_i_to_f () {
- var a = new Vector4i (1, 2, 3, 4);
- var b = a.ConvertToFloat ();
- if (b.X != 1)
- return 1;
- if (b.Y != 2)
- return 2;
- if (b.Z != 3)
- return 3;
- if (b.W != 4)
- return 4;
- return 0;
- }
-
- public static int test_0_d_to_i () {
- var a = new Vector2d (1.4, 2.6);
- var b = a.ConvertToInt ();
- if (b.X != 1)
- return 1;
- if (b.Y != 3)
- return 2;
- if (b.Z != 0)
- return 3;
- if (b.W != 0)
- return 4;
- return 0;
- }
-
- public static int test_0_d_to_f () {
- var a = new Vector2d (1, 2);
- var b = a.ConvertToFloat ();
- if (b.X != 1)
- return 1;
- if (b.Y != 2)
- return 2;
- if (b.Z != 0)
- return 3;
- if (b.W != 0)
- return 4;
- return 0;
- }
-
- public static int test_0_f_to_i () {
- var a = new Vector4f (1.1f, 2.2f, 3.5f, 4.6f);
- var b = a.ConvertToInt ();
- if (b.X != 1)
- return 1;
- if (b.Y != 2)
- return 2;
- if (b.Z != 4)
- return 3;
- if (b.W != 5)
- return 4;
- return 0;
- }
-
- public static int test_0_f_to_d () {
- var a = new Vector4f (1,2,3,4);
- var b = a.ConvertToDouble ();
- if (b.X != 1)
- return 1;
- if (b.Y != 2)
- return 2;
- return 0;
- }
-
- public static int test_0_d_to_i_trunc () {
- var a = new Vector2d (1.4, 2.6);
- var b = a.ConvertToIntTruncated ();
- if (b.X != 1)
- return 1;
- if (b.Y != 2)
- return 2;
- if (b.Z != 0)
- return 3;
- if (b.W != 0)
- return 4;
- return 0;
- }
-
- public static int test_0_f_to_i_trunc () {
- var a = new Vector4f (1.1f, 2.2f, 3.5f, 4.6f);
- var b = a.ConvertToIntTruncated ();
- if (b.X != 1)
- return 1;
- if (b.Y != 2)
- return 2;
- if (b.Z != 3)
- return 3;
- if (b.W != 4)
- return 4;
- return 0;
- }
-
- class BoxedVector2d
- {
- public Vector2d v;
- }
-
- public static int test_0_vector2d_set_x () {
- var bv = new BoxedVector2d ();
- var xy = new Vector2d ();
- xy.X = bv.v.X;
-
- if (xy.X != 0)
- return 1;
- if (xy.Y != 0)
- return 2;
- return 0;
- }
-
- public static int Main (String[] args) {
- return TestDriver.RunTests (typeof (SimdTests), args);
- }
-}
-
+++ /dev/null
-# mips cpu description file
-# this file is read by genmdesc to pruduce a table with all the relevant
-# information about the cpu instructions that may be used by the regsiter
-# allocator, the scheduler and other parts of the arch-dependent part of mini.
-#
-# An opcode name is followed by a colon and optional specifiers.
-# A specifier has a name, a colon and a value.
-# Specifiers are separated by white space.
-# Here is a description of the specifiers valid for this file and their
-# possible values.
-#
-# dest:register describes the destination register of an instruction
-# src1:register describes the first source register of an instruction
-# src2:register describes the second source register of an instruction
-#
-# register may have the following values:
-# i integer register
-# l integer register pair
-# v v0 register (output from calls)
-# V v0/v1 register pair (output from calls)
-# a at register
-# b base register (used in address references)
-# f floating point register (pair - always)
-# g floating point register return pair (f0/f1)
-#
-# len:number describe the maximun length in bytes of the instruction
-# number is a positive integer
-#
-# cost:number describe how many cycles are needed to complete the instruction (unused)
-#
-# clob:spec describe if the instruction clobbers registers or has special needs
-#
-# spec can be one of the following characters:
-# c clobbers caller-save registers
-# r 'reserves' the destination register until a later instruction unreserves it
-# used mostly to set output registers in function calls
-#
-# flags:spec describe if the instruction uses or sets the flags (unused)
-#
-# spec can be one of the following chars:
-# s sets the flags
-# u uses the flags
-# m uses and modifies the flags
-#
-# res:spec describe what units are used in the processor (unused)
-#
-# delay: describe delay slots (unused)
-#
-# the required specifiers are: len, clob (if registers are clobbered), the registers
-# specifiers if the registers are actually used, flags (when scheduling is implemented).
-#
-# See the code in mini-x86.c for more details on how the specifiers are used.
-#
-memory_barrier: len:4
-nop: len:4
-relaxed_nop: len:4
-break: len:16
-call: dest:v clob:c len:20
-br: len:16
-switch: src1:i len:40
-seq_point: len:24
-il_seq_point: len:0
-
-int_conv_to_r_un: dest:f src1:i len:32
-throw: src1:i len:24
-rethrow: src1:i len:24
-ckfinite: dest:f src1:f len:52
-start_handler: len:16
-endfinally: len:12
-ceq: dest:i len:16
-cgt: dest:i len:16
-cgt_un: dest:i len:16
-clt: dest:i len:16
-clt_un: dest:i len:16
-localloc: dest:i src1:i len:60
-compare: src1:i src2:i len:20
-compare_imm: src1:i len:20
-fcompare: src1:f src2:f len:12
-arglist: src1:i len:12
-setlret: src1:i src2:i len:12
-check_this: src1:b len:4
-
-voidcall: len:20 clob:c
-voidcall_reg: src1:i len:20 clob:c
-voidcall_membase: src1:b len:20 clob:c
-
-fcall: dest:g len:20 clob:c
-fcall_reg: dest:g src1:i len:20 clob:c
-fcall_membase: dest:g src1:b len:20 clob:c
-
-lcall: dest:V len:28 clob:c
-lcall_reg: dest:V src1:i len:28 clob:c
-lcall_membase: dest:V src1:b len:28 clob:c
-
-call_reg: dest:v src1:i len:20 clob:c
-call_membase: dest:v src1:b len:20 clob:c
-
-vcall: len:16 clob:c
-vcall_reg: src1:i len:20 clob:c
-vcall_membase: src1:b len:20 clob:c
-
-vcall2: len:16 clob:c
-vcall2_reg: src1:i len:20 clob:c
-vcall2_membase: src1:b len:20 clob:c
-
-jump_table: dest:i len:8
-
-iconst: dest:i len:12
-i8const: dest:l len:24
-r4const: dest:f len:20
-r8const: dest:f len:28
-label: len:0
-store_membase_imm: dest:b len:20
-store_membase_reg: dest:b src1:i len:20
-storei1_membase_imm: dest:b len:20
-storei1_membase_reg: dest:b src1:i len:20
-storei2_membase_imm: dest:b len:20
-storei2_membase_reg: dest:b src1:i len:20
-storei4_membase_imm: dest:b len:20
-storei4_membase_reg: dest:b src1:i len:20
-storei8_membase_imm: dest:b
-storei8_membase_reg: dest:b src1:i len:20
-storer4_membase_reg: dest:b src1:f len:20
-storer8_membase_reg: dest:b src1:f len:20
-load_membase: dest:i src1:b len:20
-loadi1_membase: dest:i src1:b len:20
-loadu1_membase: dest:i src1:b len:20
-loadi2_membase: dest:i src1:b len:20
-loadu2_membase: dest:i src1:b len:20
-loadi4_membase: dest:i src1:b len:20
-loadu4_membase: dest:i src1:b len:20
-loadi8_membase: dest:i src1:b len:20
-loadr4_membase: dest:f src1:b len:20
-loadr8_membase: dest:f src1:b len:20
-load_memindex: dest:i src1:b src2:i len:4
-loadi1_memindex: dest:i src1:b src2:i len:12
-loadu1_memindex: dest:i src1:b src2:i len:12
-loadi2_memindex: dest:i src1:b src2:i len:12
-loadu2_memindex: dest:i src1:b src2:i len:12
-loadi4_memindex: dest:i src1:b src2:i len:12
-loadu4_memindex: dest:i src1:b src2:i len:12
-loadr4_memindex: dest:f src1:b src2:i len:12
-loadr8_memindex: dest:f src1:b src2:i len:12
-store_memindex: dest:b src1:i src2:i len:12
-storei1_memindex: dest:b src1:i src2:i len:12
-storei2_memindex: dest:b src1:i src2:i len:12
-storei4_memindex: dest:b src1:i src2:i len:12
-storer4_memindex: dest:b src1:f src2:i len:12
-storer8_memindex: dest:b src1:f src2:i len:12
-loadu4_mem: dest:i len:8
-move: dest:i src1:i len:4
-fmove: dest:f src1:f len:8
-move_f_to_i4: dest:i src1:f len:4
-move_i4_to_f: dest:f src1:i len:4
-add_imm: dest:i src1:i len:12
-sub_imm: dest:i src1:i len:12
-mul_imm: dest:i src1:i len:20
-# there is no actual support for division or reminder by immediate
-# we simulate them, though (but we need to change the burg rules
-# to allocate a symbolic reg for src2)
-div_imm: dest:i src1:i src2:i len:20
-div_un_imm: dest:i src1:i src2:i len:12
-rem_imm: dest:i src1:i src2:i len:28
-rem_un_imm: dest:i src1:i src2:i len:16
-and_imm: dest:i src1:i len:12
-or_imm: dest:i src1:i len:12
-xor_imm: dest:i src1:i len:12
-shl_imm: dest:i src1:i len:8
-shr_imm: dest:i src1:i len:8
-shr_un_imm: dest:i src1:i len:8
-
-# Linear IR opcodes
-dummy_use: src1:i len:0
-dummy_iconst: dest:i len:0
-dummy_i8const: dest:i len:0
-dummy_r8const: dest:f len:0
-dummy_r4const: dest:f len:0
-not_reached: len:0
-not_null: src1:i len:0
-
-# 32 bit opcodes
-int_add: dest:i src1:i src2:i len:4
-int_sub: dest:i src1:i src2:i len:4
-int_mul: dest:i src1:i src2:i len:16
-int_div: dest:i src1:i src2:i len:84
-int_div_un: dest:i src1:i src2:i len:40
-int_rem: dest:i src1:i src2:i len:84
-int_rem_un: dest:i src1:i src2:i len:40
-int_and: dest:i src1:i src2:i len:4
-int_or: dest:i src1:i src2:i len:4
-int_xor: dest:i src1:i src2:i len:4
-int_shl: dest:i src1:i src2:i len:4
-int_shr: dest:i src1:i src2:i len:4
-int_shr_un: dest:i src1:i src2:i len:4
-int_neg: dest:i src1:i len:4
-int_not: dest:i src1:i len:4
-int_conv_to_i1: dest:i src1:i len:8
-int_conv_to_i2: dest:i src1:i len:8
-int_conv_to_i4: dest:i src1:i len:4
-int_conv_to_r4: dest:f src1:i len:36
-int_conv_to_r8: dest:f src1:i len:36
-int_conv_to_u4: dest:i src1:i
-int_conv_to_u2: dest:i src1:i len:8
-int_conv_to_u1: dest:i src1:i len:4
-int_beq: len:8
-int_bge: len:8
-int_bgt: len:8
-int_ble: len:8
-int_blt: len:8
-int_bne_un: len:8
-int_bge_un: len:8
-int_bgt_un: len:8
-int_ble_un: len:8
-int_blt_un: len:8
-int_add_ovf: dest:i src1:i src2:i len:16
-int_add_ovf_un: dest:i src1:i src2:i len:16
-int_mul_ovf: dest:i src1:i src2:i len:56
-int_mul_ovf_un: dest:i src1:i src2:i len:56
-int_sub_ovf: dest:i src1:i src2:i len:16
-int_sub_ovf_un: dest:i src1:i src2:i len:16
-
-int_adc: dest:i src1:i src2:i len:4
-int_addcc: dest:i src1:i src2:i len:4
-int_subcc: dest:i src1:i src2:i len:4
-int_sbb: dest:i src1:i src2:i len:4
-int_adc_imm: dest:i src1:i len:12
-int_sbb_imm: dest:i src1:i len:12
-
-int_add_imm: dest:i src1:i len:12
-int_sub_imm: dest:i src1:i len:12
-int_mul_imm: dest:i src1:i len:12
-int_div_imm: dest:i src1:i len:20
-int_div_un_imm: dest:i src1:i len:12
-int_rem_imm: dest:i src1:i len:28
-int_rem_un_imm: dest:i src1:i len:16
-int_and_imm: dest:i src1:i len:12
-int_or_imm: dest:i src1:i len:12
-int_xor_imm: dest:i src1:i len:12
-int_shl_imm: dest:i src1:i len:8
-int_shr_imm: dest:i src1:i len:8
-int_shr_un_imm: dest:i src1:i len:8
-
-int_ceq: dest:i len:16
-int_cgt: dest:i len:16
-int_cgt_un: dest:i len:16
-int_clt: dest:i len:16
-int_clt_un: dest:i len:16
-
-cond_exc_eq: len:32
-cond_exc_ne_un: len:32
-cond_exc_lt: len:32
-cond_exc_lt_un: len:32
-cond_exc_gt: len:32
-cond_exc_gt_un: len:32
-cond_exc_ge: len:32
-cond_exc_ge_un: len:32
-cond_exc_le: len:32
-cond_exc_le_un: len:32
-cond_exc_ov: len:32
-cond_exc_no: len:32
-cond_exc_c: len:32
-cond_exc_nc: len:32
-
-cond_exc_ieq: len:32
-cond_exc_ine_un: len:32
-cond_exc_ilt: len:32
-cond_exc_ilt_un: len:32
-cond_exc_igt: len:32
-cond_exc_igt_un: len:32
-cond_exc_ige: len:32
-cond_exc_ige_un: len:32
-cond_exc_ile: len:32
-cond_exc_ile_un: len:32
-cond_exc_iov: len:12
-cond_exc_ino: len:32
-cond_exc_ic: len:12
-cond_exc_inc: len:32
-
-icompare: src1:i src2:i len:4
-icompare_imm: src1:i len:12
-
-# 64 bit opcodes
-long_add: dest:i src1:i src2:i len:4
-long_sub: dest:i src1:i src2:i len:4
-long_mul: dest:i src1:i src2:i len:32
-long_mul_imm: dest:i src1:i len:4
-long_div: dest:i src1:i src2:i len:40
-long_div_un: dest:i src1:i src2:i len:16
-long_rem: dest:i src1:i src2:i len:48
-long_rem_un: dest:i src1:i src2:i len:24
-long_and: dest:i src1:i src2:i len:4
-long_or: dest:i src1:i src2:i len:4
-long_xor: dest:i src1:i src2:i len:4
-long_shl: dest:i src1:i src2:i len:4
-long_shl_imm: dest:i src1:i len:4
-long_shr: dest:i src1:i src2:i len:4
-long_shr_un: dest:i src1:i src2:i len:4
-long_shr_imm: dest:i src1:i len:4
-long_shr_un_imm: dest:i src1:i len:4
-long_neg: dest:i src1:i len:4
-long_not: dest:i src1:i len:4
-long_conv_to_i1: dest:i src1:l len:32
-long_conv_to_i2: dest:i src1:l len:32
-long_conv_to_i4: dest:i src1:l len:32
-long_conv_to_r4: dest:f src1:l len:32
-long_conv_to_r8: dest:f src1:l len:32
-long_conv_to_u4: dest:i src1:l len:32
-long_conv_to_u8: dest:l src1:l len:32
-long_conv_to_u2: dest:i src1:l len:32
-long_conv_to_u1: dest:i src1:l len:32
-long_conv_to_i: dest:i src1:l len:32
-long_conv_to_ovf_i: dest:i src1:i src2:i len:32
-long_conv_to_ovf_i4_2: dest:i src1:i src2:i len:32
-zext_i4: dest:i src1:i len:16
-sext_i4: dest:i src1:i len:16
-
-long_beq: len:8
-long_bge: len:8
-long_bgt: len:8
-long_ble: len:8
-long_blt: len:8
-long_bne_un: len:8
-long_bge_un: len:8
-long_bgt_un: len:8
-long_ble_un: len:8
-long_blt_un: len:8
-long_add_ovf: dest:i src1:i src2:i len:16
-long_add_ovf_un: dest:i src1:i src2:i len:16
-long_mul_ovf: dest:i src1:i src2:i len:16
-long_mul_ovf_un: dest:i src1:i src2:i len:16
-long_sub_ovf: dest:i src1:i src2:i len:16
-long_sub_ovf_un: dest:i src1:i src2:i len:16
-
-long_ceq: dest:i len:12
-long_cgt: dest:i len:12
-long_cgt_un: dest:i len:12
-long_clt: dest:i len:12
-long_clt_un: dest:i len:12
-
-long_add_imm: dest:i src1:i clob:1 len:4
-long_sub_imm: dest:i src1:i clob:1 len:4
-long_and_imm: dest:i src1:i clob:1 len:4
-long_or_imm: dest:i src1:i clob:1 len:4
-long_xor_imm: dest:i src1:i clob:1 len:4
-
-lcompare: src1:i src2:i len:4
-lcompare_imm: src1:i len:12
-
-long_conv_to_r_un: dest:f src1:i src2:i len:37
-
-float_beq: len:16
-float_bne_un: len:16
-float_blt: len:16
-float_blt_un: len:16
-float_bgt: len:16
-float_bgt_un: len:16
-float_bge: len:16
-float_bge_un: len:16
-float_ble: len:16
-float_ble_un: len:16
-
-float_add: dest:f src1:f src2:f len:4
-float_sub: dest:f src1:f src2:f len:4
-float_mul: dest:f src1:f src2:f len:4
-float_div: dest:f src1:f src2:f len:4
-float_div_un: dest:f src1:f src2:f len:4
-float_rem: dest:f src1:f src2:f len:16
-float_rem_un: dest:f src1:f src2:f len:16
-float_neg: dest:f src1:f len:4
-float_not: dest:f src1:f len:4
-float_conv_to_i1: dest:i src1:f len:40
-float_conv_to_i2: dest:i src1:f len:40
-float_conv_to_i4: dest:i src1:f len:40
-float_conv_to_i8: dest:l src1:f len:40
-float_conv_to_r4: dest:f src1:f len:8
-float_conv_to_u4: dest:i src1:f len:40
-float_conv_to_u8: dest:l src1:f len:40
-float_conv_to_u2: dest:i src1:f len:40
-float_conv_to_u1: dest:i src1:f len:40
-float_ceq: dest:i src1:f src2:f len:20
-float_cgt: dest:i src1:f src2:f len:20
-float_cgt_un: dest:i src1:f src2:f len:20
-float_clt: dest:i src1:f src2:f len:20
-float_clt_un: dest:i src1:f src2:f len:20
-call_handler: len:20 clob:c
-endfilter: src1:i len:16
-aotconst: dest:i len:8
-sqrt: dest:f src1:f len:4
-adc: dest:i src1:i src2:i len:4
-addcc: dest:i src1:i src2:i len:4
-subcc: dest:i src1:i src2:i len:4
-adc_imm: dest:i src1:i len:12
-addcc_imm: dest:i src1:i len:12
-subcc_imm: dest:i src1:i len:12
-sbb: dest:i src1:i src2:i len:4
-sbb_imm: dest:i src1:i len:12
-br_reg: src1:i len:8
-#ppc_subfic: dest:i src1:i len:4
-#ppc_subfze: dest:i src1:i len:4
-bigmul: len:52 dest:l src1:i src2:i
-bigmul_un: len:52 dest:l src1:i src2:i
-mips_beq: src1:i src2:i len:24
-mips_bgez: src1:i len:24
-mips_bgtz: src1:i len:24
-mips_blez: src1:i len:24
-mips_bltz: src1:i len:24
-mips_bne: src1:i src2:i len:24
-mips_cvtsd: dest:f src1:f len:8
-mips_fbeq: src1:f src2:f len:16
-mips_fbge: src1:f src2:f len:32
-mips_fbge_un: src1:f src2:f len:16
-mips_fbgt: src1:f src2:f len:32
-mips_fbgt_un: src1:f src2:f len:16
-mips_fble: src1:f src2:f len:32
-mips_fble_un: src1:f src2:f len:16
-mips_fblt: src1:f src2:f len:32
-mips_fblt_un: src1:f src2:f len:16
-mips_fbne: src1:f src2:f len:16
-mips_lwc1: dest:f src1:b len:16
-mips_mtc1_s: dest:f src1:i len:8
-mips_mtc1_s2: dest:f src1:i src2:i len:8
-mips_mfc1_s: dest:i src1:f len:8
-mips_mtc1_d: dest:f src1:i len:8
-mips_mfc1_d: dest:i src1:f len:8
-mips_slti: dest:i src1:i len:4
-mips_slt: dest:i src1:i src2:i len:4
-mips_sltiu: dest:i src1:i len:4
-mips_sltu: dest:i src1:i src2:i len:4
-mips_cond_exc_eq: src1:i src2:i len:44
-mips_cond_exc_ge: src1:i src2:i len:44
-mips_cond_exc_gt: src1:i src2:i len:44
-mips_cond_exc_le: src1:i src2:i len:44
-mips_cond_exc_lt: src1:i src2:i len:44
-mips_cond_exc_ne_un: src1:i src2:i len:44
-mips_cond_exc_ge_un: src1:i src2:i len:44
-mips_cond_exc_gt_un: src1:i src2:i len:44
-mips_cond_exc_le_un: src1:i src2:i len:44
-mips_cond_exc_lt_un: src1:i src2:i len:44
-mips_cond_exc_ov: src1:i src2:i len:44
-mips_cond_exc_no: src1:i src2:i len:44
-mips_cond_exc_c: src1:i src2:i len:44
-mips_cond_exc_nc: src1:i src2:i len:44
-mips_cond_exc_ieq: src1:i src2:i len:44
-mips_cond_exc_ige: src1:i src2:i len:44
-mips_cond_exc_igt: src1:i src2:i len:44
-mips_cond_exc_ile: src1:i src2:i len:44
-mips_cond_exc_ilt: src1:i src2:i len:44
-mips_cond_exc_ine_un: src1:i src2:i len:44
-mips_cond_exc_ige_un: src1:i src2:i len:44
-mips_cond_exc_igt_un: src1:i src2:i len:44
-mips_cond_exc_ile_un: src1:i src2:i len:44
-mips_cond_exc_ilt_un: src1:i src2:i len:44
-mips_cond_exc_iov: src1:i src2:i len:44
-mips_cond_exc_ino: src1:i src2:i len:44
-mips_cond_exc_ic: src1:i src2:i len:44
-mips_cond_exc_inc: src1:i src2:i len:44
-
-liverange_start: len:0
-liverange_end: len:0
-gc_safe_point: len:0
+++ /dev/null
-# sparc32 cpu description file
-# this file is read by genmdesc to pruduce a table with all the relevant information
-# about the cpu instructions that may be used by the register allocator, the scheduler
-# and other parts of the arch-dependent part of mini.
-#
-# An opcode name is followed by a colon and optional specifiers.
-# A specifier has a name, a colon and a value. Specifiers are separated by white space.
-# Here is a description of the specifiers valid for this file and their possible values.
-#
-# dest:register describes the destination register of an instruction
-# src1:register describes the first source register of an instruction
-# src2:register describes the second source register of an instruction
-#
-# register may have the following values:
-# i integer register
-# b base register (used in address references)
-# f floating point register
-# L register pair (same as 'i' on v9)
-# l %o0:%o1 register pair (same as 'i' on v9)
-# o %o0
-#
-# len:number describe the maximun length in bytes of the instruction
-# number is a positive integer
-#
-# cost:number describe how many cycles are needed to complete the instruction (unused)
-#
-# clob:spec describe if the instruction clobbers registers or has special needs
-#
-# spec can be one of the following characters:
-# c clobbers caller-save registers
-# r 'reserves' the destination register until a later instruction unreserves it
-# used mostly to set output registers in function calls
-#
-# flags:spec describe if the instruction uses or sets the flags (unused)
-#
-# spec can be one of the following chars:
-# s sets the flags
-# u uses the flags
-# m uses and modifies the flags
-#
-# res:spec describe what units are used in the processor (unused)
-#
-# delay: describe delay slots (unused)
-#
-# the required specifiers are: len, clob (if registers are clobbered), the registers
-# specifiers if the registers are actually used, flags (when scheduling is implemented).
-#
-# See the code in mini-sparc32.c for more details on how the specifiers are used.
-#
-label: len:0
-break: len:64
-br: len:8
-
-throw: src1:i len:64
-rethrow: src1:i len:64
-start_handler: len:64
-endfinally: len:64
-endfilter: src1:i len:64
-
-ckfinite: dest:f src1:f len:40
-ceq: dest:i len:64
-cgt: dest:i len:64
-cgt_un: dest:i len:64
-clt: dest:i len:64
-clt_un: dest:i len:64
-localloc: dest:i src1:i len:64
-localloc_imm: dest:i len:64
-compare: src1:i src2:i len:4
-icompare: src1:i src2:i len:4
-compare_imm: src1:i len:64
-icompare_imm: src1:i len:64
-fcompare: src1:f src2:f len:64
-lcompare: src1:i src2:i len:4
-setfret: dest:f src1:f len:8
-check_this: src1:b len:4
-arglist: src1:i len:64
-call: dest:o clob:c len:40
-call_reg: dest:o src1:i len:64 clob:c
-call_membase: dest:o src1:b len:64 clob:c
-voidcall: len:64 clob:c
-voidcall_reg: src1:i len:64 clob:c
-voidcall_membase: src1:b len:64 clob:c
-fcall: dest:f len:64 clob:c
-fcall_reg: dest:f src1:i len:64 clob:c
-fcall_membase: dest:f src1:b len:64 clob:c
-lcall: dest:l len:42 clob:c
-lcall_reg: dest:l src1:i len:64 clob:c
-lcall_membase: dest:l src1:b len:64 clob:c
-vcall: len:40 clob:c
-vcall_reg: src1:i len:64 clob:c
-vcall_membase: src1:b len:64 clob:c
-iconst: dest:i len:64
-i8const: dest:i len:64
-r4const: dest:f len:64
-r8const: dest:f len:64
-store_membase_imm: dest:b len:64
-store_membase_reg: dest:b src1:i len:64
-storei1_membase_imm: dest:b len:64
-storei1_membase_reg: dest:b src1:i len:64
-storei2_membase_imm: dest:b len:64
-storei2_membase_reg: dest:b src1:i len:64
-storei4_membase_imm: dest:b len:64
-storei4_membase_reg: dest:b src1:i len:64
-storei8_membase_imm: dest:b len:64 len:64
-storei8_membase_reg: dest:b src1:i len:64
-storer4_membase_reg: dest:b src1:f len:64
-storer8_membase_reg: dest:b src1:f len:64
-load_membase: dest:i src1:b len:64
-loadi1_membase: dest:i src1:b len:64
-loadu1_membase: dest:i src1:b len:64
-loadi2_membase: dest:i src1:b len:64
-loadu2_membase: dest:i src1:b len:64
-loadi4_membase: dest:i src1:b len:64
-loadu4_membase: dest:i src1:b len:64
-loadi8_membase: dest:i src1:b len:64
-loadr4_membase: dest:f src1:b len:64
-loadr8_membase: dest:f src1:b len:64
-loadu4_mem: dest:i len:8
-move: dest:i src1:i len:4
-add_imm: dest:i src1:i len:64
-addcc_imm: dest:i src1:i len:64
-sub_imm: dest:i src1:i len:64
-subcc_imm: dest:i src1:i len:64
-mul_imm: dest:i src1:i len:64
-div_imm: dest:a src1:i src2:i len:64
-div_un_imm: dest:a src1:i src2:i len:64
-rem_imm: dest:d src1:i src2:i len:64
-rem_un_imm: dest:d src1:i src2:i len:64
-and_imm: dest:i src1:i len:64
-or_imm: dest:i src1:i len:64
-xor_imm: dest:i src1:i len:64
-shl_imm: dest:i src1:i len:64
-shr_imm: dest:i src1:i len:64
-shr_un_imm: dest:i src1:i len:64
-cond_exc_eq: len:64
-cond_exc_ne_un: len:64
-cond_exc_lt: len:64
-cond_exc_lt_un: len:64
-cond_exc_gt: len:64
-cond_exc_gt_un: len:64
-cond_exc_ge: len:64
-cond_exc_ge_un: len:64
-cond_exc_le: len:64
-cond_exc_le_un: len:64
-cond_exc_ov: len:64
-cond_exc_no: len:64
-cond_exc_c: len:64
-cond_exc_nc: len:64
-float_beq: len:8
-float_bne_un: len:64
-float_blt: len:8
-float_blt_un: len:64
-float_bgt: len:8
-float_bgt_un: len:64
-float_bge: len:64
-float_bge_un: len:64
-float_ble: len:64
-float_ble_un: len:64
-float_add: dest:f src1:f src2:f len:4
-float_sub: dest:f src1:f src2:f len:4
-float_mul: dest:f src1:f src2:f len:4
-float_div: dest:f src1:f src2:f len:4
-float_div_un: dest:f src1:f src2:f len:4
-float_rem: dest:f src1:f src2:f len:64
-float_rem_un: dest:f src1:f src2:f len:64
-float_neg: dest:f src1:f len:4
-float_not: dest:f src1:f len:4
-float_conv_to_i1: dest:i src1:f len:40
-float_conv_to_i2: dest:i src1:f len:40
-float_conv_to_i4: dest:i src1:f len:40
-float_conv_to_i8: dest:L src1:f len:40
-float_conv_to_r4: dest:f src1:f len:8
-float_conv_to_u4: dest:i src1:f len:40
-float_conv_to_u8: dest:L src1:f len:40
-float_conv_to_u2: dest:i src1:f len:40
-float_conv_to_u1: dest:i src1:f len:40
-float_ceq: dest:i src1:f src2:f len:64
-float_cgt: dest:i src1:f src2:f len:64
-float_cgt_un: dest:i src1:f src2:f len:64
-float_clt: dest:i src1:f src2:f len:64
-float_clt_un: dest:i src1:f src2:f len:64
-call_handler: len:64 clob:c
-aotconst: dest:i len:64
-adc: dest:i src1:i src2:i len:4
-addcc: dest:i src1:i src2:i len:4
-subcc: dest:i src1:i src2:i len:4
-adc_imm: dest:i src1:i len:64
-sbb: dest:i src1:i src2:i len:4
-sbb_imm: dest:i src1:i len:64
-br_reg: src1:i len:8
-bigmul: len:2 dest:L src1:a src2:i
-bigmul_un: len:2 dest:L src1:a src2:i
-fmove: dest:f src1:f len:8
-
-# 32 bit opcodes
-int_add: dest:i src1:i src2:i len:64
-int_sub: dest:i src1:i src2:i len:64
-int_mul: dest:i src1:i src2:i len:64
-int_div: dest:i src1:i src2:i len:64
-int_div_un: dest:i src1:i src2:i len:64
-int_rem: dest:i src1:i src2:i len:64
-int_rem_un: dest:i src1:i src2:i len:64
-int_and: dest:i src1:i src2:i len:64
-int_or: dest:i src1:i src2:i len:64
-int_xor: dest:i src1:i src2:i len:64
-int_shl: dest:i src1:i src2:i len:64
-int_shr: dest:i src1:i src2:i len:64
-int_shr_un: dest:i src1:i src2:i len:64
-int_adc: dest:i src1:i src2:i len:64
-int_adc_imm: dest:i src1:i len:64
-int_sbb: dest:i src1:i src2:i len:64
-int_sbb_imm: dest:i src1:i len:64
-int_addcc: dest:i src1:i src2:i len:64
-int_subcc: dest:i src1:i src2:i len:64
-int_add_imm: dest:i src1:i len:64
-int_sub_imm: dest:i src1:i len:64
-int_mul_imm: dest:i src1:i len:64
-int_div_imm: dest:i src1:i len:64
-int_div_un_imm: dest:i src1:i len:64
-int_rem_imm: dest:i src1:i len:64
-int_rem_un_imm: dest:i src1:i len:64
-int_and_imm: dest:i src1:i len:64
-int_or_imm: dest:i src1:i len:64
-int_xor_imm: dest:i src1:i len:64
-int_shl_imm: dest:i src1:i len:64
-int_shr_imm: dest:i src1:i len:64
-int_shr_un_imm: dest:i src1:i len:64
-int_mul_ovf: dest:i src1:i src2:i len:64
-int_mul_ovf_un: dest:i src1:i src2:i len:64
-int_conv_to_i1: dest:i src1:i len:8
-int_conv_to_i2: dest:i src1:i len:8
-int_conv_to_i4: dest:i src1:i len:4
-int_conv_to_i8: dest:i src1:i len:4
-int_conv_to_r4: dest:f src1:i len:64
-int_conv_to_r8: dest:f src1:i len:64
-int_conv_to_u4: dest:i src1:i len:4
-int_conv_to_u8: dest:i src1:i len:4
-int_conv_to_u2: dest:i src1:i len:8
-int_conv_to_u1: dest:i src1:i len:4
-int_conv_to_i: dest:i src1:i len:4
-int_neg: dest:i src1:i len:64
-int_not: dest:i src1:i len:64
-int_ceq: dest:i len:64
-int_cgt: dest:i len:64
-int_cgt_un: dest:i len:64
-int_clt: dest:i len:64
-int_clt_un: dest:i len:64
-int_beq: len:8
-int_bge: len:8
-int_bgt: len:8
-int_ble: len:8
-int_blt: len:8
-int_bne_un: len:64
-int_bge_un: len:64
-int_bgt_un: len:64
-int_ble_un: len:64
-int_blt_un: len:64
-
-# 64 bit opcodes
-long_shl: dest:i src1:i src2:i len:64
-long_shr: dest:i src1:i src2:i len:64
-long_shr_un: dest:i src1:i src2:i len:64
-long_conv_to_ovf_i: dest:i src1:i src2:i len:48
-long_mul_ovf:
-long_conv_to_r_un: dest:f src1:i src2:i len:64
-long_shr_imm: dest:i src1:i len:64
-long_shr_un_imm: dest:i src1:i len:64
-long_shl_imm: dest:i src1:i len:64
-
-memory_barrier: len:4
-
-sparc_brz: src1:i len: 8
-sparc_brlez: src1:i len: 8
-sparc_brlz: src1:i len: 8
-sparc_brnz: src1:i len: 8
-sparc_brgz: src1:i len: 8
-sparc_brgez: src1:i len: 8
-sparc_cond_exc_eqz: src1:i len:64
-sparc_cond_exc_nez: src1:i len:64
-sparc_cond_exc_ltz: src1:i len:64
-sparc_cond_exc_gtz: src1:i len:64
-sparc_cond_exc_gez: src1:i len:64
-sparc_cond_exc_lez: src1:i len:64
-
-relaxed_nop: len:0
-
-# Linear IR opcodes
-nop: len:0
-dummy_use: src1:i len:0
-dummy_iconst: dest:i len:0
-dummy_i8const: dest:i len:0
-dummy_r8const: dest:f len:0
-dummy_r4const: dest:f len:0
-not_reached: len:0
-not_null: src1:i len:0
-
-jump_table: dest:i len:64
-
-cond_exc_ieq: len:64
-cond_exc_ine_un: len:64
-cond_exc_ilt: len:64
-cond_exc_ilt_un: len:64
-cond_exc_igt: len:64
-cond_exc_igt_un: len:64
-cond_exc_ige: len:64
-cond_exc_ige_un: len:64
-cond_exc_ile: len:64
-cond_exc_ile_un: len:64
-cond_exc_iov: len:64
-cond_exc_ino: len:64
-cond_exc_ic: len:64
-cond_exc_inc: len:64
-
-long_conv_to_ovf_i4_2: dest:i src1:i src2:i len:48
-
-vcall2: len:40 clob:c
-vcall2_reg: src1:i len:64 clob:c
-vcall2_membase: src1:b len:64 clob:c
-
-liverange_start: len:0
-liverange_end: len:0
-gc_safe_point: len:0
+++ /dev/null
-/**
- * \file
- * exception support for MIPS
- *
- * Authors:
- * Mark Mason (mason@broadcom.com)
- *
- * Based on exceptions-ppc.c by:
- * Dietmar Maurer (dietmar@ximian.com)
- * Paolo Molaro (lupus@ximian.com)
- *
- * (C) 2006 Broadcom
- * (C) 2001 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <signal.h>
-#include <string.h>
-
-#include <mono/arch/mips/mips-codegen.h>
-#include <mono/metadata/tabledefs.h>
-#include <mono/metadata/threads.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/exception.h>
-#include <mono/metadata/mono-debug.h>
-
-#include "mini.h"
-#include "mini-mips.h"
-#include "mini-runtime.h"
-#include "aot-runtime.h"
-#include "mono/utils/mono-tls-inline.h"
-
-#define GENERIC_EXCEPTION_SIZE 256
-
-/*
- * mono_arch_get_restore_context:
- *
- * Returns a pointer to a method which restores a previously saved MonoContext.
- * The first argument in a0 is the pointer to the MonoContext.
- */
-gpointer
-mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
-{
- int i;
- guint8 *code;
- static guint8 start [512];
- static int inited = 0;
- guint32 iregs_to_restore;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
- inited = 1;
- code = start;
-
- mips_move (code, mips_at, mips_a0);
-
- iregs_to_restore = (MONO_ARCH_CALLEE_SAVED_REGS \
- | (1 << mips_sp) | (1 << mips_ra));
- for (i = 0; i < MONO_SAVED_GREGS; ++i) {
- //if (iregs_to_restore & (1 << i)) {
- if (i != mips_zero && i != mips_at) {
- MIPS_LW (code, i, mips_at, G_STRUCT_OFFSET (MonoContext, sc_regs[i]));
- }
- }
-
- /* Get the address to return to */
- mips_lw (code, mips_t9, mips_at, G_STRUCT_OFFSET (MonoContext, sc_pc));
-
- /* jump to the saved IP */
- mips_jr (code, mips_t9);
- mips_nop (code);
-
- /* never reached */
- mips_break (code, 0xff);
-
- g_assert ((code - start) < sizeof(start));
- mono_arch_flush_icache (start, code - start);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
- return start;
-}
-
-/*
- * mono_arch_get_call_filter:
- *
- * Returns a pointer to a method which calls an exception filter. We
- * also use this function to call finally handlers (we pass NULL as
- * @exc object in this case).
- *
- * This function is invoked as
- * call_handler (MonoContext *ctx, handler)
- *
- * Where 'handler' is a function to be invoked as:
- * handler (void)
- */
-gpointer
-mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
-{
- static guint8 start [320];
- static int inited = 0;
- guint8 *code;
- int alloc_size;
- int offset;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
-
- inited = 1;
- code = start;
-
- alloc_size = 64;
- g_assert ((alloc_size & (MIPS_STACK_ALIGNMENT-1)) == 0);
-
- mips_addiu (code, mips_sp, mips_sp, -alloc_size);
- mips_sw (code, mips_ra, mips_sp, alloc_size + MIPS_RET_ADDR_OFFSET);
-
- /* Save global registers on stack (s0 - s7) */
- offset = 16;
- MIPS_SW (code, mips_s0, mips_sp, offset); offset += IREG_SIZE;
- MIPS_SW (code, mips_s1, mips_sp, offset); offset += IREG_SIZE;
- MIPS_SW (code, mips_s2, mips_sp, offset); offset += IREG_SIZE;
- MIPS_SW (code, mips_s3, mips_sp, offset); offset += IREG_SIZE;
- MIPS_SW (code, mips_s4, mips_sp, offset); offset += IREG_SIZE;
- MIPS_SW (code, mips_s5, mips_sp, offset); offset += IREG_SIZE;
- MIPS_SW (code, mips_s6, mips_sp, offset); offset += IREG_SIZE;
- MIPS_SW (code, mips_s7, mips_sp, offset); offset += IREG_SIZE;
- MIPS_SW (code, mips_fp, mips_sp, offset); offset += IREG_SIZE;
-
- /* Restore global registers from MonoContext, including the frame pointer */
- MIPS_LW (code, mips_s0, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s0]));
- MIPS_LW (code, mips_s1, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s1]));
- MIPS_LW (code, mips_s2, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s2]));
- MIPS_LW (code, mips_s3, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s3]));
- MIPS_LW (code, mips_s4, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s4]));
- MIPS_LW (code, mips_s5, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s5]));
- MIPS_LW (code, mips_s6, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s6]));
- MIPS_LW (code, mips_s7, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_s7]));
- MIPS_LW (code, mips_fp, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[mips_fp]));
-
- /* a1 is the handler to call */
- mips_move (code, mips_t9, mips_a1);
-
- /* jump to the saved IP */
- mips_jalr (code, mips_t9, mips_ra);
- mips_nop (code);
-
- /* restore all regs from the stack */
- offset = 16;
- MIPS_LW (code, mips_s0, mips_sp, offset); offset += IREG_SIZE;
- MIPS_LW (code, mips_s1, mips_sp, offset); offset += IREG_SIZE;
- MIPS_LW (code, mips_s2, mips_sp, offset); offset += IREG_SIZE;
- MIPS_LW (code, mips_s3, mips_sp, offset); offset += IREG_SIZE;
- MIPS_LW (code, mips_s4, mips_sp, offset); offset += IREG_SIZE;
- MIPS_LW (code, mips_s5, mips_sp, offset); offset += IREG_SIZE;
- MIPS_LW (code, mips_s6, mips_sp, offset); offset += IREG_SIZE;
- MIPS_LW (code, mips_s7, mips_sp, offset); offset += IREG_SIZE;
- MIPS_LW (code, mips_fp, mips_sp, offset); offset += IREG_SIZE;
-
- /* epilog */
- mips_lw (code, mips_ra, mips_sp, alloc_size + MIPS_RET_ADDR_OFFSET);
- mips_addiu (code, mips_sp, mips_sp, alloc_size);
- mips_jr (code, mips_ra);
- mips_nop (code);
-
- g_assert ((code - start) < sizeof(start));
- mono_arch_flush_icache (start, code - start);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
- return start;
-}
-
-static void
-throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean rethrow, gboolean preserve_ips)
-{
- ERROR_DECL (error);
- MonoContext ctx;
-
-#ifdef DEBUG_EXCEPTIONS
- g_print ("throw_exception: exc=%p eip=%p esp=%p rethrow=%d\n",
- exc, (void *)eip, (void *) esp, rethrow);
-#endif
-
- /* adjust eip so that it point into the call instruction */
- eip -= 8;
-
- memset (&ctx, 0, sizeof (MonoContext));
-
- /*g_print ("stack in throw: %p\n", esp);*/
- memcpy (&ctx.sc_regs, (void *)(esp + MIPS_STACK_PARAM_OFFSET),
- sizeof (gulong) * MONO_SAVED_GREGS);
- memset (&ctx.sc_fpregs, 0, sizeof (mips_freg) * MONO_SAVED_FREGS);
- MONO_CONTEXT_SET_IP (&ctx, eip);
-
- if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) {
- MonoException *mono_ex = (MonoException*)exc;
- if (!rethrow && !mono_ex->caught_in_unmanaged) {
- mono_ex->stack_trace = NULL;
- mono_ex->trace_ips = NULL;
- } if (preserve_ips) {
- mono_ex->caught_in_unmanaged = TRUE;
- }
- }
- mono_error_assert_ok (error);
- mono_handle_exception (&ctx, exc);
-#ifdef DEBUG_EXCEPTIONS
- g_print ("throw_exception: restore to pc=%p sp=%p fp=%p ctx=%p\n",
- (void *) ctx.sc_pc, (void *) ctx.sc_regs[mips_sp],
- (void *) ctx.sc_regs[mips_fp], &ctx);
-#endif
- mono_restore_context (&ctx);
-
- g_assert_not_reached ();
-}
-
-/**
- * arch_get_throw_exception_generic:
- *
- * Returns a function pointer which can be used to raise
- * exceptions. The returned function has the following
- * signature: void (*func) (MonoException *exc); or
- * void (*func) (char *exc_name);
- *
- */
-static gpointer
-mono_arch_get_throw_exception_generic (guint8 *start, int size, int corlib, gboolean rethrow, gboolean preserve_ips)
-{
- guint8 *code;
- int alloc_size, pos, i;
-
- code = start;
-
- //g_print ("mono_arch_get_throw_exception_generic: code=%p\n", code);
-
- pos = 0;
- /* XXX - save all the FP regs on the stack ? */
-
- pos += MONO_MAX_IREGS * sizeof(guint32);
-
- alloc_size = MIPS_MINIMAL_STACK_SIZE + pos + 64;
- // align to MIPS_STACK_ALIGNMENT bytes
- alloc_size += MIPS_STACK_ALIGNMENT - 1;
- alloc_size &= ~(MIPS_STACK_ALIGNMENT - 1);
-
- g_assert ((alloc_size & (MIPS_STACK_ALIGNMENT-1)) == 0);
- mips_addiu (code, mips_sp, mips_sp, -alloc_size);
- mips_sw (code, mips_ra, mips_sp, alloc_size + MIPS_RET_ADDR_OFFSET);
-
- /* Save all the regs on the stack */
- for (i = 0; i < MONO_MAX_IREGS; i++) {
- if (i != mips_sp)
- MIPS_SW (code, i, mips_sp, i*IREG_SIZE + MIPS_STACK_PARAM_OFFSET);
- else {
- mips_addiu (code, mips_at, mips_sp, alloc_size);
- MIPS_SW (code, mips_at, mips_sp, i*IREG_SIZE + MIPS_STACK_PARAM_OFFSET);
- }
- }
-
- if (corlib) {
- mips_move (code, mips_a1, mips_a0);
- mips_load (code, mips_a0, mono_defaults.corlib);
- mips_load (code, mips_t9, mono_exception_from_token);
- mips_jalr (code, mips_t9, mips_ra);
- mips_nop (code);
- mips_move (code, mips_a0, mips_v0);
- }
- /* call throw_exception (exc, ip, sp, rethrow) */
-
- /* exc is already in place in a0 */
-
- /* pointer to ip */
- if (corlib)
- mips_lw (code, mips_a1, mips_sp, alloc_size + MIPS_RET_ADDR_OFFSET);
- else
- mips_move (code, mips_a1, mips_ra);
-
- /* current sp & rethrow */
- mips_move (code, mips_a2, mips_sp);
- mips_addiu (code, mips_a3, mips_zero, rethrow);
-
- mips_load (code, mips_t9, throw_exception);
- mips_jr (code, mips_t9);
- mips_nop (code);
- /* we should never reach this breakpoint */
- mips_break (code, 0xfe);
-
- g_assert ((code - start) < size);
- mono_arch_flush_icache (start, code - start);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
- return start;
-}
-
-/**
- * mono_arch_get_rethrow_exception:
- * \returns a function pointer which can be used to rethrow
- * exceptions. The returned function has the following
- * signature: void (*func) (MonoException *exc);
- */
-gpointer
-mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
-{
- static guint8 start [GENERIC_EXCEPTION_SIZE];
- static int inited = 0;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
- mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, TRUE, FALSE);
- inited = 1;
- return start;
-}
-
-/**
- * mono_arch_get_rethrow_preserve_exception:
- * \returns a function pointer which can be used to rethrow
- * exceptions while avoiding modification of saved trace_ips.
- * The returned function has the following
- * signature: void (*func) (MonoException *exc);
- */
-gpointer
-mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
-{
- static guint8 start [GENERIC_EXCEPTION_SIZE];
- static int inited = 0;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
- mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, TRUE, TRUE);
- inited = 1;
- return start;
-}
-
-/**
- * arch_get_throw_exception:
- *
- * Returns a function pointer which can be used to raise
- * exceptions. The returned function has the following
- * signature: void (*func) (MonoException *exc);
- * For example to raise an arithmetic exception you can use:
- *
- * x86_push_imm (code, mono_get_exception_arithmetic ());
- * x86_call_code (code, arch_get_throw_exception ());
- *
- */
-gpointer
-mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
-{
- static guint8 start [GENERIC_EXCEPTION_SIZE];
- static int inited = 0;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
- mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, FALSE, FALSE);
- inited = 1;
- return start;
-}
-
-gpointer
-mono_arch_get_throw_exception_by_name (void)
-{
- guint8 *start, *code;
- int size = 64;
-
- /* Not used on MIPS */
- start = code = mono_global_codeman_reserve (size);
- mips_break (code, 0xfd);
- mono_arch_flush_icache (start, code - start);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
- return start;
-}
-
-/**
- * mono_arch_get_throw_corlib_exception:
- * \returns a function pointer which can be used to raise
- * corlib exceptions. The returned function has the following
- * signature: void (*func) (guint32 ex_token, guint32 offset);
- * On MIPS, the offset argument is missing.
- */
-gpointer
-mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
-{
- static guint8 start [GENERIC_EXCEPTION_SIZE];
- static int inited = 0;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
- mono_arch_get_throw_exception_generic (start, sizeof (start), TRUE, FALSE, FALSE);
- inited = 1;
- return start;
-}
-
-/*
- * mono_arch_unwind_frame:
- *
- * This function is used to gather information from @ctx, and store it in @frame_info.
- * It unwinds one stack frame, and stores the resulting context into @new_ctx. @lmf
- * is modified if needed.
- * Returns TRUE on success, FALSE otherwise.
- */
-gboolean
-mono_arch_unwind_frame (MonoJitTlsData *jit_tls,
- MonoJitInfo *ji, MonoContext *ctx,
- MonoContext *new_ctx, MonoLMF **lmf,
- host_mgreg_t **save_locations,
- StackFrameInfo *frame)
-{
- memset (frame, 0, sizeof (StackFrameInfo));
- frame->ji = ji;
-
- *new_ctx = *ctx;
-
- if (ji != NULL) {
- int i;
- gpointer ip = MONO_CONTEXT_GET_IP (ctx);
- host_mgreg_t regs [MONO_MAX_IREGS + 1];
- guint8 *cfa;
- guint32 unwind_info_len;
- guint8 *unwind_info;
-
- if (ji->is_trampoline)
- frame->type = FRAME_TYPE_TRAMPOLINE;
- else
- frame->type = FRAME_TYPE_MANAGED;
-
- unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
-
- for (i = 0; i < MONO_MAX_IREGS; ++i)
- regs [i] = new_ctx->sc_regs [i];
-
- gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start,
- (guint8*)ji->code_start + ji->code_size,
- ip, NULL, regs, MONO_MAX_IREGS,
- save_locations, MONO_MAX_IREGS, &cfa);
-
- if (!success)
- return FALSE;
-
- for (i = 0; i < MONO_MAX_IREGS; ++i)
- new_ctx->sc_regs [i] = regs [i];
- new_ctx->sc_pc = regs [mips_ra];
- new_ctx->sc_regs [mips_sp] = (host_mgreg_t)(gsize)cfa;
-
- /* we substract 8, so that the IP points into the call instruction */
- MONO_CONTEXT_SET_IP (new_ctx, new_ctx->sc_pc - 8);
-
- /* Sanity check -- we should have made progress here */
- g_assert (MONO_CONTEXT_GET_SP (new_ctx) != MONO_CONTEXT_GET_SP (ctx));
- return TRUE;
- } else if (*lmf) {
- g_assert ((((guint64)(*lmf)->previous_lmf) & 2) == 0);
-
- if (!(*lmf)->method) {
-#ifdef DEBUG_EXCEPTIONS
- g_print ("mono_arch_unwind_frame: bad lmf @ %p\n", (void *) *lmf);
-#endif
- return FALSE;
- }
- g_assert (((*lmf)->magic == MIPS_LMF_MAGIC1) || ((*lmf)->magic == MIPS_LMF_MAGIC2));
-
- ji = mini_jit_info_table_find ((gpointer)(*lmf)->eip);
- if (!ji)
- return FALSE;
-
- frame->ji = ji;
- frame->type = FRAME_TYPE_MANAGED_TO_NATIVE;
-
- memcpy (&new_ctx->sc_regs, (*lmf)->iregs, sizeof (gulong) * MONO_SAVED_GREGS);
- memcpy (&new_ctx->sc_fpregs, (*lmf)->fregs, sizeof (float) * MONO_SAVED_FREGS);
- MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip);
- /* ensure that we've made progress */
- g_assert (new_ctx->sc_pc != ctx->sc_pc);
-
- *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-gpointer
-mono_arch_ip_from_context (void *sigctx)
-{
- return (gpointer)(gsize)UCONTEXT_REG_PC (sigctx);
-}
-
-/*
- * handle_exception:
- *
- * Called by resuming from a signal handler.
- */
-static void
-handle_signal_exception (gpointer obj)
-{
- MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
- MonoContext ctx;
-
- memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
-
- mono_handle_exception (&ctx, obj);
-
- mono_restore_context (&ctx);
-}
-
-/*
- * This is the function called from the signal handler
- */
-gboolean
-mono_arch_handle_exception (void *ctx, gpointer obj)
-{
-#if defined(MONO_CROSS_COMPILE)
- g_assert_not_reached ();
-#elif defined(MONO_ARCH_USE_SIGACTION)
- void *sigctx = ctx;
-
- /*
- * Handling the exception in the signal handler is problematic, since the original
- * signal is disabled, and we could run arbitrary code though the debugger. So
- * resume into the normal stack and do most work there if possible.
- */
- MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
- guint64 sp = UCONTEXT_GREGS (sigctx) [mips_sp];
-
- /* Pass the ctx parameter in TLS */
- mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
- /* The others in registers */
- UCONTEXT_GREGS (sigctx)[mips_a0] = (gsize)obj;
-
- /* Allocate a stack frame */
- sp -= 256;
- UCONTEXT_GREGS (sigctx)[mips_sp] = sp;
-
- UCONTEXT_REG_PC (sigctx) = (gsize)handle_signal_exception;
-
- return TRUE;
-#else
- MonoContext mctx;
- gboolean result;
-
- mono_sigctx_to_monoctx (ctx, &mctx);
-
- result = mono_handle_exception (&mctx, obj);
- /* restore the context so that returning from the signal handler will invoke
- * the catch clause
- */
- mono_monoctx_to_sigctx (&mctx, ctx);
- return result;
-#endif
-}
-
-/*
- * mono_arch_setup_resume_sighandler_ctx:
- *
- * Setup CTX so execution continues at FUNC.
- */
-void
-mono_arch_setup_resume_sighandler_ctx (MonoContext *ctx, gpointer func)
-{
- MONO_CONTEXT_SET_IP (ctx,func);
-}
+++ /dev/null
-/**
- * \file
- * exception support for sparc
- *
- * Authors:
- * Mark Crichton (crichton@gimp.org)
- * Dietmar Maurer (dietmar@ximian.com)
- *
- * (C) 2003 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/ucontext.h>
-
-#include <mono/arch/sparc/sparc-codegen.h>
-#include <mono/metadata/tabledefs.h>
-#include <mono/metadata/threads.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/exception.h>
-#include <mono/metadata/mono-debug.h>
-#include <mono/metadata/gc-internals.h>
-#include <mono/metadata/tokentype.h>
-
-#include "mini.h"
-#include "mini-sparc.h"
-#include "mono/utils/mono-tls-inline.h"
-
-#ifndef REG_SP
-#define REG_SP REG_O6
-#endif
-
-#define MONO_SPARC_WINDOW_ADDR(sp) ((gpointer*)(((guint8*)(sp)) + MONO_SPARC_STACK_BIAS))
-
-/*
- * mono_arch_get_restore_context:
- *
- * Returns a pointer to a method which restores a previously saved sigcontext.
- */
-gpointer
-mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
-{
- static guint32 *start;
- static int inited = 0;
- guint32 *code;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
-
- code = start = mono_global_codeman_reserve (32 * sizeof (guint32));
-
- sparc_ldi_imm (code, sparc_o0, G_STRUCT_OFFSET (MonoContext, ip), sparc_i7);
- sparc_ldi_imm (code, sparc_o0, G_STRUCT_OFFSET (MonoContext, sp), sparc_i6);
-
- sparc_jmpl_imm (code, sparc_i7, 0, sparc_g0);
- /* FIXME: This does not return to the correct window */
- sparc_restore_imm (code, sparc_g0, 0, sparc_g0);
-
- g_assert ((code - start) < 32);
-
- mono_arch_flush_icache ((guint8*)start, (guint8*)code - (guint8*)start);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
-
- inited = 1;
-
- return start;
-}
-
-/*
- * mono_arch_get_call_filter:
- *
- * Returns a pointer to a method which calls an exception filter. We
- * also use this function to call finally handlers (we pass NULL as
- * @exc object in this case).
- *
- * call_filter (MonoContext *ctx, gpointer ip)
- */
-gpointer
-mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
-{
- static guint32 *start;
- static int inited = 0;
- guint32 *code;
- int i;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
-
- code = start = mono_global_codeman_reserve (64 * sizeof (guint32));
-
- /*
- * There are two frames here:
- * - the first frame is used by call_filter
- * - the second frame is used to run the filter code
- */
-
- /* Create first frame */
- sparc_save_imm (code, sparc_sp, -256, sparc_sp);
-
- sparc_mov_reg_reg (code, sparc_i1, sparc_o0);
- sparc_ldi_imm (code, sparc_i0, G_STRUCT_OFFSET (MonoContext, sp), sparc_o1);
-
- /* Create second frame */
- sparc_save_imm (code, sparc_sp, -256, sparc_sp);
-
- sparc_mov_reg_reg (code, sparc_i0, sparc_o0);
- sparc_mov_reg_reg (code, sparc_i1, sparc_o1);
-
- /*
- * We need to change %fp to point to the stack frame of the method
- * containing the filter. But changing %fp also changes the %sp of
- * the parent frame (the first frame), so if the OS saves the first frame,
- * it saves it to the stack frame of the method, which is not good.
- * So flush all register windows to memory before changing %fp.
- */
- sparc_flushw (code);
-
- sparc_mov_reg_reg (code, sparc_fp, sparc_o7);
-
- /*
- * Modify the second frame so it is identical to the one used in the
- * method containing the filter.
- */
- for (i = 0; i < 16; ++i)
- sparc_ldi_imm (code, sparc_o1, MONO_SPARC_STACK_BIAS + i * sizeof (target_mgreg_t), sparc_l0 + i);
-
- /* Save %fp to a location reserved in mono_arch_allocate_vars */
- sparc_sti_imm (code, sparc_o7, sparc_fp, MONO_SPARC_STACK_BIAS - sizeof (target_mgreg_t));
-
- /* Call the filter code, after this returns, %o0 will hold the result */
- sparc_call_imm (code, sparc_o0, 0);
- sparc_nop (code);
-
- /* Restore original %fp */
- sparc_ldi_imm (code, sparc_fp, MONO_SPARC_STACK_BIAS - sizeof (target_mgreg_t), sparc_fp);
-
- sparc_mov_reg_reg (code, sparc_o0, sparc_i0);
-
- /* Return to first frame */
- sparc_restore (code, sparc_g0, sparc_g0, sparc_g0);
-
- /* FIXME: Save locals to the stack */
-
- /* Return to caller */
- sparc_ret (code);
- /* Return result in delay slot */
- sparc_restore (code, sparc_o0, sparc_g0, sparc_o0);
-
- g_assert ((code - start) < 64);
-
- mono_arch_flush_icache ((guint8*)start, (guint8*)code - (guint8*)start);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
-
- inited = 1;
-
- return start;
-}
-
-static void
-throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow, gboolean preserve_ips)
-{
- ERROR_DECL (error);
- MonoContext ctx;
- static void (*restore_context) (MonoContext *);
- gpointer *window;
-
- if (!restore_context)
- restore_context = mono_get_restore_context ();
-
- window = MONO_SPARC_WINDOW_ADDR (sp);
- ctx.sp = (gpointer*)sp;
- ctx.ip = ip;
- ctx.fp = (gpointer*)(MONO_SPARC_WINDOW_ADDR (sp) [sparc_i6 - 16]);
-
- if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) {
- MonoException *mono_ex = (MonoException*)exc;
- if (!rethrow && !mono_ex->caught_in_unmanaged) {
- mono_ex->stack_trace = NULL;
- mono_ex->trace_ips = NULL;
- } else (preserve_ips) {
- mono_ex->caught_in_unmanaged = NULL;
- }
- }
- mono_error_assert_ok (error);
- mono_handle_exception (&ctx, exc);
- restore_context (&ctx);
-
- g_assert_not_reached ();
-}
-
-static gpointer
-get_throw_exception (gboolean rethrow, gboolean preserve_ips)
-{
- guint32 *start, *code;
-
- code = start = mono_global_codeman_reserve (16 * sizeof (guint32));
-
- sparc_save_imm (code, sparc_sp, -512, sparc_sp);
-
- sparc_flushw (code);
- sparc_mov_reg_reg (code, sparc_i0, sparc_o0);
- sparc_mov_reg_reg (code, sparc_fp, sparc_o1);
- sparc_mov_reg_reg (code, sparc_i7, sparc_o2);
- sparc_set (code, rethrow, sparc_o3);
- sparc_set (code, preserve_ips, sparc_o3);
- sparc_set (code, throw_exception, sparc_o7);
- sparc_jmpl (code, sparc_o7, sparc_g0, sparc_callsite);
- sparc_nop (code);
-
- g_assert ((code - start) <= 16);
-
- mono_arch_flush_icache ((guint8*)start, (guint8*)code - (guint8*)start);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
-
- return start;
-}
-
-/**
- * mono_arch_get_throw_exception:
- * \returns a function pointer which can be used to raise exceptions.
- * The returned function has the following
- * signature: void (*func) (MonoException *exc);
- */
-gpointer
-mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
-{
- static guint32* start;
- static int inited = 0;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
-
- inited = 1;
-
- start = get_throw_exception (FALSE, FALSE);
-
- return start;
-}
-
-gpointer
-mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
-{
- static guint32* start;
- static int inited = 0;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
-
- inited = 1;
-
- start = get_throw_exception (TRUE, FALSE);
-
- return start;
-}
-
-gpointer
-mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
-{
- static guint32* start;
- static int inited = 0;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
-
- inited = 1;
-
- start = get_throw_exception (TRUE, TRUE);
-
- return start;
-}
-
-/**
- * mono_arch_get_throw_corlib_exception:
- * \returns a function pointer which can be used to raise
- * corlib exceptions. The returned function has the following
- * signature: void (*func) (guint32 ex_token, guint32 offset);
- * Here, offset is the offset which needs to be substracted from the caller IP
- * to get the IP of the throw. Passing the offset has the advantage that it
- * needs no relocations in the caller.
- */
-gpointer
-mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
-{
- static guint32 *start;
- static int inited = 0;
- guint32 *code;
- int reg;
-
- g_assert (!aot);
- if (info)
- *info = NULL;
-
- if (inited)
- return start;
-
- inited = 1;
- code = start = mono_global_codeman_reserve (64 * sizeof (guint32));
-
-#ifdef SPARCV9
- reg = sparc_g4;
-#else
- reg = sparc_g1;
-#endif
-
- sparc_mov_reg_reg (code, sparc_o7, sparc_o2);
- sparc_save_imm (code, sparc_sp, -160, sparc_sp);
-
- sparc_set (code, MONO_TOKEN_TYPE_DEF, sparc_o7);
- sparc_add (code, FALSE, sparc_i0, sparc_o7, sparc_o1);
- sparc_set (code, m_class_get_image (mono_defaults.exception_class), sparc_o0);
- sparc_set (code, mono_exception_from_token, sparc_o7);
- sparc_jmpl (code, sparc_o7, sparc_g0, sparc_callsite);
- sparc_nop (code);
-
- /* Return to the caller, so exception handling does not see this frame */
- sparc_restore (code, sparc_o0, sparc_g0, sparc_o0);
-
- /* Compute throw ip */
- sparc_sll_imm (code, sparc_o1, 2, sparc_o1);
- sparc_sub (code, 0, sparc_o2, sparc_o1, sparc_o7);
-
- sparc_set (code, mono_arch_get_throw_exception (NULL, FALSE), reg);
- /* Use a jmp instead of a call so o7 is preserved */
- sparc_jmpl_imm (code, reg, 0, sparc_g0);
- sparc_nop (code);
-
- g_assert ((code - start) < 32);
-
- mono_arch_flush_icache ((guint8*)start, (guint8*)code - (guint8*)start);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
-
- return start;
-}
-
-/* mono_arch_unwind_frame:
- *
- * This function is used to gather information from @ctx. It return the
- * MonoJitInfo of the corresponding function, unwinds one stack frame and
- * stores the resulting context into @new_ctx. It also stores a string
- * describing the stack location into @trace (if not NULL), and modifies
- * the @lmf if necessary. @native_offset return the IP offset from the
- * start of the function or -1 if that info is not available.
- */
-gboolean
-mono_arch_unwind_frame (MonoJitTlsData *jit_tls,
- MonoJitInfo *ji, MonoContext *ctx,
- MonoContext *new_ctx, MonoLMF **lmf,
- host_mgreg_t **save_locations,
- StackFrameInfo *frame)
-{
- gpointer *window;
-
- memset (frame, 0, sizeof (StackFrameInfo));
- frame->ji = ji;
-
- *new_ctx = *ctx;
-
- if (ji != NULL) {
- if (ji->is_trampoline)
- frame->type = FRAME_TYPE_TRAMPOLINE;
- else
- frame->type = FRAME_TYPE_MANAGED;
-
- /* Restore ip and sp from the saved register window */
- window = MONO_SPARC_WINDOW_ADDR (ctx->sp);
- new_ctx->ip = window [sparc_i7 - 16];
- new_ctx->sp = (gpointer*)(window [sparc_i6 - 16]);
- new_ctx->fp = (gpointer*)(MONO_SPARC_WINDOW_ADDR (new_ctx->sp) [sparc_i6 - 16]);
-
- return TRUE;
- }
- else {
- if (!(*lmf))
- return FALSE;
-
- if (!(*lmf)->method)
- return FALSE;
-
- ji = mini_jit_info_table_find ((gpointer)(*lmf)->ip);
- if (!ji)
- return FALSE;
-
- frame->ji = ji;
- frame->type = FRAME_TYPE_MANAGED_TO_NATIVE;
-
- new_ctx->ip = (*lmf)->ip;
- new_ctx->sp = (*lmf)->sp;
- new_ctx->fp = (*lmf)->ebp;
-
- *lmf = (*lmf)->previous_lmf;
-
- return TRUE;
- }
-}
-
-#ifdef __linux__
-
-gboolean
-mono_arch_handle_exception (void *sigctx, gpointer obj)
-{
- MonoContext mctx;
- struct sigcontext *sc = sigctx;
- gpointer *window;
-
-#ifdef SPARCV9
- mctx.ip = (gpointer) sc->sigc_regs.tpc;
- mctx.sp = (gpointer) sc->sigc_regs.u_regs[14];
-#else
- mctx.ip = (gpointer) sc->si_regs.pc;
- mctx.sp = (gpointer) sc->si_regs.u_regs[14];
-#endif
-
- window = (gpointer*)(((guint8*)mctx.sp) + MONO_SPARC_STACK_BIAS);
- mctx.fp = window [sparc_fp - 16];
-
- mono_handle_exception (&mctx, obj);
-
-#ifdef SPARCV9
- sc->sigc_regs.tpc = (unsigned long) mctx.ip;
- sc->sigc_regs.tnpc = (unsigned long) (mctx.ip + 4);
- sc->sigc_regs.u_regs[14] = (unsigned long) mctx.sp;
-#else
- sc->si_regs.pc = (unsigned long) mctx.ip;
- sc->si_regs.npc = (unsigned long) (mctx.ip + 4);
- sc->si_regs.u_regs[14] = (unsigned long) mctx.sp;
-#endif
-
- window = (gpointer*)(((guint8*)mctx.sp) + MONO_SPARC_STACK_BIAS);
- window [sparc_fp - 16] = mctx.fp;
-
- return TRUE;
-}
-
-gpointer
-mono_arch_ip_from_context (void *sigctx)
-{
- struct sigcontext *sc = sigctx;
- gpointer *ret;
-
-#ifdef SPARCV9
- ret = (gpointer) sc->sigc_regs.tpc;
-#else
- ret = (gpointer) sc->si_regs.pc;
-#endif
-
- return ret;
-}
-
-#else /* !__linux__ */
-
-gboolean
-mono_arch_handle_exception (void *sigctx, gpointer obj)
-{
- MonoContext mctx;
- ucontext_t *ctx = (ucontext_t*)sigctx;
- gpointer *window;
-
- /*
- * Access to the machine state using the ucontext_t parameter is somewhat
- * under documented under solaris. The code below seems to work under
- * Solaris 9.
- */
- g_assert (!ctx->uc_mcontext.gwins);
-
- mctx.ip = ctx->uc_mcontext.gregs [REG_PC];
- mctx.sp = ctx->uc_mcontext.gregs [REG_SP];
- window = (gpointer*)(((guint8*)mctx.sp) + MONO_SPARC_STACK_BIAS);
- mctx.fp = window [sparc_fp - 16];
-
- mono_handle_exception (&mctx, obj);
-
- /* We can't use restore_context to return from a signal handler */
- ctx->uc_mcontext.gregs [REG_PC] = mctx.ip;
- ctx->uc_mcontext.gregs [REG_nPC] = mctx.ip + 4;
- ctx->uc_mcontext.gregs [REG_SP] = mctx.sp;
- window = (gpointer*)(((guint8*)mctx.sp) + MONO_SPARC_STACK_BIAS);
- window [sparc_fp - 16] = mctx.fp;
-
- return TRUE;
-}
-
-gpointer
-mono_arch_ip_from_context (void *sigctx)
-{
- ucontext_t *ctx = (ucontext_t*)sigctx;
- return (gpointer)ctx->uc_mcontext.gregs [REG_PC];
-}
-
-#endif
"TARGET_ARM" : 1,
"TARGET_ARM64" : 1,
"TARGET_POWERPC" : 1,
- "TARGET_SPARC" : 1,
"TARGET_S390X" : 1,
- "TARGET_MIPS" : 1,
"TARGET_RISCV" : 1,
"TARGET_RISCV32" : 1,
"TARGET_RISCV64" : 1,
#define DIS_CMD "otool -v -t"
#endif
#else
-#if defined(sparc) && !defined(__GNUC__)
-#define DIS_CMD "dis"
-#elif defined(TARGET_X86)
+#if defined(TARGET_X86)
#define DIS_CMD "objdump -l -d"
#elif defined(TARGET_AMD64)
#if defined(HOST_WIN32)
#endif
#endif
-#if defined(sparc)
-#define AS_CMD "as -xarch=v9"
-#elif defined (TARGET_X86)
+#if defined (TARGET_X86)
# if defined(__APPLE__)
# define AS_CMD "as -arch i386"
# else
# else
# define AS_CMD "as -gstabs"
# endif
-#elif defined(__mips__) && (_MIPS_SIM == _ABIO32)
-#define AS_CMD "as -mips32"
#elif defined(__ppc64__)
#define AS_CMD "as -arch ppc64"
#elif defined(__powerpc64__)
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
- <dict>
- <key>com.apple.security.cs.allow-jit</key>
- <true/>
- <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
- <true/>
- <key>com.apple.security.cs.allow-dyld-environment-variables</key>
- <true/>
- <key>com.apple.security.cs.disable-library-validation</key>
- <true/>
- </dict>
-</plist>
for (i = 0; i < AMD64_NREG; ++i) {
if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->arch.saved_iregs & (1 << i))) {
/* Restore only used_int_regs, not arch.saved_iregs */
-#if defined(MONO_SUPPORT_TASKLETS)
- int restore_reg = 1;
-#else
int restore_reg = (cfg->used_int_regs & (1 << i));
-#endif
if (restore_reg) {
amd64_mov_reg_membase (code, i, cfg->frame_reg, save_area_offset, 8);
mono_emit_unwind_op_same_value (cfg, code, i);
#define MONO_ARCH_AOT_SUPPORTED 1
#define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
-#define MONO_ARCH_SUPPORT_TASKLETS 1
-
#define MONO_ARCH_GSHARED_SUPPORTED 1
#define MONO_ARCH_DYN_CALL_SUPPORTED 1
#define MONO_ARCH_DYN_CALL_PARAM_AREA 0
#include "mini-amd64.h"
#elif defined(TARGET_POWERPC)
#include "mini-ppc.h"
-#elif defined(__sparc__) || defined(sparc)
-#include "mini-sparc.h"
#elif defined(TARGET_S390X)
# if defined(__s390x__)
# include "mini-s390x.h"
#include "mini-arm.h"
#elif defined(TARGET_ARM64)
#include "mini-arm64.h"
-#elif defined(__mips__)
-#include "mini-mips.h"
#elif defined (TARGET_RISCV)
#include "mini-riscv.h"
#elif TARGET_WASM
#include <mono/metadata/abi-details.h>
void
-mono_dump_metadata_offsets (void);
-
-void
mono_metadata_cross_helpers_run (void);
-
-static void
-mono_dump_jit_offsets (void)
-{
-#ifdef USED_CROSS_COMPILER_OFFSETS
- g_print ("#error not using native offsets\n");
-#else
- mono_dump_metadata_offsets ();
-
- g_print ("#ifndef DISABLE_JIT_OFFSETS\n");
- g_print ("#define USED_CROSS_COMPILER_OFFSETS\n");
-#define DISABLE_METADATA_OFFSETS
-#define DECL_OFFSET2(struct,field,offset) this_should_not_happen
-#define DECL_ALIGN2(type,size) this_should_not_happen
-
-#define DECL_OFFSET(struct,field) g_print ("DECL_OFFSET2(%s,%s,%d)\n", #struct, #field, (int)MONO_STRUCT_OFFSET (struct, field));
-#define DECL_ALIGN(type)
-#define DECL_SIZE2(type,size) this_should_not_happen
-#define DECL_SIZE(type)
-#include <mono/metadata/object-offsets.h>
-
- g_print ("#endif //disable jit check\n");
- g_print ("#endif //cross compiler checks\n");
- g_print ("#endif //gc check\n");
- g_print ("#endif //os check\n");
- g_print ("#endif //arch check\n");
- g_print ("#endif //USED_CROSS_COMPILER_OFFSETS check\n");
-#endif
-}
-
/*
* mono_cross_helpers_run:
*
gboolean is_broken = FALSE;
#endif
-#ifndef USED_CROSS_COMPILER_OFFSETS
- if (g_hasenv ("DUMP_CROSS_OFFSETS"))
- mono_dump_jit_offsets ();
-#endif
-
#if defined (HAS_CROSS_COMPILER_OFFSETS) && !defined (MONO_CROSS_COMPILE)
mono_metadata_cross_helpers_run ();
/*
* simd_class_to_llvm_type:
*
- * Return the LLVM type corresponding to the Mono.SIMD class KLASS
+ * Return the LLVM type corresponding to the System.Numerics class KLASS
*/
static LLVMTypeRef
simd_class_to_llvm_type (EmitContext *ctx, MonoClass *klass)
{
const char *klass_name = m_class_get_name (klass);
- if (!strcmp (klass_name, "Vector2d")) {
- return LLVMVectorType (LLVMDoubleType (), 2);
- } else if (!strcmp (klass_name, "Vector2l")) {
- return LLVMVectorType (LLVMInt64Type (), 2);
- } else if (!strcmp (klass_name, "Vector2ul")) {
- return LLVMVectorType (LLVMInt64Type (), 2);
- } else if (!strcmp (klass_name, "Vector4i")) {
- return LLVMVectorType (LLVMInt32Type (), 4);
- } else if (!strcmp (klass_name, "Vector4ui")) {
- return LLVMVectorType (LLVMInt32Type (), 4);
- } else if (!strcmp (klass_name, "Vector4f")) {
- return LLVMVectorType (LLVMFloatType (), 4);
- } else if (!strcmp (klass_name, "Vector8s")) {
- return LLVMVectorType (LLVMInt16Type (), 8);
- } else if (!strcmp (klass_name, "Vector8us")) {
- return LLVMVectorType (LLVMInt16Type (), 8);
- } else if (!strcmp (klass_name, "Vector16sb")) {
- return LLVMVectorType (LLVMInt8Type (), 16);
- } else if (!strcmp (klass_name, "Vector16b")) {
- return LLVMVectorType (LLVMInt8Type (), 16);
- } else if (!strcmp (klass_name, "Vector2")) {
- /* System.Numerics */
+ if (!strcmp (klass_name, "Vector2")) {
return LLVMVectorType (LLVMFloatType (), 4);
} else if (!strcmp (klass_name, "Vector3")) {
return LLVMVectorType (LLVMFloatType (), 4);
+++ /dev/null
-/**
- * \file
- * MIPS backend for the Mono code generator
- *
- * Authors:
- * Mark Mason (mason@broadcom.com)
- *
- * Based on mini-ppc.c by
- * Paolo Molaro (lupus@ximian.com)
- * Dietmar Maurer (dietmar@ximian.com)
- *
- * (C) 2006 Broadcom
- * (C) 2003 Ximian, Inc.
- */
-#include "mini.h"
-#include <string.h>
-#include <asm/cachectl.h>
-
-#include <mono/metadata/abi-details.h>
-#include <mono/metadata/appdomain.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap.h>
-#include <mono/utils/unlocked.h>
-
-#include <mono/arch/mips/mips-codegen.h>
-
-#include "mini-mips.h"
-#include "cpu-mips.h"
-#include "ir-emit.h"
-#include "aot-runtime.h"
-#include "mini-runtime.h"
-#include "mono/utils/mono-tls-inline.h"
-
-#define SAVE_FP_REGS 0
-
-#define ALWAYS_SAVE_RA 1 /* call-handler & switch currently clobber ra */
-
-#define PROMOTE_R4_TO_R8 1 /* promote single values in registers to doubles */
-#define USE_MUL 0 /* use mul instead of mult/mflo for multiply
- remember to update cpu-mips.md if you change this */
-
-/* Emit a call sequence to 'v', using 'D' as a scratch register if necessary */
-#define mips_call(c,D,v) do { \
- guint32 _target = (guint32)(v); \
- if (1 || ((v) == NULL) || ((_target & 0xfc000000) != (((guint32)(c)) & 0xfc000000))) { \
- mips_load_const (c, D, _target); \
- mips_jalr (c, D, mips_ra); \
- } \
- else { \
- mips_jumpl (c, _target >> 2); \
- } \
- mips_nop (c); \
- } while (0)
-
-enum {
- TLS_MODE_DETECT,
- TLS_MODE_FAILED,
- TLS_MODE_LTHREADS,
- TLS_MODE_NPTL
-};
-
-/* This mutex protects architecture specific caches */
-#define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
-#define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
-static mono_mutex_t mini_arch_mutex;
-
-/* Whenever the host is little-endian */
-static int little_endian;
-/* Index of ms word/register */
-static int ls_word_idx;
-/* Index of ls word/register */
-static int ms_word_idx;
-/* Same for offsets */
-static int ls_word_offset;
-static int ms_word_offset;
-
-/*
- * The code generated for sequence points reads from this location, which is
- * made read-only when single stepping is enabled.
- */
-static gpointer ss_trigger_page;
-
-/* Enabled breakpoints read from this trigger page */
-static gpointer bp_trigger_page;
-
-#undef DEBUG
-#define DEBUG(a) if (cfg->verbose_level > 1) a
-#undef DEBUG
-#define DEBUG(a) a
-#undef DEBUG
-#define DEBUG(a)
-
-#define EMIT_SYSTEM_EXCEPTION_NAME(exc_name) \
- do { \
- code = mips_emit_exc_by_name (code, exc_name); \
- cfg->bb_exit->max_offset += 16; \
- } while (0)
-
-#define MONO_EMIT_NEW_LOAD_R8(cfg,dr,addr) do { \
- MonoInst *inst; \
- MONO_INST_NEW ((cfg), (inst), OP_R8CONST); \
- inst->type = STACK_R8; \
- inst->dreg = (dr); \
- inst->inst_p0 = (void*)(addr); \
- mono_bblock_add_inst (cfg->cbb, inst); \
- } while (0)
-
-#define ins_is_compare(ins) ((ins) && (((ins)->opcode == OP_COMPARE) \
- || ((ins)->opcode == OP_ICOMPARE) \
- || ((ins)->opcode == OP_LCOMPARE)))
-#define ins_is_compare_imm(ins) ((ins) && (((ins)->opcode == OP_COMPARE_IMM) \
- || ((ins)->opcode == OP_ICOMPARE_IMM) \
- || ((ins)->opcode == OP_LCOMPARE_IMM)))
-
-#define INS_REWRITE(ins, op, _s1, _s2) do { \
- int s1 = _s1; \
- int s2 = _s2; \
- ins->opcode = (op); \
- ins->sreg1 = (s1); \
- ins->sreg2 = (s2); \
- } while (0);
-
-#define INS_REWRITE_IMM(ins, op, _s1, _imm) do { \
- int s1 = _s1; \
- ins->opcode = (op); \
- ins->sreg1 = (s1); \
- ins->inst_imm = (_imm); \
- } while (0);
-
-
-typedef struct InstList InstList;
-
-struct InstList {
- InstList *prev;
- InstList *next;
- MonoInst *data;
-};
-
-typedef enum {
- ArgInIReg,
- ArgOnStack,
- ArgInFReg,
- ArgStructByVal,
- ArgStructByAddr
-} ArgStorage;
-
-typedef struct {
- gint32 offset;
- guint16 vtsize; /* in param area */
- guint8 reg;
- ArgStorage storage;
- guint8 size : 4; /* 1, 2, 4, 8, or regs used by ArgStructByVal */
-} ArgInfo;
-
-struct CallInfo {
- int nargs;
- int gr;
- int fr;
- gboolean gr_passed;
- gboolean on_stack;
- gboolean vtype_retaddr;
- int stack_size;
- guint32 stack_usage;
- guint32 struct_ret;
- ArgInfo ret;
- ArgInfo sig_cookie;
- ArgInfo args [1];
-};
-
-void patch_lui_addiu(guint32 *ip, guint32 val);
-static
-guint8 *mono_arch_emit_epilog_sub (MonoCompile *cfg);
-guint8 *mips_emit_cond_branch (MonoCompile *cfg, guint8 *code, int op, MonoInst *ins);
-void mips_adjust_stackframe(MonoCompile *cfg);
-void mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, int this_reg, int this_type, int vt_reg);
-MonoInst *mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
-
-
-/* Not defined in asm/cachectl.h */
-int cacheflush(char *addr, int nbytes, int cache);
-
-void
-mono_arch_flush_icache (guint8 *code, gint size)
-{
- /* Linux/MIPS specific */
- cacheflush ((char*)code, size, BCACHE);
-}
-
-void
-mono_arch_flush_register_windows (void)
-{
-}
-
-gboolean
-mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm)
-{
- return TRUE;
-}
-
-static guint8 *
-mips_emit_exc_by_name(guint8 *code, const char *name)
-{
- gpointer addr;
- MonoClass *exc_class;
-
- exc_class = mono_class_load_from_name (mono_defaults.corlib, "System", name);
-
- mips_load_const (code, mips_a0, m_class_get_type_token (exc_class));
- addr = mono_get_throw_corlib_exception ();
- mips_call (code, mips_t9, addr);
- return code;
-}
-
-guint8 *
-mips_emit_load_const (guint8 *code, int dreg, target_mgreg_t v)
-{
- if (mips_is_imm16 (v))
- mips_addiu (code, dreg, mips_zero, ((guint32)v) & 0xffff);
- else {
-#if SIZEOF_REGISTER == 8
- if (v != (long) v) {
- /* v is not a sign-extended 32-bit value */
- mips_lui (code, dreg, mips_zero, (guint32)((v >> (32+16)) & 0xffff));
- mips_ori (code, dreg, dreg, (guint32)((v >> (32)) & 0xffff));
- mips_dsll (code, dreg, dreg, 16);
- mips_ori (code, dreg, dreg, (guint32)((v >> (16)) & 0xffff));
- mips_dsll (code, dreg, dreg, 16);
- mips_ori (code, dreg, dreg, (guint32)(v & 0xffff));
- return code;
- }
-#endif
- if (((guint32)v) & (1 << 15)) {
- mips_lui (code, dreg, mips_zero, (((guint32)v)>>16)+1);
- }
- else {
- mips_lui (code, dreg, mips_zero, (((guint32)v)>>16));
- }
- if (((guint32)v) & 0xffff)
- mips_addiu (code, dreg, dreg, ((guint32)v) & 0xffff);
- }
- return code;
-}
-
-guint8 *
-mips_emit_cond_branch (MonoCompile *cfg, guint8 *code, int op, MonoInst *ins)
-{
- g_assert (ins);
- if (cfg->arch.long_branch) {
- int br_offset = 5;
-
- /* Invert test and emit branch around jump */
- switch (op) {
- case OP_MIPS_BEQ:
- mips_bne (code, ins->sreg1, ins->sreg2, br_offset);
- mips_nop (code);
- break;
- case OP_MIPS_BNE:
- mips_beq (code, ins->sreg1, ins->sreg2, br_offset);
- mips_nop (code);
- break;
- case OP_MIPS_BGEZ:
- mips_bltz (code, ins->sreg1, br_offset);
- mips_nop (code);
- break;
- case OP_MIPS_BGTZ:
- mips_blez (code, ins->sreg1, br_offset);
- mips_nop (code);
- break;
- case OP_MIPS_BLEZ:
- mips_bgtz (code, ins->sreg1, br_offset);
- mips_nop (code);
- break;
- case OP_MIPS_BLTZ:
- mips_bgez (code, ins->sreg1, br_offset);
- mips_nop (code);
- break;
- default:
- g_assert_not_reached ();
- }
- mono_add_patch_info (cfg, code - cfg->native_code,
- MONO_PATCH_INFO_BB, ins->inst_true_bb);
- mips_lui (code, mips_at, mips_zero, 0);
- mips_addiu (code, mips_at, mips_at, 0);
- mips_jr (code, mips_at);
- mips_nop (code);
- }
- else {
- mono_add_patch_info (cfg, code - cfg->native_code,
- MONO_PATCH_INFO_BB, ins->inst_true_bb);
- switch (op) {
- case OP_MIPS_BEQ:
- mips_beq (code, ins->sreg1, ins->sreg2, 0);
- mips_nop (code);
- break;
- case OP_MIPS_BNE:
- mips_bne (code, ins->sreg1, ins->sreg2, 0);
- mips_nop (code);
- break;
- case OP_MIPS_BGEZ:
- mips_bgez (code, ins->sreg1, 0);
- mips_nop (code);
- break;
- case OP_MIPS_BGTZ:
- mips_bgtz (code, ins->sreg1, 0);
- mips_nop (code);
- break;
- case OP_MIPS_BLEZ:
- mips_blez (code, ins->sreg1, 0);
- mips_nop (code);
- break;
- case OP_MIPS_BLTZ:
- mips_bltz (code, ins->sreg1, 0);
- mips_nop (code);
- break;
- default:
- g_assert_not_reached ();
- }
- }
- return (code);
-}
-
-/* XXX - big-endian dependent? */
-void
-patch_lui_addiu(guint32 *ip, guint32 val)
-{
- guint16 *__lui_addiu = (guint16*)(void *)(ip);
-
-#if 0
- printf ("patch_lui_addiu ip=0x%08x (0x%08x, 0x%08x) to point to 0x%08x\n",
- ip, ((guint32 *)ip)[0], ((guint32 *)ip)[1], val);
- fflush (stdout);
-#endif
- if (((guint32)(val)) & (1 << 15))
- __lui_addiu [MINI_LS_WORD_IDX] = ((((guint32)(val)) >> 16) & 0xffff) + 1;
- else
- __lui_addiu [MINI_LS_WORD_IDX] = (((guint32)(val)) >> 16) & 0xffff;
- __lui_addiu [MINI_LS_WORD_IDX + 2] = ((guint32)(val)) & 0xffff;
- mono_arch_flush_icache ((guint8 *)ip, 8);
-}
-
-guint32 trap_target;
-void
-mips_patch (guint32 *code, guint32 target)
-{
- guint32 ins = *code;
- guint32 op = ins >> 26;
- guint32 diff, offset;
-
- g_assert (trap_target != target);
- //printf ("patching 0x%08x (0x%08x) to point to 0x%08x\n", code, ins, target);
- switch (op) {
- case 0x00: /* jr ra */
- if (ins == 0x3e00008)
- break;
- g_assert_not_reached ();
- break;
- case 0x02: /* j */
- case 0x03: /* jal */
- g_assert (!(target & 0x03));
- g_assert ((target & 0xfc000000) == (((guint32)code) & 0xfc000000));
- ins = (ins & 0xfc000000) | (((target) >> 2) & 0x03ffffff);
- *code = ins;
- mono_arch_flush_icache ((guint8 *)code, 4);
- break;
- case 0x01: /* BLTZ */
- case 0x04: /* BEQ */
- case 0x05: /* BNE */
- case 0x06: /* BLEZ */
- case 0x07: /* BGTZ */
- case 0x11: /* bc1t */
- diff = target - (guint32)(code + 1);
- g_assert (((diff & 0x0003ffff) == diff) || ((diff | 0xfffc0000) == diff));
- g_assert (!(diff & 0x03));
- offset = ((gint32)diff) >> 2;
- if (((int)offset) != ((int)(short)offset))
- g_assert (((int)offset) == ((int)(short)offset));
- ins = (ins & 0xffff0000) | (offset & 0x0000ffff);
- *code = ins;
- mono_arch_flush_icache ((guint8 *)code, 4);
- break;
- case 0x0f: /* LUI / ADDIU pair */
- g_assert ((code[1] >> 26) == 0x9);
- patch_lui_addiu (code, target);
- mono_arch_flush_icache ((guint8 *)code, 8);
- break;
-
- default:
- printf ("unknown op 0x%02x (0x%08x) @ %p\n", op, ins, code);
- g_assert_not_reached ();
- }
-}
-
-static void mono_arch_compute_omit_fp (MonoCompile *cfg);
-
-const char*
-mono_arch_regname (int reg) {
-#if _MIPS_SIM == _ABIO32
- static const char * rnames[] = {
- "zero", "at", "v0", "v1",
- "a0", "a1", "a2", "a3",
- "t0", "t1", "t2", "t3",
- "t4", "t5", "t6", "t7",
- "s0", "s1", "s2", "s3",
- "s4", "s5", "s6", "s7",
- "t8", "t9", "k0", "k1",
- "gp", "sp", "fp", "ra"
- };
-#elif _MIPS_SIM == _ABIN32
- static const char * rnames[] = {
- "zero", "at", "v0", "v1",
- "a0", "a1", "a2", "a3",
- "a4", "a5", "a6", "a7",
- "t0", "t1", "t2", "t3",
- "s0", "s1", "s2", "s3",
- "s4", "s5", "s6", "s7",
- "t8", "t9", "k0", "k1",
- "gp", "sp", "fp", "ra"
- };
-#endif
- if (reg >= 0 && reg < 32)
- return rnames [reg];
- return "unknown";
-}
-
-const char*
-mono_arch_fregname (int reg) {
- static const char * rnames[] = {
- "f0", "f1", "f2", "f3",
- "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11",
- "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19",
- "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27",
- "f28", "f29", "f30", "f31"
- };
- if (reg >= 0 && reg < 32)
- return rnames [reg];
- return "unknown";
-}
-
-/* this function overwrites at */
-static guint8*
-emit_memcpy (guint8 *code, int size, int dreg, int doffset, int sreg, int soffset)
-{
- /* XXX write a loop, not an unrolled loop */
- while (size > 0) {
- mips_lw (code, mips_at, sreg, soffset);
- mips_sw (code, mips_at, dreg, doffset);
- size -= 4;
- soffset += 4;
- doffset += 4;
- }
- return code;
-}
-
-/*
- * mono_arch_get_argument_info:
- * @csig: a method signature
- * @param_count: the number of parameters to consider
- * @arg_info: an array to store the result infos
- *
- * Gathers information on parameters such as size, alignment and
- * padding. arg_info should be large enought to hold param_count + 1 entries.
- *
- * Returns the size of the activation frame.
- */
-int
-mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
-{
- int k, frame_size = 0;
- guint32 size, align, pad;
- int offset = 0;
-
- if (MONO_TYPE_ISSTRUCT (csig->ret)) {
- frame_size += sizeof (target_mgreg_t);
- offset += 4;
- }
-
- arg_info [0].offset = offset;
-
- if (csig->hasthis) {
- frame_size += sizeof (target_mgreg_t);
- offset += 4;
- }
-
- arg_info [0].size = frame_size;
-
- for (k = 0; k < param_count; k++) {
- size = mini_type_stack_size_full (csig->params [k], &align, csig->pinvoke && !csig->marshalling_disabled);
-
- /* ignore alignment for now */
- align = 1;
-
- frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
- arg_info [k].pad = pad;
- frame_size += size;
- arg_info [k + 1].pad = 0;
- arg_info [k + 1].size = size;
- offset += pad;
- arg_info [k + 1].offset = offset;
- offset += size;
- }
-
- align = MONO_ARCH_FRAME_ALIGNMENT;
- frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
- arg_info [k].pad = pad;
-
- return frame_size;
-}
-
-/* The delegate object plus 3 params */
-#define MAX_ARCH_DELEGATE_PARAMS (4 - 1)
-
-static guint8*
-get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, gboolean param_count)
-{
- guint8 *code, *start;
-
- if (has_target) {
- start = code = mono_global_codeman_reserve (16);
-
- /* Replace the this argument with the target */
- mips_lw (code, mips_temp, mips_a0, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
- mips_lw (code, mips_a0, mips_a0, MONO_STRUCT_OFFSET (MonoDelegate, target));
- mips_jr (code, mips_temp);
- mips_nop (code);
-
- g_assert ((code - start) <= 16);
-
- mono_arch_flush_icache (start, 16);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
- } else {
- int size, i;
-
- size = 16 + param_count * 4;
- start = code = mono_global_codeman_reserve (size);
-
- mips_lw (code, mips_temp, mips_a0, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
- /* slide down the arguments */
- for (i = 0; i < param_count; ++i) {
- mips_move (code, mips_a0 + i, mips_a0 + i + 1);
- }
- mips_jr (code, mips_temp);
- mips_nop (code);
-
- g_assert ((code - start) <= size);
-
- mono_arch_flush_icache (start, size);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
- }
-
- if (has_target) {
- *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
- } else {
- char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
- *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
- g_free (name);
- }
-
- return start;
-}
-
-/*
- * mono_arch_get_delegate_invoke_impls:
- *
- * Return a list of MonoAotTrampInfo structures for the delegate invoke impl
- * trampolines.
- */
-GSList*
-mono_arch_get_delegate_invoke_impls (void)
-{
- GSList *res = NULL;
- MonoTrampInfo *info;
- int i;
-
- get_delegate_invoke_impl (&info, TRUE, 0);
- res = g_slist_prepend (res, info);
-
- for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
- get_delegate_invoke_impl (&info, FALSE, i);
- res = g_slist_prepend (res, info);
- }
-
- return res;
-}
-
-gpointer
-mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
-{
- guint8 *code, *start;
-
- /* FIXME: Support more cases */
- if (MONO_TYPE_ISSTRUCT (sig->ret))
- return NULL;
-
- if (has_target) {
- static guint8* cached = NULL;
- mono_mini_arch_lock ();
- if (cached) {
- mono_mini_arch_unlock ();
- return cached;
- }
-
- if (mono_ee_features.use_aot_trampolines) {
- start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
- } else {
- MonoTrampInfo *info;
- start = get_delegate_invoke_impl (&info, TRUE, 0);
- mono_tramp_info_register (info, NULL);
- }
- cached = start;
- mono_mini_arch_unlock ();
- return cached;
- } else {
- static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
- int i;
-
- if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
- return NULL;
- for (i = 0; i < sig->param_count; ++i)
- if (!mono_is_regsize_var (sig->params [i]))
- return NULL;
-
- mono_mini_arch_lock ();
- code = cache [sig->param_count];
- if (code) {
- mono_mini_arch_unlock ();
- return code;
- }
-
- if (mono_ee_features.use_aot_trampolines) {
- char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
- start = mono_aot_get_trampoline (name);
- g_free (name);
- } else {
- MonoTrampInfo *info;
- start = get_delegate_invoke_impl (&info, FALSE, sig->param_count);
- mono_tramp_info_register (info, NULL);
- }
- cache [sig->param_count] = start;
- mono_mini_arch_unlock ();
- return start;
- }
-
- return NULL;
-}
-
-gpointer
-mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg)
-{
- return NULL;
-}
-
-gpointer
-mono_arch_get_this_arg_from_call (host_mgreg_t *regs, guint8 *code)
-{
- g_assert(regs);
- return (gpointer)regs [mips_a0];
-}
-
-/*
- * Initialize the cpu to execute managed code.
- */
-void
-mono_arch_cpu_init (void)
-{
-#if TARGET_BYTE_ORDER == G_LITTLE_ENDIAN
- little_endian = 1;
- ls_word_idx = 0;
- ms_word_idx = 1;
-#else
- ls_word_idx = 1;
- ms_word_idx = 0;
-#endif
-
- ls_word_offset = ls_word_idx * 4;
- ms_word_offset = ms_word_idx * 4;
-}
-
-/*
- * Initialize architecture specific code.
- */
-void
-mono_arch_init (void)
-{
- mono_os_mutex_init_recursive (&mini_arch_mutex);
-
- ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
- bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
- mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
-}
-
-/*
- * Cleanup architecture specific code.
- */
-void
-mono_arch_cleanup (void)
-{
- mono_os_mutex_destroy (&mini_arch_mutex);
-}
-
-gboolean
-mono_arch_have_fast_tls (void)
-{
- return FALSE;
-}
-
-/*
- * This function returns the optimizations supported on this cpu.
- */
-guint32
-mono_arch_cpu_optimizations (guint32 *exclude_mask)
-{
- guint32 opts = 0;
-
- /* no mips-specific optimizations yet */
- *exclude_mask = 0;
- return opts;
-}
-
-GList *
-mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
-{
- GList *vars = NULL;
- int i;
-
- for (i = 0; i < cfg->num_varinfo; i++) {
- MonoInst *ins = cfg->varinfo [i];
- MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
-
- /* unused vars */
- if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
- continue;
-
- if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
- continue;
-
- /* we can only allocate 32 bit values */
- if (mono_is_regsize_var (ins->inst_vtype)) {
- g_assert (MONO_VARINFO (cfg, i)->reg == -1);
- g_assert (i == vmv->idx);
- vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
- }
- }
-
- return vars;
-}
-
-GList *
-mono_arch_get_global_int_regs (MonoCompile *cfg)
-{
- GList *regs = NULL;
-
- regs = g_list_prepend (regs, (gpointer)mips_s0);
- regs = g_list_prepend (regs, (gpointer)mips_s1);
- regs = g_list_prepend (regs, (gpointer)mips_s2);
- regs = g_list_prepend (regs, (gpointer)mips_s3);
- regs = g_list_prepend (regs, (gpointer)mips_s4);
- //regs = g_list_prepend (regs, (gpointer)mips_s5);
- regs = g_list_prepend (regs, (gpointer)mips_s6);
- regs = g_list_prepend (regs, (gpointer)mips_s7);
-
- return regs;
-}
-
-/*
- * mono_arch_regalloc_cost:
- *
- * Return the cost, in number of memory references, of the action of
- * allocating the variable VMV into a register during global register
- * allocation.
- */
-guint32
-mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
-{
- /* FIXME: */
- return 2;
-}
-
-static void
-args_onto_stack (CallInfo *info)
-{
- g_assert (!info->on_stack);
- g_assert (info->stack_size <= MIPS_STACK_PARAM_OFFSET);
- info->on_stack = TRUE;
- info->stack_size = MIPS_STACK_PARAM_OFFSET;
-}
-
-#if _MIPS_SIM == _ABIO32
-/*
- * O32 calling convention version
- */
-
-static void
-add_int32_arg (CallInfo *info, ArgInfo *ainfo) {
- /* First, see if we need to drop onto the stack */
- if (!info->on_stack && info->gr > MIPS_LAST_ARG_REG)
- args_onto_stack (info);
-
- /* Now, place the argument */
- if (info->on_stack) {
- ainfo->storage = ArgOnStack;
- ainfo->reg = mips_sp; /* in the caller */
- ainfo->offset = info->stack_size;
- }
- else {
- ainfo->storage = ArgInIReg;
- ainfo->reg = info->gr;
- info->gr += 1;
- info->gr_passed = TRUE;
- }
- info->stack_size += 4;
-}
-
-static void
-add_int64_arg (CallInfo *info, ArgInfo *ainfo) {
- /* First, see if we need to drop onto the stack */
- if (!info->on_stack && info->gr+1 > MIPS_LAST_ARG_REG)
- args_onto_stack (info);
-
- /* Now, place the argument */
- if (info->on_stack) {
- g_assert (info->stack_size % 4 == 0);
- info->stack_size += (info->stack_size % 8);
-
- ainfo->storage = ArgOnStack;
- ainfo->reg = mips_sp; /* in the caller */
- ainfo->offset = info->stack_size;
- }
- else {
- // info->gr must be a0 or a2
- info->gr += (info->gr - MIPS_FIRST_ARG_REG) % 2;
- g_assert(info->gr <= MIPS_LAST_ARG_REG);
-
- ainfo->storage = ArgInIReg;
- ainfo->reg = info->gr;
- info->gr += 2;
- info->gr_passed = TRUE;
- }
- info->stack_size += 8;
-}
-
-static void
-add_float32_arg (CallInfo *info, ArgInfo *ainfo) {
- /* First, see if we need to drop onto the stack */
- if (!info->on_stack && info->gr > MIPS_LAST_ARG_REG)
- args_onto_stack (info);
-
- /* Now, place the argument */
- if (info->on_stack) {
- ainfo->storage = ArgOnStack;
- ainfo->reg = mips_sp; /* in the caller */
- ainfo->offset = info->stack_size;
- }
- else {
- /* Only use FP regs for args if no int args passed yet */
- if (!info->gr_passed && info->fr <= MIPS_LAST_FPARG_REG) {
- ainfo->storage = ArgInFReg;
- ainfo->reg = info->fr;
- /* Even though it's a single-precision float, it takes up two FP regs */
- info->fr += 2;
- /* FP and GP slots do not overlap */
- info->gr += 1;
- }
- else {
- /* Passing single-precision float arg in a GP register
- * such as: func (0, 1.0, 2, 3);
- * In this case, only one 'gr' register is consumed.
- */
- ainfo->storage = ArgInIReg;
- ainfo->reg = info->gr;
-
- info->gr += 1;
- info->gr_passed = TRUE;
- }
- }
- info->stack_size += 4;
-}
-
-static void
-add_float64_arg (CallInfo *info, ArgInfo *ainfo) {
- /* First, see if we need to drop onto the stack */
- if (!info->on_stack && info->gr+1 > MIPS_LAST_ARG_REG)
- args_onto_stack (info);
-
- /* Now, place the argument */
- if (info->on_stack) {
- g_assert(info->stack_size % 4 == 0);
- info->stack_size += (info->stack_size % 8);
-
- ainfo->storage = ArgOnStack;
- ainfo->reg = mips_sp; /* in the caller */
- ainfo->offset = info->stack_size;
- }
- else {
- /* Only use FP regs for args if no int args passed yet */
- if (!info->gr_passed && info->fr <= MIPS_LAST_FPARG_REG) {
- ainfo->storage = ArgInFReg;
- ainfo->reg = info->fr;
- info->fr += 2;
- /* FP and GP slots do not overlap */
- info->gr += 2;
- }
- else {
- // info->gr must be a0 or a2
- info->gr += (info->gr - MIPS_FIRST_ARG_REG) % 2;
- g_assert(info->gr <= MIPS_LAST_ARG_REG);
-
- ainfo->storage = ArgInIReg;
- ainfo->reg = info->gr;
- info->gr += 2;
- info->gr_passed = TRUE;
- }
- }
- info->stack_size += 8;
-}
-#elif _MIPS_SIM == _ABIN32
-/*
- * N32 calling convention version
- */
-
-static void
-add_int32_arg (CallInfo *info, ArgInfo *ainfo) {
- /* First, see if we need to drop onto the stack */
- if (!info->on_stack && info->gr > MIPS_LAST_ARG_REG)
- args_onto_stack (info);
-
- /* Now, place the argument */
- if (info->on_stack) {
- ainfo->storage = ArgOnStack;
- ainfo->reg = mips_sp; /* in the caller */
- ainfo->offset = info->stack_size;
- info->stack_size += SIZEOF_REGISTER;
- }
- else {
- ainfo->storage = ArgInIReg;
- ainfo->reg = info->gr;
- info->gr += 1;
- info->gr_passed = TRUE;
- }
-}
-
-static void
-add_int64_arg (CallInfo *info, ArgInfo *ainfo) {
- /* First, see if we need to drop onto the stack */
- if (!info->on_stack && info->gr > MIPS_LAST_ARG_REG)
- args_onto_stack (info);
-
- /* Now, place the argument */
- if (info->on_stack) {
- g_assert (info->stack_size % 4 == 0);
- info->stack_size += (info->stack_size % 8);
-
- ainfo->storage = ArgOnStack;
- ainfo->reg = mips_sp; /* in the caller */
- ainfo->offset = info->stack_size;
- info->stack_size += SIZEOF_REGISTER;
- }
- else {
- g_assert (info->gr <= MIPS_LAST_ARG_REG);
-
- ainfo->storage = ArgInIReg;
- ainfo->reg = info->gr;
- info->gr += 1;
- info->gr_passed = TRUE;
- }
-}
-
-static void
-add_float32_arg (CallInfo *info, ArgInfo *ainfo) {
- /* First, see if we need to drop onto the stack */
- if (!info->on_stack) {
- if (info->gr > MIPS_LAST_ARG_REG)
- args_onto_stack (info);
- else if (info->fr > MIPS_LAST_FPARG_REG)
- args_onto_stack (info);
- }
-
- /* Now, place the argument */
- if (info->on_stack) {
- ainfo->storage = ArgOnStack;
- ainfo->reg = mips_sp; /* in the caller */
- ainfo->offset = info->stack_size;
- info->stack_size += FREG_SIZE;
- }
- else {
- ainfo->storage = ArgInFReg;
- ainfo->reg = info->fr;
- info->fr += 1;
- /* FP and GP slots do not overlap */
- info->gr += 1;
- }
-}
-
-static void
-add_float64_arg (CallInfo *info, ArgInfo *ainfo) {
- /* First, see if we need to drop onto the stack */
- if (!info->on_stack) {
- if (info->gr > MIPS_LAST_ARG_REG)
- args_onto_stack (info);
- else if (info->fr > MIPS_LAST_FPARG_REG)
- args_onto_stack (info);
- }
-
- /* Now, place the argument */
- if (info->on_stack) {
- g_assert(info->stack_size % 4 == 0);
- info->stack_size += (info->stack_size % 8);
-
- ainfo->storage = ArgOnStack;
- ainfo->reg = mips_sp; /* in the caller */
- ainfo->offset = info->stack_size;
- info->stack_size += FREG_SIZE;
- }
- else {
- ainfo->storage = ArgInFReg;
- ainfo->reg = info->fr;
- info->fr += 1;
- /* FP and GP slots do not overlap */
- info->gr += 1;
- }
-}
-#endif
-
-static CallInfo*
-get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
-{
- guint i;
- int n = sig->hasthis + sig->param_count;
- int pstart;
- MonoType* simpletype;
- CallInfo *cinfo;
- gboolean is_pinvoke = sig->pinvoke;
-
- if (mp)
- cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + (sizeof (ArgInfo) * n));
- else
- cinfo = g_malloc0 (sizeof (CallInfo) + (sizeof (ArgInfo) * n));
-
- cinfo->fr = MIPS_FIRST_FPARG_REG;
- cinfo->gr = MIPS_FIRST_ARG_REG;
- cinfo->stack_size = 0;
-
- DEBUG(printf("calculate_sizes\n"));
-
- cinfo->vtype_retaddr = MONO_TYPE_ISSTRUCT (sig->ret) ? TRUE : FALSE;
- pstart = 0;
- n = 0;
-#if 0
- /* handle returning a struct */
- if (MONO_TYPE_ISSTRUCT (sig->ret)) {
- cinfo->struct_ret = cinfo->gr;
- add_int32_arg (cinfo, &cinfo->ret);
- }
-
- if (sig->hasthis) {
- add_int32_arg (cinfo, cinfo->args + n);
- n++;
- }
-#else
- /*
- * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
- * the first argument, allowing 'this' to be always passed in the first arg reg.
- * Also do this if the first argument is a reference type, since virtual calls
- * are sometimes made using calli without sig->hasthis set, like in the delegate
- * invoke wrappers.
- */
- if (cinfo->vtype_retaddr && !is_pinvoke && (sig->hasthis || (sig->param_count > 0 && MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
- if (sig->hasthis) {
- add_int32_arg (cinfo, cinfo->args + n);
- n ++;
- } else {
- add_int32_arg (cinfo, cinfo->args + sig->hasthis);
- pstart = 1;
- n ++;
- }
- add_int32_arg (cinfo, &cinfo->ret);
- cinfo->struct_ret = cinfo->ret.reg;
- } else {
- /* this */
- if (sig->hasthis) {
- add_int32_arg (cinfo, cinfo->args + n);
- n ++;
- }
-
- if (cinfo->vtype_retaddr) {
- add_int32_arg (cinfo, &cinfo->ret);
- cinfo->struct_ret = cinfo->ret.reg;
- }
- }
-#endif
-
- DEBUG(printf("params: %d\n", sig->param_count));
- for (i = pstart; i < sig->param_count; ++i) {
- if ((sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
- /* Prevent implicit arguments and sig_cookie from
- being passed in registers */
- args_onto_stack (cinfo);
- /* Emit the signature cookie just before the implicit arguments */
- add_int32_arg (cinfo, &cinfo->sig_cookie);
- }
- DEBUG(printf("param %d: ", i));
- simpletype = mini_get_underlying_type (sig->params [i]);
- switch (simpletype->type) {
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- DEBUG(printf("1 byte\n"));
- cinfo->args [n].size = 1;
- add_int32_arg (cinfo, &cinfo->args[n]);
- n++;
- break;
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- DEBUG(printf("2 bytes\n"));
- cinfo->args [n].size = 2;
- add_int32_arg (cinfo, &cinfo->args[n]);
- n++;
- break;
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- DEBUG(printf("4 bytes\n"));
- cinfo->args [n].size = 4;
- add_int32_arg (cinfo, &cinfo->args[n]);
- n++;
- break;
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_PTR:
- case MONO_TYPE_FNPTR:
- case MONO_TYPE_OBJECT:
- cinfo->args [n].size = sizeof (target_mgreg_t);
- add_int32_arg (cinfo, &cinfo->args[n]);
- n++;
- break;
- case MONO_TYPE_GENERICINST:
- if (!mono_type_generic_inst_is_valuetype (simpletype)) {
- cinfo->args [n].size = sizeof (target_mgreg_t);
- add_int32_arg (cinfo, &cinfo->args[n]);
- n++;
- break;
- }
- /* Fall through */
- case MONO_TYPE_TYPEDBYREF:
- case MONO_TYPE_VALUETYPE: {
- int j;
- int nwords = 0;
- int has_offset = FALSE;
- ArgInfo dummy_arg;
- gint size, alignment;
- MonoClass *klass;
-
- if (simpletype->type == MONO_TYPE_TYPEDBYREF) {
- size = MONO_ABI_SIZEOF (MonoTypedRef);
- alignment = sizeof (target_mgreg_t);
- } else {
- klass = mono_class_from_mono_type_internal (sig->params [i]);
- if (sig->pinvoke && !sig->marshalling_disabled)
- size = mono_class_native_size (klass, NULL);
- else
- size = mono_class_value_size (klass, NULL);
- alignment = mono_class_min_align (klass);
- }
-#if MIPS_PASS_STRUCTS_BY_VALUE
- /* Need to do alignment if struct contains long or double */
- if (alignment > 4) {
- /* Drop onto stack *before* looking at
- stack_size, if required. */
- if (!cinfo->on_stack && cinfo->gr > MIPS_LAST_ARG_REG)
- args_onto_stack (cinfo);
- if (cinfo->stack_size & (alignment - 1)) {
- add_int32_arg (cinfo, &dummy_arg);
- }
- g_assert (!(cinfo->stack_size & (alignment - 1)));
- }
-
-#if 0
- g_printf ("valuetype struct size=%d offset=%d align=%d\n",
- mono_class_native_size (sig->params [i]->data.klass, NULL),
- cinfo->stack_size, alignment);
-#endif
- nwords = (size + sizeof (target_mgreg_t) -1 ) / sizeof (target_mgreg_t);
- g_assert (cinfo->args [n].size == 0);
- g_assert (cinfo->args [n].vtsize == 0);
- for (j = 0; j < nwords; ++j) {
- if (j == 0) {
- add_int32_arg (cinfo, &cinfo->args [n]);
- if (cinfo->on_stack)
- has_offset = TRUE;
- } else {
- add_int32_arg (cinfo, &dummy_arg);
- if (!has_offset && cinfo->on_stack) {
- cinfo->args [n].offset = dummy_arg.offset;
- has_offset = TRUE;
- }
- }
- if (cinfo->on_stack)
- cinfo->args [n].vtsize += 1;
- else
- cinfo->args [n].size += 1;
- }
- //g_printf ("\tstack_size=%d vtsize=%d\n", cinfo->args [n].size, cinfo->args[n].vtsize);
- cinfo->args [n].storage = ArgStructByVal;
-#else
- add_int32_arg (cinfo, &cinfo->args[n]);
- cinfo->args [n].storage = ArgStructByAddr;
-#endif
- n++;
- break;
- }
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- DEBUG(printf("8 bytes\n"));
- cinfo->args [n].size = 8;
- add_int64_arg (cinfo, &cinfo->args[n]);
- n++;
- break;
- case MONO_TYPE_R4:
- DEBUG(printf("R4\n"));
- cinfo->args [n].size = 4;
- add_float32_arg (cinfo, &cinfo->args[n]);
- n++;
- break;
- case MONO_TYPE_R8:
- DEBUG(printf("R8\n"));
- cinfo->args [n].size = 8;
- add_float64_arg (cinfo, &cinfo->args[n]);
- n++;
- break;
- default:
- g_error ("Can't trampoline 0x%x", sig->params [i]->type);
- }
- }
-
- /* Handle the case where there are no implicit arguments */
- if ((sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
- /* Prevent implicit arguments and sig_cookie from
- being passed in registers */
- args_onto_stack (cinfo);
- /* Emit the signature cookie just before the implicit arguments */
- add_int32_arg (cinfo, &cinfo->sig_cookie);
- }
-
- {
- simpletype = mini_get_underlying_type (sig->ret);
- switch (simpletype->type) {
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_PTR:
- case MONO_TYPE_FNPTR:
- case MONO_TYPE_OBJECT:
- cinfo->ret.reg = mips_v0;
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- cinfo->ret.reg = mips_v0;
- break;
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- cinfo->ret.reg = mips_f0;
- cinfo->ret.storage = ArgInFReg;
- break;
- case MONO_TYPE_GENERICINST:
- if (!mono_type_generic_inst_is_valuetype (simpletype)) {
- cinfo->ret.reg = mips_v0;
- break;
- }
- break;
- case MONO_TYPE_VALUETYPE:
- case MONO_TYPE_TYPEDBYREF:
- break;
- case MONO_TYPE_VOID:
- break;
- default:
- g_error ("Can't handle as return value 0x%x", sig->ret->type);
- }
- }
-
- /* align stack size to 16 */
- cinfo->stack_size = (cinfo->stack_size + MIPS_STACK_ALIGNMENT - 1) & ~(MIPS_STACK_ALIGNMENT - 1);
-
- cinfo->stack_usage = cinfo->stack_size;
- return cinfo;
-}
-
-static gboolean
-debug_omit_fp (void)
-{
-#if 0
- return mono_debug_count ();
-#else
- return TRUE;
-#endif
-}
-
-/**
- * mono_arch_compute_omit_fp:
- * Determine whether the frame pointer can be eliminated.
- */
-static void
-mono_arch_compute_omit_fp (MonoCompile *cfg)
-{
- MonoMethodSignature *sig;
- MonoMethodHeader *header;
- int i;
- CallInfo *cinfo;
-
- if (cfg->arch.omit_fp_computed)
- return;
-
- header = cfg->header;
-
- sig = mono_method_signature_internal (cfg->method);
-
- if (!cfg->arch.cinfo)
- cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
- cinfo = cfg->arch.cinfo;
-
- /*
- * FIXME: Remove some of the restrictions.
- */
- cfg->arch.omit_fp = TRUE;
- cfg->arch.omit_fp_computed = TRUE;
-
- if (cfg->disable_omit_fp)
- cfg->arch.omit_fp = FALSE;
- if (!debug_omit_fp ())
- cfg->arch.omit_fp = FALSE;
- if (cfg->method->save_lmf)
- cfg->arch.omit_fp = FALSE;
- if (cfg->flags & MONO_CFG_HAS_ALLOCA)
- cfg->arch.omit_fp = FALSE;
- if (header->num_clauses)
- cfg->arch.omit_fp = FALSE;
- if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG))
- cfg->arch.omit_fp = FALSE;
- /*
- * On MIPS, fp points to the bottom of the frame, so it can be eliminated even if
- * there are stack arguments.
- */
- /*
- if (cinfo->stack_usage)
- cfg->arch.omit_fp = FALSE;
- */
-
- //printf ("D: %s %d\n", cfg->method->name, cfg->arch.omit_fp);
-}
-
-/*
- * Set var information according to the calling convention. mips version.
- * The locals var stuff should most likely be split in another method.
- */
-void
-mono_arch_allocate_vars (MonoCompile *cfg)
-{
- MonoMethodSignature *sig;
- MonoMethodHeader *header;
- MonoInst *inst;
- int i, offset, size, align, curinst;
- int frame_reg = mips_sp;
- guint32 iregs_to_save = 0;
-#if SAVE_FP_REGS
- guint32 fregs_to_restore;
-#endif
- CallInfo *cinfo;
-
- sig = mono_method_signature_internal (cfg->method);
-
- if (!cfg->arch.cinfo)
- cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
- cinfo = cfg->arch.cinfo;
-
- mono_arch_compute_omit_fp (cfg);
-
- /* spill down, we'll fix it in a separate pass */
- // cfg->flags |= MONO_CFG_HAS_SPILLUP;
-
- /* this is bug #60332: remove when #59509 is fixed, so no weird vararg
- * call convs needs to be handled this way.
- */
- if (cfg->flags & MONO_CFG_HAS_VARARGS)
- cfg->param_area = MAX (cfg->param_area, sizeof (target_mgreg_t)*8);
-
- /* gtk-sharp and other broken code will dllimport vararg functions even with
- * non-varargs signatures. Since there is little hope people will get this right
- * we assume they won't.
- */
- if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
- cfg->param_area = MAX (cfg->param_area, sizeof (target_mgreg_t)*8);
-
- /* a0-a3 always present */
- cfg->param_area = MAX (cfg->param_area, MIPS_STACK_PARAM_OFFSET);
-
- header = cfg->header;
-
- if (cfg->arch.omit_fp)
- frame_reg = mips_sp;
- else
- frame_reg = mips_fp;
- cfg->frame_reg = frame_reg;
- if (frame_reg != mips_sp) {
- cfg->used_int_regs |= 1 << frame_reg;
- }
-
- offset = 0;
- curinst = 0;
- if (!MONO_TYPE_ISSTRUCT (sig->ret)) {
- /* FIXME: handle long and FP values */
- switch (mini_get_underlying_type (sig->ret)->type) {
- case MONO_TYPE_VOID:
- break;
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- cfg->ret->opcode = OP_REGVAR;
- cfg->ret->inst_c0 = cfg->ret->dreg = mips_f0;
- break;
- default:
- cfg->ret->opcode = OP_REGVAR;
- cfg->ret->inst_c0 = mips_v0;
- break;
- }
- }
- /* Space for outgoing parameters, including a0-a3 */
- offset += cfg->param_area;
-
- /* Now handle the local variables */
-
- curinst = cfg->locals_start;
- for (i = curinst; i < cfg->num_varinfo; ++i) {
- inst = cfg->varinfo [i];
- if ((inst->flags & MONO_INST_IS_DEAD) || inst->opcode == OP_REGVAR)
- continue;
-
- /* inst->backend.is_pinvoke indicates native sized value types, this is used by the
- * pinvoke wrappers when they call functions returning structure
- */
- if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF)
- size = mono_class_native_size (mono_class_from_mono_type_internal (inst->inst_vtype), (unsigned int *) &align);
- else
- size = mono_type_size (inst->inst_vtype, &align);
-
- offset += align - 1;
- offset &= ~(align - 1);
- inst->inst_offset = offset;
- inst->opcode = OP_REGOFFSET;
- inst->inst_basereg = frame_reg;
- offset += size;
- // g_print ("allocating local %d to %d\n", i, inst->inst_offset);
- }
-
- /* Space for LMF (if needed) */
- if (cfg->method->save_lmf) {
- /* align the offset to 16 bytes */
- offset = (offset + MIPS_STACK_ALIGNMENT - 1) & ~(MIPS_STACK_ALIGNMENT - 1);
- cfg->arch.lmf_offset = offset;
- offset += sizeof (MonoLMF);
- }
-
- if (sig->call_convention == MONO_CALL_VARARG) {
- size = 4;
- align = 4;
-
- /* Allocate a local slot to hold the sig cookie address */
- offset += align - 1;
- offset &= ~(align - 1);
- cfg->sig_cookie = offset;
- offset += size;
- }
-
- offset += SIZEOF_REGISTER - 1;
- offset &= ~(SIZEOF_REGISTER - 1);
-
- /* Space for saved registers */
- cfg->arch.iregs_offset = offset;
- iregs_to_save = (cfg->used_int_regs & MONO_ARCH_CALLEE_SAVED_REGS);
- if (iregs_to_save) {
- for (i = MONO_MAX_IREGS-1; i >= 0; --i) {
- if (iregs_to_save & (1 << i)) {
- offset += SIZEOF_REGISTER;
- }
- }
- }
-
- /* saved float registers */
-#if SAVE_FP_REGS
- fregs_to_restore = (cfg->used_float_regs & MONO_ARCH_CALLEE_SAVED_FREGS);
- if (fregs_to_restore) {
- for (i = MONO_MAX_FREGS-1; i >= 0; --i) {
- if (fregs_to_restore & (1 << i)) {
- offset += sizeof(double);
- }
- }
- }
-#endif
-
-#if _MIPS_SIM == _ABIO32
- /* Now add space for saving the ra */
- offset += TARGET_SIZEOF_VOID_P;
-
- /* change sign? */
- offset = (offset + MIPS_STACK_ALIGNMENT - 1) & ~(MIPS_STACK_ALIGNMENT - 1);
- cfg->stack_offset = offset;
- cfg->arch.local_alloc_offset = cfg->stack_offset;
-#endif
-
- /*
- * Now allocate stack slots for the int arg regs (a0 - a3)
- * On MIPS o32, these are just above the incoming stack pointer
- * Even if the arg has been assigned to a regvar, it gets a stack slot
- */
-
- /* Return struct-by-value results in a hidden first argument */
- if (MONO_TYPE_ISSTRUCT (sig->ret)) {
- cfg->vret_addr->opcode = OP_REGOFFSET;
- cfg->vret_addr->inst_c0 = mips_a0;
- cfg->vret_addr->inst_offset = offset;
- cfg->vret_addr->inst_basereg = frame_reg;
- offset += SIZEOF_REGISTER;
- }
-
- for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
- inst = cfg->args [i];
- if (inst->opcode != OP_REGVAR) {
- MonoType *arg_type;
-
- if (sig->hasthis && (i == 0))
- arg_type = mono_get_object_type ();
- else
- arg_type = sig->params [i - sig->hasthis];
-
- inst->opcode = OP_REGOFFSET;
- size = mono_type_size (arg_type, &align);
-
- if (size < SIZEOF_REGISTER) {
- size = SIZEOF_REGISTER;
- align = SIZEOF_REGISTER;
- }
- inst->inst_basereg = frame_reg;
- offset = (offset + align - 1) & ~(align - 1);
- inst->inst_offset = offset;
- offset += size;
- if (cfg->verbose_level > 1)
- printf ("allocating param %d to fp[%d]\n", i, inst->inst_offset);
- }
- else {
-#if _MIPS_SIM == _ABIO32
- /* o32: Even a0-a3 get stack slots */
- size = SIZEOF_REGISTER;
- align = SIZEOF_REGISTER;
- inst->inst_basereg = frame_reg;
- offset = (offset + align - 1) & ~(align - 1);
- inst->inst_offset = offset;
- offset += size;
- if (cfg->verbose_level > 1)
- printf ("allocating param %d to fp[%d]\n", i, inst->inst_offset);
-#endif
- }
- }
-#if _MIPS_SIM == _ABIN32
- /* Now add space for saving the ra */
- offset += TARGET_SIZEOF_VOID_P;
-
- /* change sign? */
- offset = (offset + MIPS_STACK_ALIGNMENT - 1) & ~(MIPS_STACK_ALIGNMENT - 1);
- cfg->stack_offset = offset;
- cfg->arch.local_alloc_offset = cfg->stack_offset;
-#endif
-}
-
-void
-mono_arch_create_vars (MonoCompile *cfg)
-{
- MonoMethodSignature *sig;
-
- sig = mono_method_signature_internal (cfg->method);
-
- if (MONO_TYPE_ISSTRUCT (sig->ret)) {
- cfg->vret_addr = mono_compile_create_var (cfg, mono_get_int_type (), OP_ARG);
- if (G_UNLIKELY (cfg->verbose_level > 1)) {
- printf ("vret_addr = ");
- mono_print_ins (cfg->vret_addr);
- }
- }
-}
-
-/* Fixme: we need an alignment solution for enter_method and mono_arch_call_opcode,
- * currently alignment in mono_arch_call_opcode is computed without arch_get_argument_info
- */
-
-/*
- * take the arguments and generate the arch-specific
- * instructions to properly call the function in call.
- * This includes pushing, moving arguments to the right register
- * etc.
- * Issue: who does the spilling if needed, and when?
- */
-static void
-emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
-{
- MonoMethodSignature *tmp_sig;
- MonoInst *sig_arg;
-
- if (MONO_IS_TAILCALL_OPCODE (call))
- NOT_IMPLEMENTED;
-
- /* FIXME: Add support for signature tokens to AOT */
- cfg->disable_aot = TRUE;
-
- /*
- * mono_ArgIterator_Setup assumes the signature cookie is
- * passed first and all the arguments which were before it are
- * passed on the stack after the signature. So compensate by
- * passing a different signature.
- */
- tmp_sig = mono_metadata_signature_dup (call->signature);
- tmp_sig->param_count -= call->signature->sentinelpos;
- tmp_sig->sentinelpos = 0;
- memcpy (tmp_sig->params, call->signature->params + call->signature->sentinelpos, tmp_sig->param_count * sizeof (MonoType*));
-
- MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
- sig_arg->dreg = mono_alloc_ireg (cfg);
- sig_arg->inst_p0 = tmp_sig;
- MONO_ADD_INS (cfg->cbb, sig_arg);
-
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, mips_sp, cinfo->sig_cookie.offset, sig_arg->dreg);
-}
-
-void
-mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
-{
- MonoInst *in, *ins;
- MonoMethodSignature *sig;
- int i, n;
- CallInfo *cinfo;
- int is_virtual = 0;
-
- sig = call->signature;
- n = sig->param_count + sig->hasthis;
-
- cinfo = get_call_info (cfg->mempool, sig);
- if (cinfo->struct_ret)
- call->used_iregs |= 1 << cinfo->struct_ret;
-
- for (i = 0; i < n; ++i) {
- ArgInfo *ainfo = cinfo->args + i;
- MonoType *t;
-
- if (i >= sig->hasthis)
- t = sig->params [i - sig->hasthis];
- else
- t = mono_get_int_type ();
- t = mini_get_underlying_type (t);
-
- if ((sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
- /* Emit the signature cookie just before the implicit arguments */
- emit_sig_cookie (cfg, call, cinfo);
- }
-
- if (is_virtual && i == 0) {
- /* the argument will be attached to the call instrucion */
- in = call->args [i];
- call->used_iregs |= 1 << ainfo->reg;
- continue;
- }
- in = call->args [i];
- if (ainfo->storage == ArgInIReg) {
-#if SIZEOF_REGISTER == 4
- if (!m_type_is_byref (t) && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) {
- MONO_INST_NEW (cfg, ins, OP_MOVE);
- ins->dreg = mono_alloc_ireg (cfg);
- ins->sreg1 = MONO_LVREG_LS (in->dreg);
- MONO_ADD_INS (cfg->cbb, ins);
- mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg + ls_word_idx, FALSE);
-
- MONO_INST_NEW (cfg, ins, OP_MOVE);
- ins->dreg = mono_alloc_ireg (cfg);
- ins->sreg1 = MONO_LVREG_MS (in->dreg);
- MONO_ADD_INS (cfg->cbb, ins);
- mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg + ms_word_idx, FALSE);
- } else
-#endif
- if (!m_type_is_byref (t) && (t->type == MONO_TYPE_R4)) {
- int freg;
-
-#if PROMOTE_R4_TO_R8
- /* ??? - convert to single first? */
- MONO_INST_NEW (cfg, ins, OP_MIPS_CVTSD);
- ins->dreg = mono_alloc_freg (cfg);
- ins->sreg1 = in->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
- freg = ins->dreg;
-#else
- freg = in->dreg;
-#endif
- /* trying to load float value into int registers */
- MONO_INST_NEW (cfg, ins, OP_MIPS_MFC1S);
- ins->dreg = mono_alloc_ireg (cfg);
- ins->sreg1 = freg;
- MONO_ADD_INS (cfg->cbb, ins);
- mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
- } else if (!m_type_is_byref (t) && (t->type == MONO_TYPE_R8)) {
- /* trying to load float value into int registers */
- MONO_INST_NEW (cfg, ins, OP_MIPS_MFC1D);
- ins->dreg = mono_alloc_ireg (cfg);
- ins->sreg1 = in->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
- mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
- } else {
- MONO_INST_NEW (cfg, ins, OP_MOVE);
- ins->dreg = mono_alloc_ireg (cfg);
- ins->sreg1 = in->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
- mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
- }
- } else if (ainfo->storage == ArgStructByAddr) {
- MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
- ins->opcode = OP_OUTARG_VT;
- ins->sreg1 = in->dreg;
- ins->klass = in->klass;
- ins->inst_p0 = call;
- ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
- memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
- MONO_ADD_INS (cfg->cbb, ins);
- } else if (ainfo->storage == ArgStructByVal) {
- /* this is further handled in mono_arch_emit_outarg_vt () */
- MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
- ins->opcode = OP_OUTARG_VT;
- ins->sreg1 = in->dreg;
- ins->klass = in->klass;
- ins->inst_p0 = call;
- ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
- memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
- MONO_ADD_INS (cfg->cbb, ins);
- } else if (ainfo->storage == ArgOnStack) {
- if (!m_type_is_byref (t) && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) {
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, mips_sp, ainfo->offset, in->dreg);
- } else if (!m_type_is_byref (t) && ((t->type == MONO_TYPE_R4) || (t->type == MONO_TYPE_R8))) {
- if (t->type == MONO_TYPE_R8)
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, mips_sp, ainfo->offset, in->dreg);
- else
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, mips_sp, ainfo->offset, in->dreg);
- } else {
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, mips_sp, ainfo->offset, in->dreg);
- }
- } else if (ainfo->storage == ArgInFReg) {
- if (t->type == MONO_TYPE_VALUETYPE) {
- /* this is further handled in mono_arch_emit_outarg_vt () */
- MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
- ins->opcode = OP_OUTARG_VT;
- ins->sreg1 = in->dreg;
- ins->klass = in->klass;
- ins->inst_p0 = call;
- ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
- memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
- MONO_ADD_INS (cfg->cbb, ins);
-
- cfg->flags |= MONO_CFG_HAS_FPOUT;
- } else {
- int dreg = mono_alloc_freg (cfg);
-
- if (ainfo->size == 4) {
- MONO_EMIT_NEW_UNALU (cfg, OP_MIPS_CVTSD, dreg, in->dreg);
- } else {
- MONO_INST_NEW (cfg, ins, OP_FMOVE);
- ins->dreg = dreg;
- ins->sreg1 = in->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
- }
-
- mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
- cfg->flags |= MONO_CFG_HAS_FPOUT;
- }
- } else {
- g_assert_not_reached ();
- }
- }
-
- /* Handle the case where there are no implicit arguments */
- if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == sig->sentinelpos))
- emit_sig_cookie (cfg, call, cinfo);
-
- if (cinfo->struct_ret) {
- MonoInst *vtarg;
-
- MONO_INST_NEW (cfg, vtarg, OP_MOVE);
- vtarg->sreg1 = call->vret_var->dreg;
- vtarg->dreg = mono_alloc_preg (cfg);
- MONO_ADD_INS (cfg->cbb, vtarg);
-
- mono_call_inst_add_outarg_reg (cfg, call, vtarg->dreg, cinfo->struct_ret, FALSE);
- }
-#if 0
- /*
- * Reverse the call->out_args list.
- */
- {
- MonoInst *prev = NULL, *list = call->out_args, *next;
- while (list) {
- next = list->next;
- list->next = prev;
- prev = list;
- list = next;
- }
- call->out_args = prev;
- }
-#endif
- call->stack_usage = cinfo->stack_usage;
- cfg->param_area = MAX (cfg->param_area, cinfo->stack_usage);
-#if _MIPS_SIM == _ABIO32
- /* a0-a3 always present */
- cfg->param_area = MAX (cfg->param_area, 4 * SIZEOF_REGISTER);
-#endif
- cfg->param_area = (cfg->param_area + MIPS_STACK_ALIGNMENT - 1) & ~(MIPS_STACK_ALIGNMENT - 1);
- cfg->flags |= MONO_CFG_HAS_CALLS;
- /*
- * should set more info in call, such as the stack space
- * used by the args that needs to be added back to esp
- */
-}
-
-void
-mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
-{
- MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
- ArgInfo *ainfo = ins->inst_p1;
- int ovf_size = ainfo->vtsize;
- int doffset = ainfo->offset;
- int i, soffset, dreg;
-
- if (ainfo->storage == ArgStructByVal) {
-#if 0
- if (cfg->verbose_level > 0) {
- char* nm = mono_method_full_name (cfg->method, TRUE);
- g_print ("Method %s outarg_vt struct doffset=%d ainfo->size=%d ovf_size=%d\n",
- nm, doffset, ainfo->size, ovf_size);
- g_free (nm);
- }
-#endif
-
- soffset = 0;
- for (i = 0; i < ainfo->size; ++i) {
- dreg = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, soffset);
- mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg + i, FALSE);
- soffset += SIZEOF_REGISTER;
- }
- if (ovf_size != 0) {
- mini_emit_memcpy (cfg, mips_sp, doffset, src->dreg, soffset, ovf_size * sizeof (target_mgreg_t), TARGET_SIZEOF_VOID_P);
- }
- } else if (ainfo->storage == ArgInFReg) {
- int tmpr = mono_alloc_freg (cfg);
-
- if (ainfo->size == 4)
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, tmpr, src->dreg, 0);
- else
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, tmpr, src->dreg, 0);
- dreg = mono_alloc_freg (cfg);
- MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, dreg, tmpr);
- mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
- } else {
- MonoInst *vtcopy = mono_compile_create_var (cfg, m_class_get_byval_arg (src->klass), OP_LOCAL);
- MonoInst *load;
- guint32 size;
-
- /* FIXME: alignment? */
- if (call->signature->pinvoke && !call->signature->marshalling_disabled) {
- size = mono_type_native_stack_size (m_class_get_byval_arg (src->klass), NULL);
- vtcopy->backend.is_pinvoke = 1;
- } else {
- size = mini_type_stack_size (m_class_get_byval_arg (src->klass), NULL);
- }
- if (size > 0)
- g_assert (ovf_size > 0);
-
- EMIT_NEW_VARLOADA (cfg, load, vtcopy, vtcopy->inst_vtype);
- mini_emit_memcpy (cfg, load->dreg, 0, src->dreg, 0, size, TARGET_SIZEOF_VOID_P);
-
- if (ainfo->offset)
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, mips_at, ainfo->offset, load->dreg);
- else
- mono_call_inst_add_outarg_reg (cfg, call, load->dreg, ainfo->reg, FALSE);
- }
-}
-
-void
-mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
-{
- MonoType *ret = mini_get_underlying_type (mono_method_signature_internal (method)->ret);
-
- if (!m_type_is_byref (ret)) {
-#if (SIZEOF_REGISTER == 4)
- if (ret->type == MONO_TYPE_I8 || ret->type == MONO_TYPE_U8) {
- MonoInst *ins;
-
- MONO_INST_NEW (cfg, ins, OP_SETLRET);
- ins->sreg1 = MONO_LVREG_LS (val->dreg);
- ins->sreg2 = MONO_LVREG_MS (val->dreg);
- MONO_ADD_INS (cfg->cbb, ins);
- return;
- }
-#endif
- if (ret->type == MONO_TYPE_R8) {
- MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
- return;
- }
- if (ret->type == MONO_TYPE_R4) {
- MONO_EMIT_NEW_UNALU (cfg, OP_MIPS_CVTSD, cfg->ret->dreg, val->dreg);
- return;
- }
- }
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
-}
-
-void
-mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
-{
- MonoInst *ins, *n, *last_ins = NULL;
-
- if (cfg->verbose_level > 2)
- g_print ("Basic block %d peephole pass 1\n", bb->block_num);
-
- ins = bb->code;
- MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
- if (cfg->verbose_level > 2)
- mono_print_ins_index (0, ins);
-
- switch (ins->opcode) {
-#if 0
- case OP_LOAD_MEMBASE:
- case OP_LOADI4_MEMBASE:
- /*
- * OP_IADD reg2, reg1, const1
- * OP_LOAD_MEMBASE const2(reg2), reg3
- * ->
- * OP_LOAD_MEMBASE (const1+const2)(reg1), reg3
- */
- if (last_ins && (last_ins->opcode == OP_IADD_IMM || last_ins->opcode == OP_ADD_IMM) && (last_ins->dreg == ins->inst_basereg) && (last_ins->sreg1 != last_ins->dreg)){
- int const1 = last_ins->inst_imm;
- int const2 = ins->inst_offset;
-
- if (mips_is_imm16 (const1 + const2)) {
- ins->inst_basereg = last_ins->sreg1;
- ins->inst_offset = const1 + const2;
- }
- }
- break;
-#endif
-
- }
- last_ins = ins;
- ins = ins->next;
- }
- bb->last_ins = last_ins;
-}
-
-void
-mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
-{
- MonoInst *ins, *n, *last_ins = NULL;
- ins = bb->code;
-
- MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
- MonoInst *last_ins = ins->prev;
-
- switch (ins->opcode) {
- case OP_MUL_IMM:
- /* remove unnecessary multiplication with 1 */
- if (ins->inst_imm == 1) {
- if (ins->dreg != ins->sreg1) {
- ins->opcode = OP_MOVE;
- } else {
- MONO_DELETE_INS (bb, ins);
- continue;
- }
- } else if (ins->inst_imm > 0) {
- int power2 = mono_is_power_of_two (ins->inst_imm);
- if (power2 > 0) {
- ins->opcode = OP_SHL_IMM;
- ins->inst_imm = power2;
- }
- }
- break;
- case OP_LOAD_MEMBASE:
- case OP_LOADI4_MEMBASE:
- /*
- * OP_STORE_MEMBASE_REG reg, offset(basereg)
- * OP_LOAD_MEMBASE offset(basereg), reg
- */
- if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG
- || last_ins->opcode == OP_STORE_MEMBASE_REG) &&
- ins->inst_basereg == last_ins->inst_destbasereg &&
- ins->inst_offset == last_ins->inst_offset) {
- if (ins->dreg == last_ins->sreg1) {
- MONO_DELETE_INS (bb, ins);
- continue;
- } else {
- //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
- ins->opcode = OP_MOVE;
- ins->sreg1 = last_ins->sreg1;
- }
- break;
- }
- /*
- * Note: reg1 must be different from the basereg in the second load
- * OP_LOAD_MEMBASE offset(basereg), reg1
- * OP_LOAD_MEMBASE offset(basereg), reg2
- * -->
- * OP_LOAD_MEMBASE offset(basereg), reg1
- * OP_MOVE reg1, reg2
- */
- if (last_ins && (last_ins->opcode == OP_LOADI4_MEMBASE
- || last_ins->opcode == OP_LOAD_MEMBASE) &&
- ins->inst_basereg != last_ins->dreg &&
- ins->inst_basereg == last_ins->inst_basereg &&
- ins->inst_offset == last_ins->inst_offset) {
-
- if (ins->dreg == last_ins->dreg) {
- MONO_DELETE_INS (bb, ins);
- continue;
- } else {
- ins->opcode = OP_MOVE;
- ins->sreg1 = last_ins->dreg;
- }
-
- //g_assert_not_reached ();
- break;
- }
-#if 0
- /*
- * OP_STORE_MEMBASE_IMM imm, offset(basereg)
- * OP_LOAD_MEMBASE offset(basereg), reg
- * -->
- * OP_STORE_MEMBASE_IMM imm, offset(basereg)
- * OP_ICONST reg, imm
- */
- if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_IMM
- || last_ins->opcode == OP_STORE_MEMBASE_IMM) &&
- ins->inst_basereg == last_ins->inst_destbasereg &&
- ins->inst_offset == last_ins->inst_offset) {
- //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
- ins->opcode = OP_ICONST;
- ins->inst_c0 = last_ins->inst_imm;
- g_assert_not_reached (); // check this rule
- break;
- }
-#endif
- break;
- case OP_LOADU1_MEMBASE:
- case OP_LOADI1_MEMBASE:
- if (last_ins && (last_ins->opcode == OP_STOREI1_MEMBASE_REG) &&
- ins->inst_basereg == last_ins->inst_destbasereg &&
- ins->inst_offset == last_ins->inst_offset) {
- ins->opcode = (ins->opcode == OP_LOADI1_MEMBASE) ? OP_ICONV_TO_I1 : OP_ICONV_TO_U1;
- ins->sreg1 = last_ins->sreg1;
- }
- break;
- case OP_LOADU2_MEMBASE:
- case OP_LOADI2_MEMBASE:
- if (last_ins && (last_ins->opcode == OP_STOREI2_MEMBASE_REG) &&
- ins->inst_basereg == last_ins->inst_destbasereg &&
- ins->inst_offset == last_ins->inst_offset) {
- ins->opcode = (ins->opcode == OP_LOADI2_MEMBASE) ? OP_ICONV_TO_I2 : OP_ICONV_TO_U2;
- ins->sreg1 = last_ins->sreg1;
- }
- break;
- case OP_ICONV_TO_I4:
- case OP_ICONV_TO_U4:
- case OP_MOVE:
- ins->opcode = OP_MOVE;
- /*
- * OP_MOVE reg, reg
- */
- if (ins->dreg == ins->sreg1) {
- MONO_DELETE_INS (bb, ins);
- continue;
- }
- /*
- * OP_MOVE sreg, dreg
- * OP_MOVE dreg, sreg
- */
- if (last_ins && last_ins->opcode == OP_MOVE &&
- ins->sreg1 == last_ins->dreg &&
- ins->dreg == last_ins->sreg1) {
- MONO_DELETE_INS (bb, ins);
- continue;
- }
- break;
- }
- last_ins = ins;
- ins = ins->next;
- }
- bb->last_ins = last_ins;
-}
-
-void
-mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *ins)
-{
- int tmp1 = -1;
- int tmp2 = -1;
- int tmp3 = -1;
- int tmp4 = -1;
- int tmp5 = -1;
-
- switch (ins->opcode) {
- case OP_LADD:
- tmp1 = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg+1, ins->sreg1+1, ins->sreg2+1);
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp1, ins->dreg+1, ins->sreg1+1);
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg+2, ins->sreg1+2, ins->sreg2+2);
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg+2, ins->dreg+2, tmp1);
- NULLIFY_INS(ins);
- break;
-
- case OP_LADD_IMM:
- tmp1 = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IADD_IMM, ins->dreg+1, ins->sreg1+1, ins_get_l_low (ins));
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp1, ins->dreg+1, ins->sreg1+1);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IADD_IMM, ins->dreg+2, ins->sreg1+2, ins_get_l_high (ins));
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg+2, ins->dreg+2, tmp1);
- NULLIFY_INS(ins);
- break;
-
- case OP_LSUB:
- tmp1 = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+1, ins->sreg1+1, ins->sreg2+1);
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp1, ins->sreg1+1, ins->dreg+1);
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+2, ins->sreg1+2, ins->sreg2+2);
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+2, ins->dreg+2, tmp1);
- NULLIFY_INS(ins);
- break;
-
- case OP_LSUB_IMM:
- tmp1 = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISUB_IMM, ins->dreg+1, ins->sreg1+1, ins_get_l_low (ins));
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp1, ins->sreg1+1, ins->dreg+1);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISUB_IMM, ins->dreg+2, ins->sreg1+2, ins_get_l_high (ins));
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+2, ins->dreg+2, tmp1);
- NULLIFY_INS(ins);
- break;
-
- case OP_LNEG:
- tmp1 = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+1, mips_zero, ins->sreg1+1);
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp1, mips_zero, ins->dreg+1);
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+2, mips_zero, ins->sreg1+2);
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+2, ins->dreg+2, tmp1);
- NULLIFY_INS(ins);
- break;
-
- case OP_LADD_OVF:
- tmp1 = mono_alloc_ireg (cfg);
- tmp2 = mono_alloc_ireg (cfg);
- tmp3 = mono_alloc_ireg (cfg);
- tmp4 = mono_alloc_ireg (cfg);
- tmp5 = mono_alloc_ireg (cfg);
-
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg+1, ins->sreg1+1, ins->sreg2+1);
-
- /* tmp1 holds the carry from the low 32-bit to the high 32-bits */
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp5, ins->dreg+1, ins->sreg1+1);
-
- /* add the high 32-bits, and add in the carry from the low 32-bits */
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg+2, ins->sreg1+2, ins->sreg2+2);
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg+2, tmp5, ins->dreg+2);
-
- /* Overflow happens if
- * neg + neg = pos or
- * pos + pos = neg
- * XOR of the high bits returns 0 if the signs match
- * XOR of that with the high bit of the result return 1 if overflow.
- */
-
- /* tmp1 = 0 if the signs of the two inputs match, 1 otherwise */
- MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tmp1, ins->sreg1+2, ins->sreg2+2);
-
- /* set tmp2 = 0 if bit31 of results matches is different than the operands */
- MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tmp2, ins->dreg+2, ins->sreg2+2);
- MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tmp2, tmp2);
-
- /* OR(tmp1, tmp2) = 0 if both conditions are true */
- MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tmp3, tmp2, tmp1);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, tmp4, tmp3, 31);
-
- /* Now, if (tmp4 == 0) then overflow */
- MONO_EMIT_NEW_COMPARE_EXC (cfg, EQ, tmp4, mips_zero, "OverflowException");
- NULLIFY_INS(ins);
- break;
-
- case OP_LADD_OVF_UN:
- tmp1 = mono_alloc_ireg (cfg);
- tmp2 = mono_alloc_ireg (cfg);
-
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg+1, ins->sreg1+1, ins->sreg2+1);
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp1, ins->dreg+1, ins->sreg1+1);
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg+2, ins->sreg1+2, ins->sreg2+2);
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg+2, tmp1, ins->dreg+2);
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp2, ins->dreg+2, ins->sreg1+2);
- MONO_EMIT_NEW_COMPARE_EXC (cfg, NE_UN, tmp2, mips_zero, "OverflowException");
- NULLIFY_INS(ins);
- break;
-
- case OP_LSUB_OVF:
- tmp1 = mono_alloc_ireg (cfg);
- tmp2 = mono_alloc_ireg (cfg);
- tmp3 = mono_alloc_ireg (cfg);
- tmp4 = mono_alloc_ireg (cfg);
- tmp5 = mono_alloc_ireg (cfg);
-
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+1, ins->sreg1+1, ins->sreg2+1);
-
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp5, ins->sreg1+1, ins->dreg+1);
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+2, ins->sreg1+2, ins->sreg2+2);
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+2, ins->dreg+2, tmp5);
-
- /* Overflow happens if
- * neg - pos = pos or
- * pos - neg = neg
- * XOR of bit31 of the lhs & rhs = 1 if the signs are different
- *
- * tmp1 = (lhs ^ rhs)
- * tmp2 = (lhs ^ result)
- * if ((tmp1 < 0) & (tmp2 < 0)) then overflow
- */
-
- MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tmp1, ins->sreg1+2, ins->sreg2+2);
- MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tmp2, ins->sreg1+2, ins->dreg+2);
- MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tmp3, tmp2, tmp1);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, tmp4, tmp3, 31);
-
- /* Now, if (tmp4 == 1) then overflow */
- MONO_EMIT_NEW_COMPARE_EXC (cfg, NE_UN, tmp4, mips_zero, "OverflowException");
- NULLIFY_INS(ins);
- break;
-
- case OP_LSUB_OVF_UN:
- tmp1 = mono_alloc_ireg (cfg);
- tmp2 = mono_alloc_ireg (cfg);
-
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+1, ins->sreg1+1, ins->sreg2+1);
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp1, ins->sreg1+1, ins->dreg+1);
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+2, ins->sreg1+2, ins->sreg2+2);
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg+2, ins->dreg+2, tmp1);
-
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp2, ins->sreg1+2, ins->dreg+2);
- MONO_EMIT_NEW_COMPARE_EXC (cfg, NE_UN, tmp2, mips_zero, "OverflowException");
- NULLIFY_INS(ins);
- break;
- case OP_LCONV_TO_OVF_I4_2:
- tmp1 = mono_alloc_ireg (cfg);
-
- /* Overflows if reg2 != sign extension of reg1 */
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, tmp1, ins->sreg1, 31);
- MONO_EMIT_NEW_COMPARE_EXC (cfg, NE_UN, ins->sreg2, tmp1, "OverflowException");
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
- NULLIFY_INS(ins);
- break;
- default:
- break;
- }
-}
-
-void
-mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
-{
- int tmp1 = -1;
- int tmp2 = -1;
- int tmp3 = -1;
- int tmp4 = -1;
- int tmp5 = -1;
-
- switch (ins->opcode) {
- case OP_IADD_OVF:
- tmp1 = mono_alloc_ireg (cfg);
- tmp2 = mono_alloc_ireg (cfg);
- tmp3 = mono_alloc_ireg (cfg);
- tmp4 = mono_alloc_ireg (cfg);
- tmp5 = mono_alloc_ireg (cfg);
-
- /* add the operands */
-
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg, ins->sreg1, ins->sreg2);
-
- /* Overflow happens if
- * neg + neg = pos or
- * pos + pos = neg
- *
- * (bit31s of operands match) AND (bit31 of operand != bit31 of result)
- * XOR of the high bit returns 0 if the signs match
- * XOR of that with the high bit of the result return 1 if overflow.
- */
-
- /* tmp1 = 0 if the signs of the two inputs match, 1 otherwise */
- MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tmp1, ins->sreg1, ins->sreg2);
-
- /* set tmp2 = 0 if bit31 of results matches is different than the operands */
- MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tmp2, ins->dreg, ins->sreg2);
- MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tmp3, tmp2);
-
- /* OR(tmp1, tmp2) = 0 if both conditions are true */
- MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tmp4, tmp3, tmp1);
-
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, tmp5, tmp4, 31);
-
- /* Now, if (tmp5 == 0) then overflow */
- MONO_EMIT_NEW_COMPARE_EXC (cfg, EQ, tmp5, mips_zero, "OverflowException");
- /* Make decompse and method-to-ir.c happy, last insn writes dreg */
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->dreg);
- NULLIFY_INS(ins);
- break;
-
- case OP_IADD_OVF_UN:
- tmp1 = mono_alloc_ireg (cfg);
-
- MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg, ins->sreg1, ins->sreg2);
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp1, ins->dreg, ins->sreg1);
- MONO_EMIT_NEW_COMPARE_EXC (cfg, NE_UN, tmp1, mips_zero, "OverflowException");
- /* Make decompse and method-to-ir.c happy, last insn writes dreg */
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->dreg);
- NULLIFY_INS(ins);
- break;
-
- case OP_ISUB_OVF:
- tmp1 = mono_alloc_ireg (cfg);
- tmp2 = mono_alloc_ireg (cfg);
- tmp3 = mono_alloc_ireg (cfg);
- tmp4 = mono_alloc_ireg (cfg);
- tmp5 = mono_alloc_ireg (cfg);
-
- /* add the operands */
-
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg, ins->sreg1, ins->sreg2);
-
- /* Overflow happens if
- * neg - pos = pos or
- * pos - neg = neg
- * XOR of bit31 of the lhs & rhs = 1 if the signs are different
- *
- * tmp1 = (lhs ^ rhs)
- * tmp2 = (lhs ^ result)
- * if ((tmp1 < 0) & (tmp2 < 0)) then overflow
- */
-
- /* tmp3 = 1 if the signs of the two inputs differ */
- MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tmp1, ins->sreg1, ins->sreg2);
- MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tmp2, ins->sreg1, ins->dreg);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_MIPS_SLTI, tmp3, tmp1, 0);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_MIPS_SLTI, tmp4, tmp2, 0);
- MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tmp5, tmp4, tmp3);
-
- MONO_EMIT_NEW_COMPARE_EXC (cfg, NE_UN, tmp5, mips_zero, "OverflowException");
- /* Make decompse and method-to-ir.c happy, last insn writes dreg */
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->dreg);
- NULLIFY_INS(ins);
- break;
-
- case OP_ISUB_OVF_UN:
- tmp1 = mono_alloc_ireg (cfg);
-
- MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, ins->dreg, ins->sreg1, ins->sreg2);
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, tmp1, ins->sreg1, ins->dreg);
- MONO_EMIT_NEW_COMPARE_EXC (cfg, NE_UN, tmp1, mips_zero, "OverflowException");
- /* Make decompse and method-to-ir.c happy, last insn writes dreg */
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->dreg);
- NULLIFY_INS(ins);
- break;
- }
-}
-
-static int
-map_to_reg_reg_op (int op)
-{
- switch (op) {
- case OP_ADD_IMM:
- return OP_IADD;
- case OP_SUB_IMM:
- return OP_ISUB;
- case OP_AND_IMM:
- return OP_IAND;
- case OP_COMPARE_IMM:
- return OP_COMPARE;
- case OP_ICOMPARE_IMM:
- return OP_ICOMPARE;
- case OP_LCOMPARE_IMM:
- return OP_LCOMPARE;
- case OP_ADDCC_IMM:
- return OP_IADDCC;
- case OP_ADC_IMM:
- return OP_IADC;
- case OP_SUBCC_IMM:
- return OP_ISUBCC;
- case OP_SBB_IMM:
- return OP_ISBB;
- case OP_OR_IMM:
- return OP_IOR;
- case OP_XOR_IMM:
- return OP_IXOR;
- case OP_MUL_IMM:
- return OP_IMUL;
- case OP_LOAD_MEMBASE:
- return OP_LOAD_MEMINDEX;
- case OP_LOADI4_MEMBASE:
- return OP_LOADI4_MEMINDEX;
- case OP_LOADU4_MEMBASE:
- return OP_LOADU4_MEMINDEX;
- case OP_LOADU1_MEMBASE:
- return OP_LOADU1_MEMINDEX;
- case OP_LOADI2_MEMBASE:
- return OP_LOADI2_MEMINDEX;
- case OP_LOADU2_MEMBASE:
- return OP_LOADU2_MEMINDEX;
- case OP_LOADI1_MEMBASE:
- return OP_LOADI1_MEMINDEX;
- case OP_LOADR4_MEMBASE:
- return OP_LOADR4_MEMINDEX;
- case OP_LOADR8_MEMBASE:
- return OP_LOADR8_MEMINDEX;
- case OP_STOREI1_MEMBASE_REG:
- return OP_STOREI1_MEMINDEX;
- case OP_STOREI2_MEMBASE_REG:
- return OP_STOREI2_MEMINDEX;
- case OP_STOREI4_MEMBASE_REG:
- return OP_STOREI4_MEMINDEX;
- case OP_STORE_MEMBASE_REG:
- return OP_STORE_MEMINDEX;
- case OP_STORER4_MEMBASE_REG:
- return OP_STORER4_MEMINDEX;
- case OP_STORER8_MEMBASE_REG:
- return OP_STORER8_MEMINDEX;
- case OP_STORE_MEMBASE_IMM:
- return OP_STORE_MEMBASE_REG;
- case OP_STOREI1_MEMBASE_IMM:
- return OP_STOREI1_MEMBASE_REG;
- case OP_STOREI2_MEMBASE_IMM:
- return OP_STOREI2_MEMBASE_REG;
- case OP_STOREI4_MEMBASE_IMM:
- return OP_STOREI4_MEMBASE_REG;
- case OP_STOREI8_MEMBASE_IMM:
- return OP_STOREI8_MEMBASE_REG;
- }
- if (mono_op_imm_to_op (op) == -1)
- g_error ("mono_op_imm_to_op failed for %s\n", mono_inst_name (op));
- return mono_op_imm_to_op (op);
-}
-
-static int
-map_to_mips_op (int op)
-{
- switch (op) {
- case OP_FBEQ:
- return OP_MIPS_FBEQ;
- case OP_FBGE:
- return OP_MIPS_FBGE;
- case OP_FBGT:
- return OP_MIPS_FBGT;
- case OP_FBLE:
- return OP_MIPS_FBLE;
- case OP_FBLT:
- return OP_MIPS_FBLT;
- case OP_FBNE_UN:
- return OP_MIPS_FBNE;
- case OP_FBGE_UN:
- return OP_MIPS_FBGE_UN;
- case OP_FBGT_UN:
- return OP_MIPS_FBGT_UN;
- case OP_FBLE_UN:
- return OP_MIPS_FBLE_UN;
- case OP_FBLT_UN:
- return OP_MIPS_FBLT_UN;
-
- case OP_FCEQ:
- case OP_FCGT:
- case OP_FCGT_UN:
- case OP_FCLT:
- case OP_FCLT_UN:
- default:
- g_warning ("unknown opcode %s in %s()\n", mono_inst_name (op), __FUNCTION__);
- g_assert_not_reached ();
- }
-}
-
-#define NEW_INS(cfg,after,dest,op) do { \
- MONO_INST_NEW((cfg), (dest), (op)); \
- mono_bblock_insert_after_ins (bb, (after), (dest)); \
- } while (0)
-
-#define INS(pos,op,_dreg,_sreg1,_sreg2) do { \
- MonoInst *temp; \
- MONO_INST_NEW(cfg, temp, (op)); \
- mono_bblock_insert_after_ins (bb, (pos), temp); \
- temp->dreg = (_dreg); \
- temp->sreg1 = (_sreg1); \
- temp->sreg2 = (_sreg2); \
- pos = temp; \
- } while (0)
-
-#define INS_IMM(pos,op,_dreg,_sreg1,_imm) do { \
- MonoInst *temp; \
- MONO_INST_NEW(cfg, temp, (op)); \
- mono_bblock_insert_after_ins (bb, (pos), temp); \
- temp->dreg = (_dreg); \
- temp->sreg1 = (_sreg1); \
- temp->inst_c0 = (_imm); \
- pos = temp; \
- } while (0)
-
-/*
- * Remove from the instruction list the instructions that can't be
- * represented with very simple instructions with no register
- * requirements.
- */
-void
-mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
-{
- MonoInst *ins, *next, *temp, *last_ins = NULL;
- int imm;
-
-#if 1
- if (cfg->verbose_level > 2) {
- int idx = 0;
-
- g_print ("BASIC BLOCK %d (before lowering)\n", bb->block_num);
- MONO_BB_FOR_EACH_INS (bb, ins) {
- mono_print_ins_index (idx++, ins);
- }
-
- }
-#endif
-
- MONO_BB_FOR_EACH_INS (bb, ins) {
-loop_start:
- switch (ins->opcode) {
- case OP_COMPARE:
- case OP_ICOMPARE:
- case OP_LCOMPARE:
- next = ins->next;
- /* Branch opts can eliminate the branch */
- if (!next || (!(MONO_IS_COND_BRANCH_OP (next) || MONO_IS_COND_EXC (next) || MONO_IS_SETCC (next)))) {
- NULLIFY_INS(ins);
- break;
- }
- break;
-
- case OP_COMPARE_IMM:
- case OP_ICOMPARE_IMM:
- case OP_LCOMPARE_IMM:
- next = ins->next;
- /* Branch opts can eliminate the branch */
- if (!next || (!(MONO_IS_COND_BRANCH_OP (next) || MONO_IS_COND_EXC (next) || MONO_IS_SETCC (next)))) {
- NULLIFY_INS(ins);
- break;
- }
- if (ins->inst_imm) {
- NEW_INS (cfg, last_ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
- temp->dreg = mono_alloc_ireg (cfg);
- ins->sreg2 = temp->dreg;
- last_ins = temp;
- }
- else {
- ins->sreg2 = mips_zero;
- }
- if (ins->opcode == OP_COMPARE_IMM)
- ins->opcode = OP_COMPARE;
- else if (ins->opcode == OP_ICOMPARE_IMM)
- ins->opcode = OP_ICOMPARE;
- else if (ins->opcode == OP_LCOMPARE_IMM)
- ins->opcode = OP_LCOMPARE;
- goto loop_start;
-
- case OP_IDIV_UN_IMM:
- case OP_IDIV_IMM:
- case OP_IREM_IMM:
- case OP_IREM_UN_IMM:
- NEW_INS (cfg, last_ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
- temp->dreg = mono_alloc_ireg (cfg);
- ins->sreg2 = temp->dreg;
- if (ins->opcode == OP_IDIV_IMM)
- ins->opcode = OP_IDIV;
- else if (ins->opcode == OP_IREM_IMM)
- ins->opcode = OP_IREM;
- else if (ins->opcode == OP_IDIV_UN_IMM)
- ins->opcode = OP_IDIV_UN;
- else if (ins->opcode == OP_IREM_UN_IMM)
- ins->opcode = OP_IREM_UN;
- last_ins = temp;
- /* handle rem separately */
- goto loop_start;
-
-#if 0
- case OP_AND_IMM:
- case OP_OR_IMM:
- case OP_XOR_IMM:
- if ((ins->inst_imm & 0xffff0000) && (ins->inst_imm & 0xffff)) {
- NEW_INS (cfg, last_ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
- temp->dreg = mono_alloc_ireg (cfg);
- ins->sreg2 = temp->dreg;
- ins->opcode = map_to_reg_reg_op (ins->opcode);
- }
- break;
-#endif
- case OP_AND_IMM:
- case OP_IAND_IMM:
- case OP_OR_IMM:
- case OP_IOR_IMM:
- case OP_XOR_IMM:
- case OP_IXOR_IMM:
- /* unsigned 16 bit immediate */
- if (ins->inst_imm & 0xffff0000) {
- NEW_INS (cfg, last_ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
- temp->dreg = mono_alloc_ireg (cfg);
- ins->sreg2 = temp->dreg;
- ins->opcode = map_to_reg_reg_op (ins->opcode);
- }
- break;
-
- case OP_IADD_IMM:
- case OP_ADD_IMM:
- case OP_ADDCC_IMM:
- /* signed 16 bit immediate */
- if (!mips_is_imm16 (ins->inst_imm)) {
- NEW_INS (cfg, last_ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
- temp->dreg = mono_alloc_ireg (cfg);
- ins->sreg2 = temp->dreg;
- ins->opcode = map_to_reg_reg_op (ins->opcode);
- }
- break;
-
- case OP_SUB_IMM:
- case OP_ISUB_IMM:
- if (!mips_is_imm16 (-ins->inst_imm)) {
- NEW_INS (cfg, last_ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
- temp->dreg = mono_alloc_ireg (cfg);
- ins->sreg2 = temp->dreg;
- ins->opcode = map_to_reg_reg_op (ins->opcode);
- }
- break;
-
- case OP_MUL_IMM:
- case OP_IMUL_IMM:
- if (ins->inst_imm == 1) {
- ins->opcode = OP_MOVE;
- break;
- }
- if (ins->inst_imm == 0) {
- ins->opcode = OP_ICONST;
- ins->inst_c0 = 0;
- break;
- }
- imm = (ins->inst_imm > 0) ? mono_is_power_of_two (ins->inst_imm) : -1;
- if (imm > 0) {
- ins->opcode = OP_SHL_IMM;
- ins->inst_imm = imm;
- break;
- }
- NEW_INS (cfg, last_ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
- temp->dreg = mono_alloc_ireg (cfg);
- ins->sreg2 = temp->dreg;
- ins->opcode = map_to_reg_reg_op (ins->opcode);
- break;
-
- case OP_LOCALLOC_IMM:
- NEW_INS (cfg, last_ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
- temp->dreg = mono_alloc_ireg (cfg);
- ins->sreg1 = temp->dreg;
- ins->opcode = OP_LOCALLOC;
- break;
-
- case OP_LOADR4_MEMBASE:
- case OP_STORER4_MEMBASE_REG:
- /* we can do two things: load the immed in a register
- * and use an indexed load, or see if the immed can be
- * represented as an ad_imm + a load with a smaller offset
- * that fits. We just do the first for now, optimize later.
- */
- if (mips_is_imm16 (ins->inst_offset))
- break;
- NEW_INS (cfg, last_ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_offset;
- temp->dreg = mono_alloc_ireg (cfg);
- ins->sreg2 = temp->dreg;
- ins->opcode = map_to_reg_reg_op (ins->opcode);
- break;
-
- case OP_STORE_MEMBASE_IMM:
- case OP_STOREI1_MEMBASE_IMM:
- case OP_STOREI2_MEMBASE_IMM:
- case OP_STOREI4_MEMBASE_IMM:
- case OP_STOREI8_MEMBASE_IMM:
- if (!ins->inst_imm) {
- ins->sreg1 = mips_zero;
- ins->opcode = map_to_reg_reg_op (ins->opcode);
- }
- else {
- NEW_INS (cfg, last_ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
- temp->dreg = mono_alloc_ireg (cfg);
- ins->sreg1 = temp->dreg;
- ins->opcode = map_to_reg_reg_op (ins->opcode);
- last_ins = temp;
- goto loop_start; /* make it handle the possibly big ins->inst_offset */
- }
- break;
-
- case OP_FCOMPARE:
- next = ins->next;
- /* Branch opts can eliminate the branch */
- if (!next || (!(MONO_IS_COND_BRANCH_OP (next) || MONO_IS_COND_EXC (next) || MONO_IS_SETCC (next)))) {
- NULLIFY_INS(ins);
- break;
- }
- g_assert(next);
-
- /*
- * remap compare/branch and compare/set
- * to MIPS specific opcodes.
- */
- next->opcode = map_to_mips_op (next->opcode);
- next->sreg1 = ins->sreg1;
- next->sreg2 = ins->sreg2;
- NULLIFY_INS(ins);
- break;
-
-#if 0
- case OP_R8CONST:
- case OP_R4CONST:
- NEW_INS (cfg, last_ins, temp, OP_ICONST);
- temp->inst_c0 = (guint32)ins->inst_p0;
- temp->dreg = mono_alloc_ireg (cfg);
- ins->inst_basereg = temp->dreg;
- ins->inst_offset = 0;
- ins->opcode = ins->opcode == OP_R4CONST? OP_LOADR4_MEMBASE: OP_LOADR8_MEMBASE;
- last_ins = temp;
- /* make it handle the possibly big ins->inst_offset
- * later optimize to use lis + load_membase
- */
- goto loop_start;
-#endif
- case OP_IBEQ:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_BEQ, last_ins->sreg1, last_ins->sreg2);
- NULLIFY_INS(last_ins);
- break;
-
- case OP_IBNE_UN:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_BNE, last_ins->sreg1, last_ins->sreg2);
- NULLIFY_INS(last_ins);
- break;
-
- case OP_IBGE:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(last_ins, OP_MIPS_SLT, last_ins->sreg1, last_ins->sreg2);
- last_ins->dreg = mono_alloc_ireg (cfg);
- INS_REWRITE(ins, OP_MIPS_BEQ, last_ins->dreg, mips_zero);
- break;
-
- case OP_IBGE_UN:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(last_ins, OP_MIPS_SLTU, last_ins->sreg1, last_ins->sreg2);
- last_ins->dreg = mono_alloc_ireg (cfg);
- INS_REWRITE(ins, OP_MIPS_BEQ, last_ins->dreg, mips_zero);
- break;
-
- case OP_IBLT:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(last_ins, OP_MIPS_SLT, last_ins->sreg1, last_ins->sreg2);
- last_ins->dreg = mono_alloc_ireg (cfg);
- INS_REWRITE(ins, OP_MIPS_BNE, last_ins->dreg, mips_zero);
- break;
-
- case OP_IBLT_UN:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(last_ins, OP_MIPS_SLTU, last_ins->sreg1, last_ins->sreg2);
- last_ins->dreg = mono_alloc_ireg (cfg);
- INS_REWRITE(ins, OP_MIPS_BNE, last_ins->dreg, mips_zero);
- break;
-
- case OP_IBLE:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(last_ins, OP_MIPS_SLT, last_ins->sreg2, last_ins->sreg1);
- last_ins->dreg = mono_alloc_ireg (cfg);
- INS_REWRITE(ins, OP_MIPS_BEQ, last_ins->dreg, mips_zero);
- break;
-
- case OP_IBLE_UN:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(last_ins, OP_MIPS_SLTU, last_ins->sreg2, last_ins->sreg1);
- last_ins->dreg = mono_alloc_ireg (cfg);
- INS_REWRITE(ins, OP_MIPS_BEQ, last_ins->dreg, mips_zero);
- break;
-
- case OP_IBGT:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(last_ins, OP_MIPS_SLT, last_ins->sreg2, last_ins->sreg1);
- last_ins->dreg = mono_alloc_ireg (cfg);
- INS_REWRITE(ins, OP_MIPS_BNE, last_ins->dreg, mips_zero);
- break;
-
- case OP_IBGT_UN:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(last_ins, OP_MIPS_SLTU, last_ins->sreg2, last_ins->sreg1);
- last_ins->dreg = mono_alloc_ireg (cfg);
- INS_REWRITE(ins, OP_MIPS_BNE, last_ins->dreg, mips_zero);
- break;
-
- case OP_CEQ:
- case OP_ICEQ:
- g_assert (ins_is_compare(last_ins));
- last_ins->opcode = OP_IXOR;
- last_ins->dreg = mono_alloc_ireg(cfg);
- INS_REWRITE_IMM(ins, OP_MIPS_SLTIU, last_ins->dreg, 1);
- break;
-
- case OP_CLT:
- case OP_ICLT:
- INS_REWRITE(ins, OP_MIPS_SLT, last_ins->sreg1, last_ins->sreg2);
- NULLIFY_INS(last_ins);
- break;
-
-
- case OP_CLT_UN:
- case OP_ICLT_UN:
- INS_REWRITE(ins, OP_MIPS_SLTU, last_ins->sreg1, last_ins->sreg2);
- NULLIFY_INS(last_ins);
- break;
-
- case OP_CGT:
- case OP_ICGT:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_SLT, last_ins->sreg2, last_ins->sreg1);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_CGT_UN:
- case OP_ICGT_UN:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_SLTU, last_ins->sreg2, last_ins->sreg1);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_COND_EXC_EQ:
- case OP_COND_EXC_IEQ:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_COND_EXC_EQ, last_ins->sreg1, last_ins->sreg2);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_COND_EXC_GE:
- case OP_COND_EXC_IGE:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_COND_EXC_GE, last_ins->sreg1, last_ins->sreg2);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_COND_EXC_GT:
- case OP_COND_EXC_IGT:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_COND_EXC_GT, last_ins->sreg1, last_ins->sreg2);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_COND_EXC_LE:
- case OP_COND_EXC_ILE:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_COND_EXC_LE, last_ins->sreg1, last_ins->sreg2);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_COND_EXC_LT:
- case OP_COND_EXC_ILT:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_COND_EXC_LT, last_ins->sreg1, last_ins->sreg2);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_COND_EXC_NE_UN:
- case OP_COND_EXC_INE_UN:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_COND_EXC_NE_UN, last_ins->sreg1, last_ins->sreg2);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_COND_EXC_GE_UN:
- case OP_COND_EXC_IGE_UN:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_COND_EXC_GE_UN, last_ins->sreg1, last_ins->sreg2);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_COND_EXC_GT_UN:
- case OP_COND_EXC_IGT_UN:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_COND_EXC_GT_UN, last_ins->sreg1, last_ins->sreg2);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_COND_EXC_LE_UN:
- case OP_COND_EXC_ILE_UN:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_COND_EXC_LE_UN, last_ins->sreg1, last_ins->sreg2);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_COND_EXC_LT_UN:
- case OP_COND_EXC_ILT_UN:
- g_assert (ins_is_compare(last_ins));
- INS_REWRITE(ins, OP_MIPS_COND_EXC_LT_UN, last_ins->sreg1, last_ins->sreg2);
- MONO_DELETE_INS(bb, last_ins);
- break;
-
- case OP_COND_EXC_OV:
- case OP_COND_EXC_IOV: {
- int tmp1, tmp2, tmp3, tmp4, tmp5;
- MonoInst *pos = last_ins;
-
- /* Overflow happens if
- * neg + neg = pos or
- * pos + pos = neg
- *
- * (bit31s of operands match) AND (bit31 of operand
- * != bit31 of result)
- * XOR of the high bit returns 0 if the signs match
- * XOR of that with the high bit of the result return 1
- * if overflow.
- */
- g_assert (last_ins->opcode == OP_IADC);
-
- tmp1 = mono_alloc_ireg (cfg);
- tmp2 = mono_alloc_ireg (cfg);
- tmp3 = mono_alloc_ireg (cfg);
- tmp4 = mono_alloc_ireg (cfg);
- tmp5 = mono_alloc_ireg (cfg);
-
- /* tmp1 = 0 if the signs of the two inputs match, else 1 */
- INS (pos, OP_IXOR, tmp1, last_ins->sreg1, last_ins->sreg2);
-
- /* set tmp2 = 0 if bit31 of results matches is different than the operands */
- INS (pos, OP_IXOR, tmp2, last_ins->dreg, last_ins->sreg2);
- INS (pos, OP_INOT, tmp3, tmp2, -1);
-
- /* OR(tmp1, tmp2) = 0 if both conditions are true */
- INS (pos, OP_IOR, tmp4, tmp3, tmp1);
- INS_IMM (pos, OP_SHR_IMM, tmp5, tmp4, 31);
-
- /* Now, if (tmp5 == 0) then overflow */
- INS_REWRITE(ins, OP_MIPS_COND_EXC_EQ, tmp5, mips_zero);
- ins->dreg = -1;
- break;
- }
-
- case OP_COND_EXC_NO:
- case OP_COND_EXC_INO:
- g_assert_not_reached ();
- break;
-
- case OP_COND_EXC_C:
- case OP_COND_EXC_IC:
- g_assert_not_reached ();
- break;
-
- case OP_COND_EXC_NC:
- case OP_COND_EXC_INC:
- g_assert_not_reached ();
- break;
-
- }
- last_ins = ins;
- }
- bb->last_ins = last_ins;
- bb->max_vreg = cfg->next_vreg;
-
-#if 1
- if (cfg->verbose_level > 2) {
- int idx = 0;
-
- g_print ("BASIC BLOCK %d (after lowering)\n", bb->block_num);
- MONO_BB_FOR_EACH_INS (bb, ins) {
- mono_print_ins_index (idx++, ins);
- }
-
- }
-#endif
-
-}
-
-static guchar*
-emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
-{
- /* sreg is a float, dreg is an integer reg. mips_at is used as scratch */
-#if 1
- mips_truncwd (code, mips_ftemp, sreg);
-#else
- mips_cvtwd (code, mips_ftemp, sreg);
-#endif
- mips_mfc1 (code, dreg, mips_ftemp);
- if (!is_signed) {
- if (size == 1)
- mips_andi (code, dreg, dreg, 0xff);
- else if (size == 2) {
- mips_sll (code, dreg, dreg, 16);
- mips_srl (code, dreg, dreg, 16);
- }
- } else {
- if (size == 1) {
- mips_sll (code, dreg, dreg, 24);
- mips_sra (code, dreg, dreg, 24);
- }
- else if (size == 2) {
- mips_sll (code, dreg, dreg, 16);
- mips_sra (code, dreg, dreg, 16);
- }
- }
- return code;
-}
-
-/*
- * emit_load_volatile_arguments:
- *
- * Load volatile arguments from the stack to the original input registers.
- * Required before a tailcall.
- */
-static guint8 *
-emit_load_volatile_arguments(MonoCompile *cfg, guint8 *code)
-{
- MonoMethod *method = cfg->method;
- MonoMethodSignature *sig;
- MonoInst *inst;
- CallInfo *cinfo;
- int i;
-
- sig = mono_method_signature_internal (method);
-
- if (!cfg->arch.cinfo)
- cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
- cinfo = cfg->arch.cinfo;
-
- if (cinfo->struct_ret) {
- ArgInfo *ainfo = &cinfo->ret;
- inst = cfg->vret_addr;
- mips_lw (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
- }
-
- for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
- ArgInfo *ainfo = cinfo->args + i;
- inst = cfg->args [i];
- if (inst->opcode == OP_REGVAR) {
- if (ainfo->storage == ArgInIReg)
- MIPS_MOVE (code, ainfo->reg, inst->dreg);
- else if (ainfo->storage == ArgInFReg)
- g_assert_not_reached();
- else if (ainfo->storage == ArgOnStack) {
- /* do nothing */
- } else
- g_assert_not_reached ();
- } else {
- if (ainfo->storage == ArgInIReg) {
- g_assert (mips_is_imm16 (inst->inst_offset));
- switch (ainfo->size) {
- case 1:
- mips_lb (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
- break;
- case 2:
- mips_lh (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
- break;
- case 0: /* XXX */
- case 4:
- mips_lw (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
- break;
- case 8:
- mips_lw (code, ainfo->reg, inst->inst_basereg, inst->inst_offset + ls_word_offset);
- mips_lw (code, ainfo->reg + 1, inst->inst_basereg, inst->inst_offset + ms_word_offset);
- break;
- default:
- g_assert_not_reached ();
- break;
- }
- } else if (ainfo->storage == ArgOnStack) {
- /* do nothing */
- } else if (ainfo->storage == ArgInFReg) {
- g_assert (mips_is_imm16 (inst->inst_offset));
- if (ainfo->size == 8) {
-#if _MIPS_SIM == _ABIO32
- mips_lwc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset + ls_word_offset);
- mips_lwc1 (code, ainfo->reg+1, inst->inst_basereg, inst->inst_offset + ms_word_offset);
-#elif _MIPS_SIM == _ABIN32
- mips_ldc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
-#endif
- }
- else if (ainfo->size == 4)
- mips_lwc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
- else
- g_assert_not_reached ();
- } else if (ainfo->storage == ArgStructByVal) {
- int i;
- int doffset = inst->inst_offset;
-
- g_assert (mips_is_imm16 (inst->inst_offset));
- g_assert (mips_is_imm16 (inst->inst_offset + ainfo->size * sizeof (target_mgreg_t)));
- for (i = 0; i < ainfo->size; ++i) {
- mips_lw (code, ainfo->reg + i, inst->inst_basereg, doffset);
- doffset += SIZEOF_REGISTER;
- }
- } else if (ainfo->storage == ArgStructByAddr) {
- g_assert (mips_is_imm16 (inst->inst_offset));
- mips_lw (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
- } else
- g_assert_not_reached ();
- }
- }
-
- return code;
-}
-
-static guint8*
-emit_reserve_param_area (MonoCompile *cfg, guint8 *code)
-{
- int size = cfg->param_area;
-
- size += MONO_ARCH_FRAME_ALIGNMENT - 1;
- size &= -MONO_ARCH_FRAME_ALIGNMENT;
-
- if (!size)
- return code;
-#if 0
- ppc_lwz (code, ppc_r0, 0, ppc_sp);
- if (ppc_is_imm16 (-size)) {
- ppc_stwu (code, ppc_r0, -size, ppc_sp);
- } else {
- ppc_load (code, ppc_r12, -size);
- ppc_stwux (code, ppc_r0, ppc_sp, ppc_r12);
- }
-#endif
- return code;
-}
-
-static guint8*
-emit_unreserve_param_area (MonoCompile *cfg, guint8 *code)
-{
- int size = cfg->param_area;
-
- size += MONO_ARCH_FRAME_ALIGNMENT - 1;
- size &= -MONO_ARCH_FRAME_ALIGNMENT;
-
- if (!size)
- return code;
-#if 0
- ppc_lwz (code, ppc_r0, 0, ppc_sp);
- if (ppc_is_imm16 (size)) {
- ppc_stwu (code, ppc_r0, size, ppc_sp);
- } else {
- ppc_load (code, ppc_r12, size);
- ppc_stwux (code, ppc_r0, ppc_sp, ppc_r12);
- }
-#endif
- return code;
-}
-
-void
-mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
-{
- MonoInst *ins;
- MonoCallInst *call;
- guint8 *code = cfg->native_code + cfg->code_len;
- MonoInst *last_ins = NULL;
- int max_len, cpos;
- int ins_cnt = 0;
-
- /* we don't align basic blocks of loops on mips */
-
- if (cfg->verbose_level > 2)
- g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
-
- cpos = bb->max_offset;
-
- MONO_BB_FOR_EACH_INS (bb, ins) {
- const guint offset = code - cfg->native_code;
- set_code_cursor (cfg, code);
- max_len = ins_get_size (ins->opcode);
- code = realloc_code (cfg, max_len);
-
- mono_debug_record_line_number (cfg, ins, offset);
- if (cfg->verbose_level > 2) {
- g_print (" @ 0x%x\t", offset);
- mono_print_ins_index (ins_cnt++, ins);
- }
- /* Check for virtual regs that snuck by */
- g_assert ((ins->dreg >= -1) && (ins->dreg < 32));
-
- switch (ins->opcode) {
- case OP_RELAXED_NOP:
- case OP_NOP:
- case OP_DUMMY_USE:
- case OP_DUMMY_ICONST:
- case OP_DUMMY_I8CONST:
- case OP_DUMMY_R8CONST:
- case OP_DUMMY_R4CONST:
- case OP_NOT_REACHED:
- case OP_NOT_NULL:
- break;
- case OP_IL_SEQ_POINT:
- mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
- break;
- case OP_SEQ_POINT: {
- if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
- guint32 addr = (guint32)ss_trigger_page;
-
- mips_load_const (code, mips_t9, addr);
- mips_lw (code, mips_t9, mips_t9, 0);
- }
-
- mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
-
- /*
- * A placeholder for a possible breakpoint inserted by
- * mono_arch_set_breakpoint ().
- */
- /* mips_load_const () + mips_lw */
- mips_nop (code);
- mips_nop (code);
- mips_nop (code);
- break;
- }
- case OP_BIGMUL:
- mips_mult (code, ins->sreg1, ins->sreg2);
- mips_mflo (code, ins->dreg);
- mips_mfhi (code, ins->dreg+1);
- break;
- case OP_BIGMUL_UN:
- mips_multu (code, ins->sreg1, ins->sreg2);
- mips_mflo (code, ins->dreg);
- mips_mfhi (code, ins->dreg+1);
- break;
- case OP_MEMORY_BARRIER:
- mips_sync (code, 0);
- break;
- case OP_STOREI1_MEMBASE_IMM:
- mips_load_const (code, mips_temp, ins->inst_imm);
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_sb (code, mips_temp, ins->inst_destbasereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_sb (code, mips_temp, mips_at, ins->inst_destbasereg);
- }
- break;
- case OP_STOREI2_MEMBASE_IMM:
- mips_load_const (code, mips_temp, ins->inst_imm);
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_sh (code, mips_temp, ins->inst_destbasereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_sh (code, mips_temp, mips_at, ins->inst_destbasereg);
- }
- break;
- case OP_STOREI8_MEMBASE_IMM:
- mips_load_const (code, mips_temp, ins->inst_imm);
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_sd (code, mips_temp, ins->inst_destbasereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_sd (code, mips_temp, mips_at, ins->inst_destbasereg);
- }
- break;
- case OP_STORE_MEMBASE_IMM:
- case OP_STOREI4_MEMBASE_IMM:
- mips_load_const (code, mips_temp, ins->inst_imm);
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_sw (code, mips_temp, ins->inst_destbasereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_sw (code, mips_temp, mips_at, ins->inst_destbasereg);
- }
- break;
- case OP_STOREI1_MEMBASE_REG:
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_sb (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_destbasereg);
- mips_sb (code, ins->sreg1, mips_at, 0);
- }
- break;
- case OP_STOREI2_MEMBASE_REG:
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_sh (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_destbasereg);
- mips_sh (code, ins->sreg1, mips_at, 0);
- }
- break;
- case OP_STORE_MEMBASE_REG:
- case OP_STOREI4_MEMBASE_REG:
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_sw (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_destbasereg);
- mips_sw (code, ins->sreg1, mips_at, 0);
- }
- break;
- case OP_STOREI8_MEMBASE_REG:
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_sd (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_destbasereg);
- mips_sd (code, ins->sreg1, mips_at, 0);
- }
- break;
- case OP_LOADU4_MEM:
- g_assert_not_reached ();
- //x86_mov_reg_imm (code, ins->dreg, ins->inst_p0);
- //x86_mov_reg_membase (code, ins->dreg, ins->dreg, 0, 4);
- break;
- case OP_LOADI8_MEMBASE:
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_ld (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_basereg);
- mips_ld (code, ins->dreg, mips_at, 0);
- }
- break;
- case OP_LOAD_MEMBASE:
- case OP_LOADI4_MEMBASE:
- case OP_LOADU4_MEMBASE:
- g_assert (ins->dreg != -1);
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_lw (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_basereg);
- mips_lw (code, ins->dreg, mips_at, 0);
- }
- break;
- case OP_LOADI1_MEMBASE:
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_lb (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_basereg);
- mips_lb (code, ins->dreg, mips_at, 0);
- }
- break;
- case OP_LOADU1_MEMBASE:
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_lbu (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_basereg);
- mips_lbu (code, ins->dreg, mips_at, 0);
- }
- break;
- case OP_LOADI2_MEMBASE:
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_lh (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_basereg);
- mips_lh (code, ins->dreg, mips_at, 0);
- }
- break;
- case OP_LOADU2_MEMBASE:
- if (mips_is_imm16 (ins->inst_offset)) {
- mips_lhu (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_basereg);
- mips_lhu (code, ins->dreg, mips_at, 0);
- }
- break;
- case OP_ICONV_TO_I1:
- mips_sll (code, mips_at, ins->sreg1, 24);
- mips_sra (code, ins->dreg, mips_at, 24);
- break;
- case OP_ICONV_TO_I2:
- mips_sll (code, mips_at, ins->sreg1, 16);
- mips_sra (code, ins->dreg, mips_at, 16);
- break;
- case OP_ICONV_TO_U1:
- mips_andi (code, ins->dreg, ins->sreg1, 0xff);
- break;
- case OP_ICONV_TO_U2:
- mips_sll (code, mips_at, ins->sreg1, 16);
- mips_srl (code, ins->dreg, mips_at, 16);
- break;
- case OP_MIPS_SLT:
- mips_slt (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_MIPS_SLTI:
- g_assert (mips_is_imm16 (ins->inst_imm));
- mips_slti (code, ins->dreg, ins->sreg1, ins->inst_imm);
- break;
- case OP_MIPS_SLTU:
- mips_sltu (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_MIPS_SLTIU:
- g_assert (mips_is_imm16 (ins->inst_imm));
- mips_sltiu (code, ins->dreg, ins->sreg1, ins->inst_imm);
- break;
- case OP_BREAK:
- /*
- * gdb does not like encountering the hw breakpoint ins in the debugged code.
- * So instead of emitting a trap, we emit a call a C function and place a
- * breakpoint there.
- */
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, GUINT_TO_POINTER (MONO_JIT_ICALL_mono_break));
- mips_load (code, mips_t9, 0x1f1f1f1f);
- mips_jalr (code, mips_t9, mips_ra);
- mips_nop (code);
- break;
- case OP_IADD:
- mips_addu (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_LADD:
- mips_daddu (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
-
- case OP_ADD_IMM:
- case OP_IADD_IMM:
- g_assert (mips_is_imm16 (ins->inst_imm));
- mips_addiu (code, ins->dreg, ins->sreg1, ins->inst_imm);
- break;
- case OP_LADD_IMM:
- g_assert (mips_is_imm16 (ins->inst_imm));
- mips_daddiu (code, ins->dreg, ins->sreg1, ins->inst_imm);
- break;
-
- case OP_ISUB:
- mips_subu (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_LSUB:
- mips_dsubu (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
-
- case OP_ISUB_IMM:
- case OP_SUB_IMM:
- // we add the negated value
- g_assert (mips_is_imm16 (-ins->inst_imm));
- mips_addiu (code, ins->dreg, ins->sreg1, -ins->inst_imm);
- break;
-
- case OP_LSUB_IMM:
- // we add the negated value
- g_assert (mips_is_imm16 (-ins->inst_imm));
- mips_daddiu (code, ins->dreg, ins->sreg1, -ins->inst_imm);
- break;
-
- case OP_IAND:
- case OP_LAND:
- mips_and (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
-
- case OP_AND_IMM:
- case OP_IAND_IMM:
- case OP_LAND_IMM:
- g_assert (!(ins->inst_imm & 0xffff0000));
- mips_andi (code, ins->dreg, ins->sreg1, ins->inst_imm);
- break;
-
- case OP_IDIV:
- case OP_IREM: {
- guint32 *divisor_is_m1;
- guint32 *dividend_is_minvalue;
- guint32 *divisor_is_zero;
-
- mips_load_const (code, mips_at, -1);
- divisor_is_m1 = (guint32 *)(void *)code;
- mips_bne (code, ins->sreg2, mips_at, 0);
- mips_lui (code, mips_at, mips_zero, 0x8000);
- dividend_is_minvalue = (guint32 *)(void *)code;
- mips_bne (code, ins->sreg1, mips_at, 0);
- mips_nop (code);
-
- /* Divide Int32.MinValue by -1 -- throw exception */
- EMIT_SYSTEM_EXCEPTION_NAME("OverflowException");
-
- mips_patch (divisor_is_m1, (guint32)code);
- mips_patch (dividend_is_minvalue, (guint32)code);
-
- /* Put divide in branch delay slot (NOT YET) */
- divisor_is_zero = (guint32 *)(void *)code;
- mips_bne (code, ins->sreg2, mips_zero, 0);
- mips_nop (code);
-
- /* Divide by zero -- throw exception */
- EMIT_SYSTEM_EXCEPTION_NAME("DivideByZeroException");
-
- mips_patch (divisor_is_zero, (guint32)code);
- mips_div (code, ins->sreg1, ins->sreg2);
- if (ins->opcode == OP_IDIV)
- mips_mflo (code, ins->dreg);
- else
- mips_mfhi (code, ins->dreg);
- break;
- }
- case OP_IDIV_UN:
- case OP_IREM_UN: {
- guint32 *divisor_is_zero = (guint32 *)(void *)code;
-
- /* Put divide in branch delay slot (NOT YET) */
- mips_bne (code, ins->sreg2, mips_zero, 0);
- mips_nop (code);
-
- /* Divide by zero -- throw exception */
- EMIT_SYSTEM_EXCEPTION_NAME("DivideByZeroException");
-
- mips_patch (divisor_is_zero, (guint32)code);
- mips_divu (code, ins->sreg1, ins->sreg2);
- if (ins->opcode == OP_IDIV_UN)
- mips_mflo (code, ins->dreg);
- else
- mips_mfhi (code, ins->dreg);
- break;
- }
- case OP_DIV_IMM:
- g_assert_not_reached ();
-#if 0
- ppc_load (code, ppc_r12, ins->inst_imm);
- ppc_divwod (code, ins->dreg, ins->sreg1, ppc_r12);
- ppc_mfspr (code, ppc_r0, ppc_xer);
- ppc_andisd (code, ppc_r0, ppc_r0, (1<<14));
- /* FIXME: use OverflowException for 0x80000000/-1 */
- EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_FALSE, PPC_BR_EQ, "DivideByZeroException");
-#endif
- g_assert_not_reached();
- break;
- case OP_REM_IMM:
- g_assert_not_reached ();
- case OP_IOR:
- mips_or (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_OR_IMM:
- case OP_IOR_IMM:
- g_assert (!(ins->inst_imm & 0xffff0000));
- mips_ori (code, ins->dreg, ins->sreg1, ins->inst_imm);
- break;
- case OP_IXOR:
- mips_xor (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_XOR_IMM:
- case OP_IXOR_IMM:
- /* unsigned 16-bit immediate */
- g_assert (!(ins->inst_imm & 0xffff0000));
- mips_xori (code, ins->dreg, ins->sreg1, ins->inst_imm);
- break;
- case OP_ISHL:
- mips_sllv (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_SHL_IMM:
- case OP_ISHL_IMM:
- mips_sll (code, ins->dreg, ins->sreg1, ins->inst_imm & 0x1f);
- break;
- case OP_ISHR:
- mips_srav (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_LSHR:
- mips_dsrav (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_SHR_IMM:
- case OP_ISHR_IMM:
- mips_sra (code, ins->dreg, ins->sreg1, ins->inst_imm & 0x1f);
- break;
- case OP_LSHR_IMM:
- mips_dsra (code, ins->dreg, ins->sreg1, ins->inst_imm & 0x3f);
- break;
- case OP_SHR_UN_IMM:
- case OP_ISHR_UN_IMM:
- mips_srl (code, ins->dreg, ins->sreg1, ins->inst_imm & 0x1f);
- break;
- case OP_LSHR_UN_IMM:
- mips_dsrl (code, ins->dreg, ins->sreg1, ins->inst_imm & 0x3f);
- break;
- case OP_ISHR_UN:
- mips_srlv (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_LSHR_UN:
- mips_dsrlv (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_INOT:
- case OP_LNOT:
- mips_nor (code, ins->dreg, mips_zero, ins->sreg1);
- break;
- case OP_INEG:
- mips_subu (code, ins->dreg, mips_zero, ins->sreg1);
- break;
- case OP_LNEG:
- mips_dsubu (code, ins->dreg, mips_zero, ins->sreg1);
- break;
- case OP_IMUL:
-#if USE_MUL
- mips_mul (code, ins->dreg, ins->sreg1, ins->sreg2);
-#else
- mips_mult (code, ins->sreg1, ins->sreg2);
- mips_mflo (code, ins->dreg);
- mips_nop (code);
- mips_nop (code);
-#endif
- break;
-#if SIZEOF_REGISTER == 8
- case OP_LMUL:
- mips_dmult (code, ins->sreg1, ins->sreg2);
- mips_mflo (code, ins->dreg);
- break;
-#endif
- case OP_IMUL_OVF: {
- guint32 *patch;
- mips_mult (code, ins->sreg1, ins->sreg2);
- mips_mflo (code, ins->dreg);
- mips_mfhi (code, mips_at);
- mips_nop (code);
- mips_nop (code);
- mips_sra (code, mips_temp, ins->dreg, 31);
- patch = (guint32 *)(void *)code;
- mips_beq (code, mips_temp, mips_at, 0);
- mips_nop (code);
- EMIT_SYSTEM_EXCEPTION_NAME("OverflowException");
- mips_patch (patch, (guint32)code);
- break;
- }
- case OP_IMUL_OVF_UN: {
- guint32 *patch;
- mips_mult (code, ins->sreg1, ins->sreg2);
- mips_mflo (code, ins->dreg);
- mips_mfhi (code, mips_at);
- mips_nop (code);
- mips_nop (code);
- patch = (guint32 *)(void *)code;
- mips_beq (code, mips_at, mips_zero, 0);
- mips_nop (code);
- EMIT_SYSTEM_EXCEPTION_NAME("OverflowException");
- mips_patch (patch, (guint32)code);
- break;
- }
- case OP_ICONST:
- mips_load_const (code, ins->dreg, ins->inst_c0);
- break;
-#if SIZEOF_REGISTER == 8
- case OP_I8CONST:
- mips_load_const (code, ins->dreg, ins->inst_c0);
- break;
-#endif
- case OP_AOTCONST:
- mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
- mips_load (code, ins->dreg, 0);
- break;
-
- case OP_MIPS_MTC1S:
- mips_mtc1 (code, ins->dreg, ins->sreg1);
- break;
- case OP_MIPS_MTC1S_2:
- mips_mtc1 (code, ins->dreg, ins->sreg1);
- mips_mtc1 (code, ins->dreg+1, ins->sreg2);
- break;
- case OP_MIPS_MFC1S:
- mips_mfc1 (code, ins->dreg, ins->sreg1);
- break;
- case OP_MIPS_MTC1D:
- mips_dmtc1 (code, ins->dreg, ins->sreg1);
- break;
- case OP_MIPS_MFC1D:
-#if 0
- mips_dmfc1 (code, ins->dreg, ins->sreg1);
-#else
- mips_mfc1 (code, ins->dreg, ins->sreg1 + ls_word_idx);
- mips_mfc1 (code, ins->dreg+1, ins->sreg1 + ms_word_idx);
-#endif
- break;
-
- case OP_ICONV_TO_I4:
- case OP_ICONV_TO_U4:
- case OP_MOVE:
- if (ins->dreg != ins->sreg1)
- MIPS_MOVE (code, ins->dreg, ins->sreg1);
- break;
-#if SIZEOF_REGISTER == 8
- case OP_ZEXT_I4:
- mips_dsll (code, ins->dreg, ins->sreg1, 32);
- mips_dsrl (code, ins->dreg, ins->dreg, 32);
- break;
- case OP_SEXT_I4:
- mips_dsll (code, ins->dreg, ins->sreg1, 32);
- mips_dsra (code, ins->dreg, ins->dreg, 32);
- break;
-#endif
- case OP_SETLRET: {
- int lsreg = mips_v0 + ls_word_idx;
- int msreg = mips_v0 + ms_word_idx;
-
- /* Get sreg1 into lsreg, sreg2 into msreg */
-
- if (ins->sreg1 == msreg) {
- if (ins->sreg1 != mips_at)
- MIPS_MOVE (code, mips_at, ins->sreg1);
- if (ins->sreg2 != msreg)
- MIPS_MOVE (code, msreg, ins->sreg2);
- MIPS_MOVE (code, lsreg, mips_at);
- }
- else {
- if (ins->sreg2 != msreg)
- MIPS_MOVE (code, msreg, ins->sreg2);
- if (ins->sreg1 != lsreg)
- MIPS_MOVE (code, lsreg, ins->sreg1);
- }
- break;
- }
- case OP_FMOVE:
- if (ins->dreg != ins->sreg1) {
- mips_fmovd (code, ins->dreg, ins->sreg1);
- }
- break;
- case OP_MOVE_F_TO_I4:
- mips_cvtsd (code, mips_ftemp, ins->sreg1);
- mips_mfc1 (code, ins->dreg, mips_ftemp);
- break;
- case OP_MOVE_I4_TO_F:
- mips_mtc1 (code, ins->dreg, ins->sreg1);
- mips_cvtds (code, ins->dreg, ins->dreg);
- break;
- case OP_MIPS_CVTSD:
- /* Convert from double to float and leave it there */
- mips_cvtsd (code, ins->dreg, ins->sreg1);
- break;
- case OP_FCONV_TO_R4:
-#if 0
- mips_cvtsd (code, ins->dreg, ins->sreg1);
-#else
- /* Just a move, no precision change */
- if (ins->dreg != ins->sreg1) {
- mips_fmovd (code, ins->dreg, ins->sreg1);
- }
-#endif
- break;
- case OP_CHECK_THIS:
- /* ensure ins->sreg1 is not NULL */
- mips_lw (code, mips_zero, ins->sreg1, 0);
- break;
- case OP_ARGLIST: {
- g_assert (mips_is_imm16 (cfg->sig_cookie));
- mips_lw (code, mips_at, cfg->frame_reg, cfg->sig_cookie);
- mips_sw (code, mips_at, ins->sreg1, 0);
- break;
- }
- case OP_FCALL:
- case OP_LCALL:
- case OP_VCALL:
- case OP_VCALL2:
- case OP_VOIDCALL:
- case OP_CALL:
- case OP_FCALL_REG:
- case OP_LCALL_REG:
- case OP_VCALL_REG:
- case OP_VCALL2_REG:
- case OP_VOIDCALL_REG:
- case OP_CALL_REG:
- case OP_FCALL_MEMBASE:
- case OP_LCALL_MEMBASE:
- case OP_VCALL_MEMBASE:
- case OP_VCALL2_MEMBASE:
- case OP_VOIDCALL_MEMBASE:
- case OP_CALL_MEMBASE:
- call = (MonoCallInst*)ins;
- switch (ins->opcode) {
- case OP_FCALL:
- case OP_LCALL:
- case OP_VCALL:
- case OP_VCALL2:
- case OP_VOIDCALL:
- case OP_CALL:
- mono_call_add_patch_info (cfg, call, offset);
- if (ins->flags & MONO_INST_HAS_METHOD) {
- mips_load (code, mips_t9, call->method);
- }
- else {
- mips_load (code, mips_t9, call->fptr);
- }
- mips_jalr (code, mips_t9, mips_ra);
- mips_nop (code);
- break;
- case OP_FCALL_REG:
- case OP_LCALL_REG:
- case OP_VCALL_REG:
- case OP_VCALL2_REG:
- case OP_VOIDCALL_REG:
- case OP_CALL_REG:
- MIPS_MOVE (code, mips_t9, ins->sreg1);
- mips_jalr (code, mips_t9, mips_ra);
- mips_nop (code);
- break;
- case OP_FCALL_MEMBASE:
- case OP_LCALL_MEMBASE:
- case OP_VCALL_MEMBASE:
- case OP_VCALL2_MEMBASE:
- case OP_VOIDCALL_MEMBASE:
- case OP_CALL_MEMBASE:
- mips_lw (code, mips_t9, ins->sreg1, ins->inst_offset);
- mips_jalr (code, mips_t9, mips_ra);
- mips_nop (code);
- break;
- }
-#if PROMOTE_R4_TO_R8
- /* returned an FP R4 (single), promote to R8 (double) in place */
- switch (ins->opcode) {
- case OP_FCALL:
- case OP_FCALL_REG:
- case OP_FCALL_MEMBASE:
- if (call->signature->ret->type == MONO_TYPE_R4)
- mips_cvtds (code, mips_f0, mips_f0);
- break;
- default:
- break;
- }
-#endif
- break;
- case OP_LOCALLOC: {
- int area_offset = cfg->param_area;
-
- /* Round up ins->sreg1, mips_at ends up holding size */
- mips_addiu (code, mips_at, ins->sreg1, 31);
- mips_addiu (code, mips_temp, mips_zero, ~31);
- mips_and (code, mips_at, mips_at, mips_temp);
-
- mips_subu (code, mips_sp, mips_sp, mips_at);
- g_assert (mips_is_imm16 (area_offset));
- mips_addiu (code, ins->dreg, mips_sp, area_offset);
-
- if (ins->flags & MONO_INST_INIT) {
- guint32 *buf;
-
- buf = (guint32*)(void*)code;
- mips_beq (code, mips_at, mips_zero, 0);
- mips_nop (code);
-
- mips_move (code, mips_temp, ins->dreg);
- mips_sb (code, mips_zero, mips_temp, 0);
- mips_addiu (code, mips_at, mips_at, -1);
- mips_bne (code, mips_at, mips_zero, -3);
- mips_addiu (code, mips_temp, mips_temp, 1);
-
- mips_patch (buf, (guint32)code);
- }
- break;
- }
- case OP_THROW: {
- gpointer addr = mono_arch_get_throw_exception(NULL, FALSE);
- mips_move (code, mips_a0, ins->sreg1);
- mips_call (code, mips_t9, addr);
- mips_break (code, 0xfc);
- break;
- }
- case OP_RETHROW: {
- gpointer addr = mono_arch_get_rethrow_exception(NULL, FALSE);
- mips_move (code, mips_a0, ins->sreg1);
- mips_call (code, mips_t9, addr);
- mips_break (code, 0xfb);
- break;
- }
- case OP_START_HANDLER: {
- /*
- * The START_HANDLER instruction marks the beginning of
- * a handler block. It is called using a call
- * instruction, so mips_ra contains the return address.
- * Since the handler executes in the same stack frame
- * as the method itself, we can't use save/restore to
- * save the return address. Instead, we save it into
- * a dedicated variable.
- */
- MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
- g_assert (spvar->inst_basereg != mips_sp);
- code = emit_reserve_param_area (cfg, code);
-
- if (mips_is_imm16 (spvar->inst_offset)) {
- mips_sw (code, mips_ra, spvar->inst_basereg, spvar->inst_offset);
- } else {
- mips_load_const (code, mips_at, spvar->inst_offset);
- mips_addu (code, mips_at, mips_at, spvar->inst_basereg);
- mips_sw (code, mips_ra, mips_at, 0);
- }
- break;
- }
- case OP_ENDFILTER: {
- MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
- g_assert (spvar->inst_basereg != mips_sp);
- code = emit_unreserve_param_area (cfg, code);
-
- if (ins->sreg1 != mips_v0)
- MIPS_MOVE (code, mips_v0, ins->sreg1);
- if (mips_is_imm16 (spvar->inst_offset)) {
- mips_lw (code, mips_ra, spvar->inst_basereg, spvar->inst_offset);
- } else {
- mips_load_const (code, mips_at, spvar->inst_offset);
- mips_addu (code, mips_at, mips_at, spvar->inst_basereg);
- mips_lw (code, mips_ra, mips_at, 0);
- }
- mips_jr (code, mips_ra);
- mips_nop (code);
- break;
- }
- case OP_ENDFINALLY: {
- MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
- g_assert (spvar->inst_basereg != mips_sp);
- code = emit_unreserve_param_area (cfg, code);
- mips_lw (code, mips_t9, spvar->inst_basereg, spvar->inst_offset);
- mips_jalr (code, mips_t9, mips_ra);
- mips_nop (code);
- break;
- }
- case OP_CALL_HANDLER:
- mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb);
- mips_lui (code, mips_t9, mips_zero, 0);
- mips_addiu (code, mips_t9, mips_t9, 0);
- mips_jalr (code, mips_t9, mips_ra);
- mips_nop (code);
- /*FIXME should it be before the NOP or not? Does MIPS has a delay slot like sparc?*/
- for (GList *tmp = ins->inst_eh_blocks; tmp != bb->clause_holes; tmp = tmp->prev)
- mono_cfg_add_try_hole (cfg, ((MonoLeaveClause *) tmp->data)->clause, code, bb);
- break;
- case OP_LABEL:
- ins->inst_c0 = code - cfg->native_code;
- break;
- case OP_BR:
- mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb);
- if (cfg->arch.long_branch) {
- mips_lui (code, mips_at, mips_zero, 0);
- mips_addiu (code, mips_at, mips_at, 0);
- mips_jr (code, mips_at);
- mips_nop (code);
- }
- else {
- mips_beq (code, mips_zero, mips_zero, 0);
- mips_nop (code);
- }
- break;
- case OP_BR_REG:
- mips_jr (code, ins->sreg1);
- mips_nop (code);
- break;
- case OP_SWITCH: {
- int i;
-
- max_len += 4 * GPOINTER_TO_INT (ins->klass);
- code = realloc_code (cfg, max_len);
-
- g_assert (ins->sreg1 != -1);
- mips_sll (code, mips_at, ins->sreg1, 2);
- if (1 || !(cfg->flags & MONO_CFG_HAS_CALLS))
- MIPS_MOVE (code, mips_t8, mips_ra);
- mips_bgezal (code, mips_zero, 1); /* bal */
- mips_nop (code);
- mips_addu (code, mips_t9, mips_ra, mips_at);
- /* Table is 16 or 20 bytes from target of bal above */
- if (1 || !(cfg->flags & MONO_CFG_HAS_CALLS)) {
- MIPS_MOVE (code, mips_ra, mips_t8);
- mips_lw (code, mips_t9, mips_t9, 20);
- }
- else
- mips_lw (code, mips_t9, mips_t9, 16);
- mips_jalr (code, mips_t9, mips_t8);
- mips_nop (code);
- for (i = 0; i < GPOINTER_TO_INT (ins->klass); ++i)
- mips_emit32 (code, 0xfefefefe);
- break;
- }
- case OP_CEQ:
- case OP_ICEQ:
- mips_addiu (code, ins->dreg, mips_zero, 1);
- mips_beq (code, mips_at, mips_zero, 2);
- mips_nop (code);
- MIPS_MOVE (code, ins->dreg, mips_zero);
- break;
- case OP_CLT:
- case OP_CLT_UN:
- case OP_ICLT:
- case OP_ICLT_UN:
- mips_addiu (code, ins->dreg, mips_zero, 1);
- mips_bltz (code, mips_at, 2);
- mips_nop (code);
- MIPS_MOVE (code, ins->dreg, mips_zero);
- break;
- case OP_CGT:
- case OP_CGT_UN:
- case OP_ICGT:
- case OP_ICGT_UN:
- mips_addiu (code, ins->dreg, mips_zero, 1);
- mips_bgtz (code, mips_at, 2);
- mips_nop (code);
- MIPS_MOVE (code, ins->dreg, mips_zero);
- break;
-
- case OP_MIPS_COND_EXC_EQ:
- case OP_MIPS_COND_EXC_GE:
- case OP_MIPS_COND_EXC_GT:
- case OP_MIPS_COND_EXC_LE:
- case OP_MIPS_COND_EXC_LT:
- case OP_MIPS_COND_EXC_NE_UN:
- case OP_MIPS_COND_EXC_GE_UN:
- case OP_MIPS_COND_EXC_GT_UN:
- case OP_MIPS_COND_EXC_LE_UN:
- case OP_MIPS_COND_EXC_LT_UN:
-
- case OP_MIPS_COND_EXC_OV:
- case OP_MIPS_COND_EXC_NO:
- case OP_MIPS_COND_EXC_C:
- case OP_MIPS_COND_EXC_NC:
-
- case OP_MIPS_COND_EXC_IEQ:
- case OP_MIPS_COND_EXC_IGE:
- case OP_MIPS_COND_EXC_IGT:
- case OP_MIPS_COND_EXC_ILE:
- case OP_MIPS_COND_EXC_ILT:
- case OP_MIPS_COND_EXC_INE_UN:
- case OP_MIPS_COND_EXC_IGE_UN:
- case OP_MIPS_COND_EXC_IGT_UN:
- case OP_MIPS_COND_EXC_ILE_UN:
- case OP_MIPS_COND_EXC_ILT_UN:
-
- case OP_MIPS_COND_EXC_IOV:
- case OP_MIPS_COND_EXC_INO:
- case OP_MIPS_COND_EXC_IC:
- case OP_MIPS_COND_EXC_INC: {
- guint32 *skip;
- guint32 *throw;
-
- /* If the condition is true, raise the exception */
-
- /* need to reverse test to skip around exception raising */
-
- /* For the moment, branch around a branch to avoid reversing
- the tests. */
-
- /* Remember, an unpatched branch to 0 branches to the delay slot */
- switch (ins->opcode) {
- case OP_MIPS_COND_EXC_EQ:
- throw = (guint32 *)(void *)code;
- mips_beq (code, ins->sreg1, ins->sreg2, 0);
- mips_nop (code);
- break;
-
- case OP_MIPS_COND_EXC_NE_UN:
- throw = (guint32 *)(void *)code;
- mips_bne (code, ins->sreg1, ins->sreg2, 0);
- mips_nop (code);
- break;
-
- case OP_MIPS_COND_EXC_LE_UN:
- mips_sltu (code, mips_at, ins->sreg2, ins->sreg1);
- throw = (guint32 *)(void *)code;
- mips_beq (code, mips_at, mips_zero, 0);
- mips_nop (code);
- break;
-
- case OP_MIPS_COND_EXC_GT:
- mips_slt (code, mips_at, ins->sreg2, ins->sreg1);
- throw = (guint32 *)(void *)code;
- mips_bne (code, mips_at, mips_zero, 0);
- mips_nop (code);
- break;
-
- case OP_MIPS_COND_EXC_GT_UN:
- mips_sltu (code, mips_at, ins->sreg2, ins->sreg1);
- throw = (guint32 *)(void *)code;
- mips_bne (code, mips_at, mips_zero, 0);
- mips_nop (code);
- break;
-
- case OP_MIPS_COND_EXC_LT:
- mips_slt (code, mips_at, ins->sreg1, ins->sreg2);
- throw = (guint32 *)(void *)code;
- mips_bne (code, mips_at, mips_zero, 0);
- mips_nop (code);
- break;
-
- case OP_MIPS_COND_EXC_LT_UN:
- mips_sltu (code, mips_at, ins->sreg1, ins->sreg2);
- throw = (guint32 *)(void *)code;
- mips_bne (code, mips_at, mips_zero, 0);
- mips_nop (code);
- break;
-
- default:
- /* Not yet implemented */
- g_warning ("NYI conditional exception %s\n", mono_inst_name (ins->opcode));
- g_assert_not_reached ();
- }
- skip = (guint32 *)(void *)code;
- mips_beq (code, mips_zero, mips_zero, 0);
- mips_nop (code);
- mips_patch (throw, (guint32)code);
- code = mips_emit_exc_by_name (code, ins->inst_p1);
- mips_patch (skip, (guint32)code);
- cfg->bb_exit->max_offset += 24;
- break;
- }
- case OP_MIPS_BEQ:
- case OP_MIPS_BNE:
- case OP_MIPS_BGEZ:
- case OP_MIPS_BGTZ:
- case OP_MIPS_BLEZ:
- case OP_MIPS_BLTZ:
- code = mips_emit_cond_branch (cfg, code, ins->opcode, ins);
- break;
-
- /* floating point opcodes */
- case OP_R8CONST:
-#if 0
- if (((guint32)ins->inst_p0) & (1 << 15))
- mips_lui (code, mips_at, mips_zero, (((guint32)ins->inst_p0)>>16)+1);
- else
- mips_lui (code, mips_at, mips_zero, (((guint32)ins->inst_p0)>>16));
- mips_ldc1 (code, ins->dreg, mips_at, ((guint32)ins->inst_p0) & 0xffff);
-#else
- mips_load_const (code, mips_at, ins->inst_p0);
- mips_lwc1 (code, ins->dreg, mips_at, ls_word_offset);
- mips_lwc1 (code, ins->dreg+1, mips_at, ms_word_offset);
-#endif
- break;
- case OP_R4CONST:
- if (((guint32)ins->inst_p0) & (1 << 15))
- mips_lui (code, mips_at, mips_zero, (((guint32)ins->inst_p0)>>16)+1);
- else
- mips_lui (code, mips_at, mips_zero, (((guint32)ins->inst_p0)>>16));
- mips_lwc1 (code, ins->dreg, mips_at, ((guint32)ins->inst_p0) & 0xffff);
-#if PROMOTE_R4_TO_R8
- mips_cvtds (code, ins->dreg, ins->dreg);
-#endif
- break;
- case OP_STORER8_MEMBASE_REG:
- if (mips_is_imm16 (ins->inst_offset)) {
-#if _MIPS_SIM == _ABIO32
- mips_swc1 (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset + ls_word_offset);
- mips_swc1 (code, ins->sreg1+1, ins->inst_destbasereg, ins->inst_offset + ms_word_offset);
-#elif _MIPS_SIM == _ABIN32
- mips_sdc1 (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
-#endif
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_destbasereg);
- mips_swc1 (code, ins->sreg1, mips_at, ls_word_offset);
- mips_swc1 (code, ins->sreg1+1, mips_at, ms_word_offset);
- }
- break;
- case OP_LOADR8_MEMBASE:
- if (mips_is_imm16 (ins->inst_offset)) {
-#if _MIPS_SIM == _ABIO32
- mips_lwc1 (code, ins->dreg, ins->inst_basereg, ins->inst_offset + ls_word_offset);
- mips_lwc1 (code, ins->dreg+1, ins->inst_basereg, ins->inst_offset + ms_word_offset);
-#elif _MIPS_SIM == _ABIN32
- mips_ldc1 (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
-#endif
- } else {
- mips_load_const (code, mips_at, ins->inst_offset);
- mips_addu (code, mips_at, mips_at, ins->inst_basereg);
- mips_lwc1 (code, ins->dreg, mips_at, ls_word_offset);
- mips_lwc1 (code, ins->dreg+1, mips_at, ms_word_offset);
- }
- break;
- case OP_STORER4_MEMBASE_REG:
- g_assert (mips_is_imm16 (ins->inst_offset));
-#if PROMOTE_R4_TO_R8
- /* Need to convert ins->sreg1 to single-precision first */
- mips_cvtsd (code, mips_ftemp, ins->sreg1);
- mips_swc1 (code, mips_ftemp, ins->inst_destbasereg, ins->inst_offset);
-#else
- mips_swc1 (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
-#endif
- break;
- case OP_MIPS_LWC1:
- g_assert (mips_is_imm16 (ins->inst_offset));
- mips_lwc1 (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
- break;
- case OP_LOADR4_MEMBASE:
- g_assert (mips_is_imm16 (ins->inst_offset));
- mips_lwc1 (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
-#if PROMOTE_R4_TO_R8
- /* Convert to double precision in place */
- mips_cvtds (code, ins->dreg, ins->dreg);
-#endif
- break;
- case OP_LOADR4_MEMINDEX:
- mips_addu (code, mips_at, ins->inst_basereg, ins->sreg2);
- mips_lwc1 (code, ins->dreg, mips_at, 0);
- break;
- case OP_LOADR8_MEMINDEX:
- mips_addu (code, mips_at, ins->inst_basereg, ins->sreg2);
-#if _MIPS_SIM == _ABIO32
- mips_lwc1 (code, ins->dreg, mips_at, ls_word_offset);
- mips_lwc1 (code, ins->dreg+1, mips_at, ms_word_offset);
-#elif _MIPS_SIM == _ABIN32
- mips_ldc1 (code, ins->dreg, mips_at, 0);
-#endif
- break;
- case OP_STORER4_MEMINDEX:
- mips_addu (code, mips_at, ins->inst_destbasereg, ins->sreg2);
-#if PROMOTE_R4_TO_R8
- /* Need to convert ins->sreg1 to single-precision first */
- mips_cvtsd (code, mips_ftemp, ins->sreg1);
- mips_swc1 (code, mips_ftemp, mips_at, 0);
-#else
- mips_swc1 (code, ins->sreg1, mips_at, 0);
-#endif
- break;
- case OP_STORER8_MEMINDEX:
- mips_addu (code, mips_at, ins->inst_destbasereg, ins->sreg2);
-#if _MIPS_SIM == _ABIO32
- mips_swc1 (code, ins->sreg1, mips_at, ls_word_offset);
- mips_swc1 (code, ins->sreg1+1, mips_at, ms_word_offset);
-#elif _MIPS_SIM == _ABIN32
- mips_sdc1 (code, ins->sreg1, mips_at, 0);
-#endif
- break;
- case OP_ICONV_TO_R_UN: {
- static const guint64 adjust_val = 0x41F0000000000000ULL;
-
- /* convert unsigned int to double */
- mips_mtc1 (code, mips_ftemp, ins->sreg1);
- mips_bgez (code, ins->sreg1, 5);
- mips_cvtdw (code, ins->dreg, mips_ftemp);
-
- mips_load (code, mips_at, (guint32) &adjust_val);
- mips_ldc1 (code, mips_ftemp, mips_at, 0);
- mips_faddd (code, ins->dreg, ins->dreg, mips_ftemp);
- /* target is here */
- break;
- }
- case OP_ICONV_TO_R4:
- mips_mtc1 (code, mips_ftemp, ins->sreg1);
- mips_cvtsw (code, ins->dreg, mips_ftemp);
- mips_cvtds (code, ins->dreg, ins->dreg);
- break;
- case OP_ICONV_TO_R8:
- mips_mtc1 (code, mips_ftemp, ins->sreg1);
- mips_cvtdw (code, ins->dreg, mips_ftemp);
- break;
- case OP_FCONV_TO_I1:
- code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, TRUE);
- break;
- case OP_FCONV_TO_U1:
- code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
- break;
- case OP_FCONV_TO_I2:
- code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, TRUE);
- break;
- case OP_FCONV_TO_U2:
- code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
- break;
- case OP_FCONV_TO_I4:
- code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, TRUE);
- break;
- case OP_FCONV_TO_U4:
- code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
- break;
- case OP_SQRT:
- mips_fsqrtd (code, ins->dreg, ins->sreg1);
- break;
- case OP_FADD:
- mips_faddd (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_FSUB:
- mips_fsubd (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_FMUL:
- mips_fmuld (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_FDIV:
- mips_fdivd (code, ins->dreg, ins->sreg1, ins->sreg2);
- break;
- case OP_FNEG:
- mips_fnegd (code, ins->dreg, ins->sreg1);
- break;
- case OP_FCEQ:
- mips_fcmpd (code, MIPS_FPU_EQ, ins->sreg1, ins->sreg2);
- mips_addiu (code, ins->dreg, mips_zero, 1);
- mips_fbtrue (code, 2);
- mips_nop (code);
- MIPS_MOVE (code, ins->dreg, mips_zero);
- break;
- case OP_FCLT:
- mips_fcmpd (code, MIPS_FPU_LT, ins->sreg1, ins->sreg2);
- mips_addiu (code, ins->dreg, mips_zero, 1);
- mips_fbtrue (code, 2);
- mips_nop (code);
- MIPS_MOVE (code, ins->dreg, mips_zero);
- break;
- case OP_FCLT_UN:
- /* Less than, or Unordered */
- mips_fcmpd (code, MIPS_FPU_ULT, ins->sreg1, ins->sreg2);
- mips_addiu (code, ins->dreg, mips_zero, 1);
- mips_fbtrue (code, 2);
- mips_nop (code);
- MIPS_MOVE (code, ins->dreg, mips_zero);
- break;
- case OP_FCGT:
- mips_fcmpd (code, MIPS_FPU_ULE, ins->sreg1, ins->sreg2);
- MIPS_MOVE (code, ins->dreg, mips_zero);
- mips_fbtrue (code, 2);
- mips_nop (code);
- mips_addiu (code, ins->dreg, mips_zero, 1);
- break;
- case OP_FCGT_UN:
- /* Greater than, or Unordered */
- mips_fcmpd (code, MIPS_FPU_OLE, ins->sreg1, ins->sreg2);
- MIPS_MOVE (code, ins->dreg, mips_zero);
- mips_fbtrue (code, 2);
- mips_nop (code);
- mips_addiu (code, ins->dreg, mips_zero, 1);
- break;
- case OP_MIPS_FBEQ:
- case OP_MIPS_FBNE:
- case OP_MIPS_FBLT:
- case OP_MIPS_FBLT_UN:
- case OP_MIPS_FBGT:
- case OP_MIPS_FBGT_UN:
- case OP_MIPS_FBGE:
- case OP_MIPS_FBGE_UN:
- case OP_MIPS_FBLE:
- case OP_MIPS_FBLE_UN: {
- int cond = 0;
- gboolean is_true = TRUE, is_ordered = FALSE;
- guint32 *buf = NULL;
-
- switch (ins->opcode) {
- case OP_MIPS_FBEQ:
- cond = MIPS_FPU_EQ;
- is_true = TRUE;
- break;
- case OP_MIPS_FBNE:
- cond = MIPS_FPU_EQ;
- is_true = FALSE;
- break;
- case OP_MIPS_FBLT:
- cond = MIPS_FPU_LT;
- is_true = TRUE;
- is_ordered = TRUE;
- break;
- case OP_MIPS_FBLT_UN:
- cond = MIPS_FPU_ULT;
- is_true = TRUE;
- break;
- case OP_MIPS_FBGT:
- cond = MIPS_FPU_LE;
- is_true = FALSE;
- is_ordered = TRUE;
- break;
- case OP_MIPS_FBGT_UN:
- cond = MIPS_FPU_OLE;
- is_true = FALSE;
- break;
- case OP_MIPS_FBGE:
- cond = MIPS_FPU_LT;
- is_true = FALSE;
- is_ordered = TRUE;
- break;
- case OP_MIPS_FBGE_UN:
- cond = MIPS_FPU_OLT;
- is_true = FALSE;
- break;
- case OP_MIPS_FBLE:
- cond = MIPS_FPU_OLE;
- is_true = TRUE;
- is_ordered = TRUE;
- break;
- case OP_MIPS_FBLE_UN:
- cond = MIPS_FPU_ULE;
- is_true = TRUE;
- break;
- default:
- g_assert_not_reached ();
- }
-
- if (is_ordered) {
- /* Skip the check if unordered */
- mips_fcmpd (code, MIPS_FPU_UN, ins->sreg1, ins->sreg2);
- mips_nop (code);
- buf = (guint32*)code;
- mips_fbtrue (code, 0);
- mips_nop (code);
- }
-
- mips_fcmpd (code, cond, ins->sreg1, ins->sreg2);
- mips_nop (code);
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb);
- if (is_true)
- mips_fbtrue (code, 0);
- else
- mips_fbfalse (code, 0);
- mips_nop (code);
-
- if (is_ordered)
- mips_patch (buf, (guint32)code);
- break;
- }
- case OP_CKFINITE: {
- guint32 *branch_patch;
-
- mips_mfc1 (code, mips_at, ins->sreg1+1);
- mips_srl (code, mips_at, mips_at, 16+4);
- mips_andi (code, mips_at, mips_at, 2047);
- mips_addiu (code, mips_at, mips_at, -2047);
-
- branch_patch = (guint32 *)(void *)code;
- mips_bne (code, mips_at, mips_zero, 0);
- mips_nop (code);
-
- EMIT_SYSTEM_EXCEPTION_NAME("OverflowException");
- mips_patch (branch_patch, (guint32)code);
- mips_fmovd (code, ins->dreg, ins->sreg1);
- break;
- }
- case OP_JUMP_TABLE:
- mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_c1, ins->inst_p0);
- mips_load (code, ins->dreg, 0x0f0f0f0f);
- break;
- case OP_LIVERANGE_START: {
- if (cfg->verbose_level > 1)
- printf ("R%d START=0x%x\n", MONO_VARINFO (cfg, ins->inst_c0)->vreg, (int)(code - cfg->native_code));
- MONO_VARINFO (cfg, ins->inst_c0)->live_range_start = code - cfg->native_code;
- break;
- }
- case OP_LIVERANGE_END: {
- if (cfg->verbose_level > 1)
- printf ("R%d END=0x%x\n", MONO_VARINFO (cfg, ins->inst_c0)->vreg, (int)(code - cfg->native_code));
- MONO_VARINFO (cfg, ins->inst_c0)->live_range_end = code - cfg->native_code;
- break;
- }
- case OP_GC_SAFE_POINT:
- break;
-
-
- default:
- g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
- g_assert_not_reached ();
- }
-
- if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
- g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %d)",
- mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
- g_assert_not_reached ();
- }
-
- cpos += max_len;
-
- last_ins = ins;
- }
-
- set_code_cursor (cfg, code);
-}
-
-void
-mono_arch_register_lowlevel_calls (void)
-{
-}
-
-void
-mono_arch_patch_code_new (MonoCompile *cfg, guint8 *code, MonoJumpInfo *ji, gpointer target)
-{
- unsigned char *ip = ji->ip.i + code;
-
- switch (ji->type) {
- case MONO_PATCH_INFO_IP:
- patch_lui_addiu ((guint32 *)(void *)ip, (guint32)ip);
- continue;
- case MONO_PATCH_INFO_SWITCH: {
- gpointer *table = (gpointer *)ji->data.table->table;
- int i;
-
- patch_lui_addiu ((guint32 *)(void *)ip, (guint32)table);
-
- for (i = 0; i < ji->data.table->table_size; i++) {
- table [i] = (int)ji->data.table->table [i] + code;
- }
- continue;
- }
- case MONO_PATCH_INFO_METHODCONST:
- case MONO_PATCH_INFO_CLASS:
- case MONO_PATCH_INFO_IMAGE:
- case MONO_PATCH_INFO_FIELD:
- case MONO_PATCH_INFO_VTABLE:
- case MONO_PATCH_INFO_IID:
- case MONO_PATCH_INFO_SFLDA:
- case MONO_PATCH_INFO_LDSTR:
- case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
- case MONO_PATCH_INFO_LDTOKEN:
- case MONO_PATCH_INFO_R4:
- case MONO_PATCH_INFO_R8:
- /* from OP_AOTCONST : lui + addiu */
- patch_lui_addiu ((guint32 *)(void *)ip, (guint32)target);
- continue;
-#if 0
- case MONO_PATCH_INFO_EXC_NAME:
- g_assert_not_reached ();
- *((gconstpointer *)(void *)(ip + 1)) = target;
- continue;
-#endif
- case MONO_PATCH_INFO_NONE:
- /* everything is dealt with at epilog output time */
- continue;
- default:
- mips_patch ((guint32 *)(void *)ip, (guint32)target);
- break;
- }
-}
-
-void
-mips_adjust_stackframe(MonoCompile *cfg)
-{
- MonoBasicBlock *bb;
- int delta, threshold, i;
- MonoMethodSignature *sig;
- int ra_offset;
-
- if (cfg->stack_offset == cfg->arch.local_alloc_offset)
- return;
-
- /* adjust cfg->stack_offset for account for down-spilling */
- cfg->stack_offset += SIZEOF_REGISTER;
-
- /* re-align cfg->stack_offset if needed (due to var spilling) */
- cfg->stack_offset = (cfg->stack_offset + MIPS_STACK_ALIGNMENT - 1) & ~(MIPS_STACK_ALIGNMENT - 1);
- delta = cfg->stack_offset - cfg->arch.local_alloc_offset;
- if (cfg->verbose_level > 2) {
- g_print ("mips_adjust_stackframe:\n");
- g_print ("\tspillvars allocated 0x%x -> 0x%x\n", cfg->arch.local_alloc_offset, cfg->stack_offset);
- }
- threshold = cfg->arch.local_alloc_offset;
- ra_offset = cfg->stack_offset - sizeof(gpointer);
- if (cfg->verbose_level > 2) {
- g_print ("\tra_offset %d/0x%x delta %d/0x%x\n", ra_offset, ra_offset, delta, delta);
- }
-
- sig = mono_method_signature_internal (cfg->method);
- if (sig && sig->ret && MONO_TYPE_ISSTRUCT (sig->ret)) {
- cfg->vret_addr->inst_offset += delta;
- }
- for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
- MonoInst *inst = cfg->args [i];
-
- inst->inst_offset += delta;
- }
-
- /*
- * loads and stores based off the frame reg that (used to) lie
- * above the spill var area need to be increased by 'delta'
- * to make room for the spill vars.
- */
- /* Need to find loads and stores to adjust that
- * are above where the spillvars were inserted, but
- * which are not the spillvar references themselves.
- *
- * Idea - since all offsets from fp are positive, make
- * spillvar offsets negative to begin with so we can spot
- * them here.
- */
-
-#if 1
- for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
- int ins_cnt = 0;
- MonoInst *ins;
-
- if (cfg->verbose_level > 2) {
- g_print ("BASIC BLOCK %d:\n", bb->block_num);
- }
- MONO_BB_FOR_EACH_INS (bb, ins) {
- int adj_c0 = 0;
- int adj_imm = 0;
-
- if (cfg->verbose_level > 2) {
- mono_print_ins_index (ins_cnt, ins);
- }
- /* The == mips_sp tests catch FP spills */
- if (MONO_IS_LOAD_MEMBASE(ins) && ((ins->inst_basereg == mips_fp) ||
- (ins->inst_basereg == mips_sp))) {
- switch (ins->opcode) {
- case OP_LOADI8_MEMBASE:
- case OP_LOADR8_MEMBASE:
- adj_c0 = 8;
- break;
- default:
- adj_c0 = 4;
- break;
- }
- } else if (MONO_IS_STORE_MEMBASE(ins) && ((ins->dreg == mips_fp) ||
- (ins->dreg == mips_sp))) {
- switch (ins->opcode) {
- case OP_STOREI8_MEMBASE_REG:
- case OP_STORER8_MEMBASE_REG:
- case OP_STOREI8_MEMBASE_IMM:
- adj_c0 = 8;
- break;
- default:
- adj_c0 = 4;
- break;
- }
- }
- if (((ins->opcode == OP_ADD_IMM) || (ins->opcode == OP_IADD_IMM)) && (ins->sreg1 == cfg->frame_reg))
- adj_imm = 1;
- if (adj_c0) {
- if (ins->inst_c0 >= threshold) {
- ins->inst_c0 += delta;
- if (cfg->verbose_level > 2) {
- g_print ("adj");
- mono_print_ins_index (ins_cnt, ins);
- }
- }
- else if (ins->inst_c0 < 0) {
- /* Adj_c0 holds the size of the datatype. */
- ins->inst_c0 = - ins->inst_c0 - adj_c0;
- if (cfg->verbose_level > 2) {
- g_print ("spill");
- mono_print_ins_index (ins_cnt, ins);
- }
- }
- g_assert (ins->inst_c0 != ra_offset);
- }
- if (adj_imm) {
- if (ins->inst_imm >= threshold) {
- ins->inst_imm += delta;
- if (cfg->verbose_level > 2) {
- g_print ("adj");
- mono_print_ins_index (ins_cnt, ins);
- }
- }
- g_assert (ins->inst_c0 != ra_offset);
- }
-
- ++ins_cnt;
- }
- }
-#endif
-}
-
-/*
- * Stack frame layout:
- *
- * ------------------- sp + cfg->stack_usage + cfg->param_area
- * param area incoming
- * ------------------- sp + cfg->stack_usage + MIPS_STACK_PARAM_OFFSET
- * a0-a3 incoming
- * ------------------- sp + cfg->stack_usage
- * ra
- * ------------------- sp + cfg->stack_usage-4
- * spilled regs
- * ------------------- sp +
- * MonoLMF structure optional
- * ------------------- sp + cfg->arch.lmf_offset
- * saved registers s0-s8
- * ------------------- sp + cfg->arch.iregs_offset
- * locals
- * ------------------- sp + cfg->param_area
- * param area outgoing
- * ------------------- sp + MIPS_STACK_PARAM_OFFSET
- * a0-a3 outgoing
- * ------------------- sp
- * red zone
- */
-guint8 *
-mono_arch_emit_prolog (MonoCompile *cfg)
-{
- MonoMethod *method = cfg->method;
- MonoMethodSignature *sig;
- MonoInst *inst;
- int alloc_size, pos, i, max_offset;
- int alloc2_size = 0;
- guint8 *code;
- CallInfo *cinfo;
- guint32 iregs_to_save = 0;
-#if SAVE_FP_REGS
- guint32 fregs_to_save = 0;
-#endif
- /* lmf_offset is the offset of the LMF from our stack pointer. */
- guint32 lmf_offset = cfg->arch.lmf_offset;
- int cfa_offset = 0;
- MonoBasicBlock *bb;
-
- sig = mono_method_signature_internal (method);
- cfg->code_size = 768 + sig->param_count * 20;
- code = cfg->native_code = g_malloc (cfg->code_size);
-
- /*
- * compute max_offset in order to use short forward jumps.
- */
- max_offset = 0;
- for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
- MonoInst *ins = bb->code;
- bb->max_offset = max_offset;
-
- MONO_BB_FOR_EACH_INS (bb, ins)
- max_offset += ins_get_size (ins->opcode);
- }
- if (max_offset > 0xffff)
- cfg->arch.long_branch = TRUE;
-
- /*
- * Currently, fp points to the bottom of the frame on MIPS, unlike other platforms.
- * This means that we have to adjust the offsets inside instructions which reference
- * arguments received on the stack, since the initial offset doesn't take into
- * account spill slots.
- */
- mips_adjust_stackframe (cfg);
-
- /* Offset between current sp and the CFA */
- cfa_offset = 0;
- mono_emit_unwind_op_def_cfa (cfg, code, mips_sp, cfa_offset);
-
- /* stack_offset should not be changed here. */
- alloc_size = cfg->stack_offset;
- cfg->stack_usage = alloc_size;
-
- iregs_to_save = (cfg->used_int_regs & MONO_ARCH_CALLEE_SAVED_REGS);
-#if SAVE_FP_REGS
-#if 0
- fregs_to_save = (cfg->used_float_regs & MONO_ARCH_CALLEE_SAVED_FREGS);
-#else
- fregs_to_save = MONO_ARCH_CALLEE_SAVED_FREGS;
- fregs_to_save |= (fregs_to_save << 1);
-#endif
-#endif
- /* If the stack size is too big, save 1024 bytes to start with
- * so the prologue can use imm16(reg) addressing, then allocate
- * the rest of the frame.
- */
- if (alloc_size > ((1 << 15) - 1024)) {
- alloc2_size = alloc_size - 1024;
- alloc_size = 1024;
- }
- if (alloc_size) {
- g_assert (mips_is_imm16 (-alloc_size));
- mips_addiu (code, mips_sp, mips_sp, -alloc_size);
- cfa_offset = alloc_size;
- mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
- }
-
- if ((cfg->flags & MONO_CFG_HAS_CALLS) || ALWAYS_SAVE_RA) {
- int offset = alloc_size + MIPS_RET_ADDR_OFFSET;
- if (mips_is_imm16(offset))
- mips_sw (code, mips_ra, mips_sp, offset);
- else {
- g_assert_not_reached ();
- }
- /* sp = cfa - cfa_offset, so sp + offset = cfa - cfa_offset + offset */
- mono_emit_unwind_op_offset (cfg, code, mips_ra, offset - cfa_offset);
- }
-
- /* XXX - optimize this later to not save all regs if LMF constructed */
- pos = cfg->arch.iregs_offset - alloc2_size;
-
- if (iregs_to_save) {
- /* save used registers in own stack frame (at pos) */
- for (i = MONO_MAX_IREGS-1; i >= 0; --i) {
- if (iregs_to_save & (1 << i)) {
- g_assert (pos < (int)(cfg->stack_usage - sizeof(gpointer)));
- g_assert (mips_is_imm16(pos));
- MIPS_SW (code, i, mips_sp, pos);
- mono_emit_unwind_op_offset (cfg, code, i, pos - cfa_offset);
- pos += SIZEOF_REGISTER;
- }
- }
- }
-
- // FIXME: Don't save registers twice if there is an LMF
- // s8 has to be special cased since it is overwritten with the updated value
- // below
- if (method->save_lmf) {
- for (i = MONO_MAX_IREGS-1; i >= 0; --i) {
- int offset = lmf_offset + G_STRUCT_OFFSET(MonoLMF, iregs[i]);
- g_assert (mips_is_imm16(offset));
- if (MIPS_LMF_IREGMASK & (1 << i))
- MIPS_SW (code, i, mips_sp, offset);
- }
- }
-
-#if SAVE_FP_REGS
- /* Save float registers */
- if (fregs_to_save) {
- for (i = MONO_MAX_FREGS-1; i >= 0; --i) {
- if (fregs_to_save & (1 << i)) {
- g_assert (pos < cfg->stack_usage - MIPS_STACK_ALIGNMENT);
- g_assert (mips_is_imm16(pos));
- mips_swc1 (code, i, mips_sp, pos);
- pos += sizeof (gulong);
- }
- }
- }
-
- if (method->save_lmf) {
- for (i = MONO_MAX_FREGS-1; i >= 0; --i) {
- int offset = lmf_offset + G_STRUCT_OFFSET(MonoLMF, fregs[i]);
- g_assert (mips_is_imm16(offset));
- mips_swc1 (code, i, mips_sp, offset);
- }
- }
-
-#endif
- if (cfg->frame_reg != mips_sp) {
- MIPS_MOVE (code, cfg->frame_reg, mips_sp);
- mono_emit_unwind_op_def_cfa (cfg, code, cfg->frame_reg, cfa_offset);
-
- if (method->save_lmf) {
- int offset = lmf_offset + G_STRUCT_OFFSET(MonoLMF, iregs[cfg->frame_reg]);
- g_assert (mips_is_imm16(offset));
- MIPS_SW (code, cfg->frame_reg, mips_sp, offset);
- }
- }
-
- /* store runtime generic context */
- if (cfg->rgctx_var) {
- MonoInst *ins = cfg->rgctx_var;
-
- g_assert (ins->opcode == OP_REGOFFSET);
-
- g_assert (mips_is_imm16 (ins->inst_offset));
- mips_sw (code, MONO_ARCH_RGCTX_REG, ins->inst_basereg, ins->inst_offset);
- }
-
- /* load arguments allocated to register from the stack */
- pos = 0;
-
- if (!cfg->arch.cinfo)
- cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
- cinfo = cfg->arch.cinfo;
-
- if (MONO_TYPE_ISSTRUCT (sig->ret)) {
- ArgInfo *ainfo = &cinfo->ret;
- inst = cfg->vret_addr;
- if (inst->opcode == OP_REGVAR)
- MIPS_MOVE (code, inst->dreg, ainfo->reg);
- else if (mips_is_imm16 (inst->inst_offset)) {
- mips_sw (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
- } else {
- mips_load_const (code, mips_at, inst->inst_offset);
- mips_addu (code, mips_at, mips_at, inst->inst_basereg);
- mips_sw (code, ainfo->reg, mips_at, 0);
- }
- }
-
- if (sig->call_convention == MONO_CALL_VARARG) {
- ArgInfo *cookie = &cinfo->sig_cookie;
- int offset = alloc_size + cookie->offset;
-
- /* Save the sig cookie address */
- g_assert (cookie->storage == ArgOnStack);
-
- g_assert (mips_is_imm16(offset));
- mips_addi (code, mips_at, cfg->frame_reg, offset);
- mips_sw (code, mips_at, cfg->frame_reg, cfg->sig_cookie - alloc2_size);
- }
-
- /* Keep this in sync with emit_load_volatile_arguments */
- for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
- ArgInfo *ainfo = cinfo->args + i;
- inst = cfg->args [pos];
-
- if (cfg->verbose_level > 2)
- g_print ("Saving argument %d (type: %d)\n", i, ainfo->storage);
- if (inst->opcode == OP_REGVAR) {
- /* Argument ends up in a register */
- if (ainfo->storage == ArgInIReg)
- MIPS_MOVE (code, inst->dreg, ainfo->reg);
- else if (ainfo->storage == ArgInFReg) {
- g_assert_not_reached();
-#if 0
- ppc_fmr (code, inst->dreg, ainfo->reg);
-#endif
- }
- else if (ainfo->storage == ArgOnStack) {
- int offset = cfg->stack_usage + ainfo->offset;
- g_assert (mips_is_imm16(offset));
- mips_lw (code, inst->dreg, mips_sp, offset);
- } else
- g_assert_not_reached ();
-
- if (cfg->verbose_level > 2)
- g_print ("Argument %d assigned to register %s\n", pos, mono_arch_regname (inst->dreg));
- } else {
- /* Argument ends up on the stack */
- if (ainfo->storage == ArgInIReg) {
- int basereg_offset;
- /* Incoming parameters should be above this frame */
- if (cfg->verbose_level > 2)
- g_print ("stack slot at %d of %d+%d\n",
- inst->inst_offset, alloc_size, alloc2_size);
- /* g_assert (inst->inst_offset >= alloc_size); */
- g_assert (inst->inst_basereg == cfg->frame_reg);
- basereg_offset = inst->inst_offset - alloc2_size;
- g_assert (mips_is_imm16 (basereg_offset));
- switch (ainfo->size) {
- case 1:
- mips_sb (code, ainfo->reg, inst->inst_basereg, basereg_offset);
- break;
- case 2:
- mips_sh (code, ainfo->reg, inst->inst_basereg, basereg_offset);
- break;
- case 0: /* XXX */
- case 4:
- mips_sw (code, ainfo->reg, inst->inst_basereg, basereg_offset);
- break;
- case 8:
-#if (SIZEOF_REGISTER == 4)
- mips_sw (code, ainfo->reg, inst->inst_basereg, basereg_offset + ls_word_offset);
- mips_sw (code, ainfo->reg + 1, inst->inst_basereg, basereg_offset + ms_word_offset);
-#elif (SIZEOF_REGISTER == 8)
- mips_sd (code, ainfo->reg, inst->inst_basereg, basereg_offset);
-#endif
- break;
- default:
- g_assert_not_reached ();
- break;
- }
- } else if (ainfo->storage == ArgOnStack) {
- /*
- * Argument comes in on the stack, and ends up on the stack
- * 1 and 2 byte args are passed as 32-bit quantities, but used as
- * 8 and 16 bit quantities. Shorten them in place.
- */
- g_assert (mips_is_imm16 (inst->inst_offset));
- switch (ainfo->size) {
- case 1:
- mips_lw (code, mips_at, inst->inst_basereg, inst->inst_offset);
- mips_sb (code, mips_at, inst->inst_basereg, inst->inst_offset);
- break;
- case 2:
- mips_lw (code, mips_at, inst->inst_basereg, inst->inst_offset);
- mips_sh (code, mips_at, inst->inst_basereg, inst->inst_offset);
- break;
- case 0: /* XXX */
- case 4:
- case 8:
- break;
- default:
- g_assert_not_reached ();
- }
- } else if (ainfo->storage == ArgInFReg) {
- g_assert (mips_is_imm16 (inst->inst_offset));
- g_assert (mips_is_imm16 (inst->inst_offset+4));
- if (ainfo->size == 8) {
-#if _MIPS_SIM == _ABIO32
- mips_swc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset + ls_word_offset);
- mips_swc1 (code, ainfo->reg+1, inst->inst_basereg, inst->inst_offset + ms_word_offset);
-#elif _MIPS_SIM == _ABIN32
- mips_sdc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
-#endif
- }
- else if (ainfo->size == 4)
- mips_swc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
- else
- g_assert_not_reached ();
- } else if (ainfo->storage == ArgStructByVal) {
- int i;
- int doffset = inst->inst_offset;
-
- g_assert (mips_is_imm16 (inst->inst_offset));
- g_assert (mips_is_imm16 (inst->inst_offset + ainfo->size * sizeof (target_mgreg_t)));
- /* Push the argument registers into their stack slots */
- for (i = 0; i < ainfo->size; ++i) {
- g_assert (mips_is_imm16(doffset));
- MIPS_SW (code, ainfo->reg + i, inst->inst_basereg, doffset);
- doffset += SIZEOF_REGISTER;
- }
- } else if (ainfo->storage == ArgStructByAddr) {
- g_assert (mips_is_imm16 (inst->inst_offset));
- /* FIXME: handle overrun! with struct sizes not multiple of 4 */
- code = emit_memcpy (code, ainfo->vtsize * sizeof (target_mgreg_t), inst->inst_basereg, inst->inst_offset, ainfo->reg, 0);
- } else
- g_assert_not_reached ();
- }
- pos++;
- }
-
- if (method->save_lmf) {
- mips_load_const (code, mips_at, MIPS_LMF_MAGIC1);
- mips_sw (code, mips_at, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, magic));
-
- /* This can/will clobber the a0-a3 registers */
- mips_call (code, mips_t9, (gpointer)mono_get_lmf_addr);
-
- /* mips_v0 is the result from mono_get_lmf_addr () (MonoLMF **) */
- g_assert (mips_is_imm16(lmf_offset + G_STRUCT_OFFSET(MonoLMF, lmf_addr)));
- mips_sw (code, mips_v0, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, lmf_addr));
- /* new_lmf->previous_lmf = *lmf_addr */
- mips_lw (code, mips_at, mips_v0, 0);
- g_assert (mips_is_imm16(lmf_offset + G_STRUCT_OFFSET(MonoLMF, previous_lmf)));
- mips_sw (code, mips_at, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, previous_lmf));
- /* *(lmf_addr) = sp + lmf_offset */
- g_assert (mips_is_imm16(lmf_offset));
- mips_addiu (code, mips_at, mips_sp, lmf_offset);
- mips_sw (code, mips_at, mips_v0, 0);
-
- /* save method info */
- mips_load_const (code, mips_at, method);
- g_assert (mips_is_imm16(lmf_offset + G_STRUCT_OFFSET(MonoLMF, method)));
- mips_sw (code, mips_at, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, method));
-
- /* save the current IP */
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_IP, NULL);
- mips_load_const (code, mips_at, 0x01010101);
- mips_sw (code, mips_at, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, eip));
- }
-
- if (alloc2_size) {
- if (mips_is_imm16 (-alloc2_size)) {
- mips_addu (code, mips_sp, mips_sp, -alloc2_size);
- }
- else {
- mips_load_const (code, mips_at, -alloc2_size);
- mips_addu (code, mips_sp, mips_sp, mips_at);
- }
- alloc_size += alloc2_size;
- cfa_offset += alloc2_size;
- if (cfg->frame_reg != mips_sp)
- MIPS_MOVE (code, cfg->frame_reg, mips_sp);
- else
- mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
- }
-
- set_code_cursor (cfg, code);
-
- return code;
-}
-
-guint8 *
-mono_arch_emit_epilog_sub (MonoCompile *cfg)
-{
- guint8 *code = NULL;
- MonoMethod *method = cfg->method;
- int i;
- int max_epilog_size = 16 + 20*4;
- int alloc2_size = 0;
- guint32 iregs_to_restore;
-#if SAVE_FP_REGS
- guint32 fregs_to_restore;
-#endif
-
- if (cfg->method->save_lmf)
- max_epilog_size += 128;
-
- realloc_code (cfg, max_epilog_size);
-
- code = cfg->native_code + cfg->code_len;
-
- if (cfg->frame_reg != mips_sp) {
- MIPS_MOVE (code, mips_sp, cfg->frame_reg);
- }
- /* If the stack frame is really large, deconstruct it in two steps */
- if (cfg->stack_usage > ((1 << 15) - 1024)) {
- alloc2_size = cfg->stack_usage - 1024;
- /* partially deconstruct the stack */
- mips_load_const (code, mips_at, alloc2_size);
- mips_addu (code, mips_sp, mips_sp, mips_at);
- }
- int pos = cfg->arch.iregs_offset - alloc2_size;
- iregs_to_restore = (cfg->used_int_regs & MONO_ARCH_CALLEE_SAVED_REGS);
- if (iregs_to_restore) {
- for (i = MONO_MAX_IREGS-1; i >= 0; --i) {
- if (iregs_to_restore & (1 << i)) {
- g_assert (mips_is_imm16(pos));
- MIPS_LW (code, i, mips_sp, pos);
- pos += SIZEOF_REGISTER;
- }
- }
- }
-
-#if SAVE_FP_REGS
-#if 0
- fregs_to_restore = (cfg->used_float_regs & MONO_ARCH_CALLEE_SAVED_FREGS);
-#else
- fregs_to_restore = MONO_ARCH_CALLEE_SAVED_FREGS;
- fregs_to_restore |= (fregs_to_restore << 1);
-#endif
- if (fregs_to_restore) {
- for (i = MONO_MAX_FREGS-1; i >= 0; --i) {
- if (fregs_to_restore & (1 << i)) {
- g_assert (pos < cfg->stack_usage - MIPS_STACK_ALIGNMENT);
- g_assert (mips_is_imm16(pos));
- mips_lwc1 (code, i, mips_sp, pos);
- pos += FREG_SIZE
- }
- }
- }
-#endif
-
- /* Unlink the LMF if necessary */
- if (method->save_lmf) {
- int lmf_offset = cfg->arch.lmf_offset;
-
- /* t0 = current_lmf->previous_lmf */
- g_assert (mips_is_imm16(lmf_offset + G_STRUCT_OFFSET(MonoLMF, previous_lmf)));
- mips_lw (code, mips_temp, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, previous_lmf));
- /* t1 = lmf_addr */
- g_assert (mips_is_imm16(lmf_offset + G_STRUCT_OFFSET(MonoLMF, lmf_addr)));
- mips_lw (code, mips_t1, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, lmf_addr));
- /* (*lmf_addr) = previous_lmf */
- mips_sw (code, mips_temp, mips_t1, 0);
- }
-
-#if 0
- /* Restore the fp */
- mips_lw (code, mips_fp, mips_sp, cfg->stack_usage + MIPS_FP_ADDR_OFFSET);
-#endif
- /* Restore ra */
- if ((cfg->flags & MONO_CFG_HAS_CALLS) || ALWAYS_SAVE_RA) {
- g_assert (mips_is_imm16(cfg->stack_usage - alloc2_size + MIPS_RET_ADDR_OFFSET));
- mips_lw (code, mips_ra, mips_sp, cfg->stack_usage - alloc2_size + MIPS_RET_ADDR_OFFSET);
- }
- /* Restore the stack pointer */
- g_assert (mips_is_imm16(cfg->stack_usage - alloc2_size));
- mips_addiu (code, mips_sp, mips_sp, cfg->stack_usage - alloc2_size);
-
- /* Caller will emit either return or tail-call sequence */
-
- set_code_cursor (cfg, code);
-
- return (code);
-}
-
-void
-mono_arch_emit_epilog (MonoCompile *cfg)
-{
- guint8 *code = mono_arch_emit_epilog_sub (cfg);
-
- mips_jr (code, mips_ra);
- mips_nop (code);
-
- set_code_cursor (cfg, code);
-}
-
-/* remove once throw_exception_by_name is eliminated */
-#if 0
-static int
-exception_id_by_name (const char *name)
-{
- if (strcmp (name, "IndexOutOfRangeException") == 0)
- return MONO_EXC_INDEX_OUT_OF_RANGE;
- if (strcmp (name, "OverflowException") == 0)
- return MONO_EXC_OVERFLOW;
- if (strcmp (name, "ArithmeticException") == 0)
- return MONO_EXC_ARITHMETIC;
- if (strcmp (name, "DivideByZeroException") == 0)
- return MONO_EXC_DIVIDE_BY_ZERO;
- if (strcmp (name, "InvalidCastException") == 0)
- return MONO_EXC_INVALID_CAST;
- if (strcmp (name, "NullReferenceException") == 0)
- return MONO_EXC_NULL_REF;
- if (strcmp (name, "ArrayTypeMismatchException") == 0)
- return MONO_EXC_ARRAY_TYPE_MISMATCH;
- if (strcmp (name, "ArgumentException") == 0)
- return MONO_EXC_ARGUMENT;
- g_error ("Unknown intrinsic exception %s\n", name);
- return 0;
-}
-#endif
-
-void
-mono_arch_emit_exceptions (MonoCompile *cfg)
-{
-#if 0
- MonoJumpInfo *patch_info;
- int i;
- guint8 *code;
- const guint8* exc_throw_pos [MONO_EXC_INTRINS_NUM] = {NULL};
- guint8 exc_throw_found [MONO_EXC_INTRINS_NUM] = {0};
- int max_epilog_size = 50;
-
- /* count the number of exception infos */
-
- /*
- * make sure we have enough space for exceptions
- * 24 is the simulated call to throw_exception_by_name
- */
- for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
-#if 0
- if (patch_info->type == MONO_PATCH_INFO_EXC) {
- i = exception_id_by_name (patch_info->data.target);
- g_assert (i < MONO_EXC_INTRINS_NUM);
- if (!exc_throw_found [i]) {
- max_epilog_size += 12;
- exc_throw_found [i] = TRUE;
- }
- }
-#endif
- }
-
- code = realloc_code (cfg, max_epilog_size);
-
- /* add code to raise exceptions */
- for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
- switch (patch_info->type) {
- case MONO_PATCH_INFO_EXC: {
- g_assert_not_reached();
- break;
- }
- default:
- /* do nothing */
- break;
- }
- }
-
- set_code_cursor (cfg, code);
-#endif
-}
-
-void
-mono_arch_finish_init (void)
-{
-}
-
-void
-mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, int this_reg, int this_type, int vt_reg)
-{
- int this_dreg = mips_a0;
-
- if (vt_reg != -1)
- this_dreg = mips_a1;
-
- /* add the this argument */
- if (this_reg != -1) {
- MonoInst *this_ins;
- MONO_INST_NEW (cfg, this_ins, OP_MOVE);
- this_ins->type = this_type;
- this_ins->sreg1 = this_reg;
- this_ins->dreg = mono_alloc_ireg (cfg);
- mono_bblock_add_inst (cfg->cbb, this_ins);
- mono_call_inst_add_outarg_reg (cfg, inst, this_ins->dreg, this_dreg, FALSE);
- }
-
- if (vt_reg != -1) {
- MonoInst *vtarg;
- MONO_INST_NEW (cfg, vtarg, OP_MOVE);
- vtarg->type = STACK_MP;
- vtarg->sreg1 = vt_reg;
- vtarg->dreg = mono_alloc_ireg (cfg);
- mono_bblock_add_inst (cfg->cbb, vtarg);
- mono_call_inst_add_outarg_reg (cfg, inst, vtarg->dreg, mips_a0, FALSE);
- }
-}
-
-MonoInst*
-mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
-{
- MonoInst *ins = NULL;
-
- return ins;
-}
-
-MonoInst*
-mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
-{
- return NULL;
-}
-
-host_mgreg_t
-mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
-{
- return ctx->sc_regs [reg];
-}
-
-host_mgreg_t*
-mono_arch_context_get_int_reg_address (MonoContext *ctx, int reg)
-{
- return &ctx->sc_regs [reg];
-}
-
-#define ENABLE_WRONG_METHOD_CHECK 0
-
-#define MIPS_LOAD_SEQUENCE_LENGTH 8
-#define CMP_SIZE (MIPS_LOAD_SEQUENCE_LENGTH + 4)
-#define BR_SIZE 8
-#define LOADSTORE_SIZE 4
-#define JUMP_IMM_SIZE 16
-#define JUMP_IMM32_SIZE (MIPS_LOAD_SEQUENCE_LENGTH + 8)
-#define LOAD_CONST_SIZE 8
-#define JUMP_JR_SIZE 8
-
-gpointer
-mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoIMTCheckItem **imt_entries, int count,
- gpointer fail_tramp)
-{
- int i;
- int size = 0;
- guint8 *code, *start, *patch;
-
- for (i = 0; i < count; ++i) {
- MonoIMTCheckItem *item = imt_entries [i];
-
- if (item->is_equals) {
- if (item->check_target_idx) {
- item->chunk_size += LOAD_CONST_SIZE + BR_SIZE + JUMP_JR_SIZE;
- if (item->has_target_code)
- item->chunk_size += LOAD_CONST_SIZE;
- else
- item->chunk_size += LOADSTORE_SIZE;
- } else {
- if (fail_tramp) {
- item->chunk_size += LOAD_CONST_SIZE + BR_SIZE + JUMP_IMM32_SIZE +
- LOADSTORE_SIZE + JUMP_IMM32_SIZE;
- if (!item->has_target_code)
- item->chunk_size += LOADSTORE_SIZE;
- } else {
- item->chunk_size += LOADSTORE_SIZE + JUMP_JR_SIZE;
-#if ENABLE_WRONG_METHOD_CHECK
- item->chunk_size += CMP_SIZE + BR_SIZE + 4;
-#endif
- }
- }
- } else {
- item->chunk_size += CMP_SIZE + BR_SIZE;
- imt_entries [item->check_target_idx]->compare_done = TRUE;
- }
- size += item->chunk_size;
- }
- /* the initial load of the vtable address */
- size += MIPS_LOAD_SEQUENCE_LENGTH;
- if (fail_tramp) {
- code = (guint8 *)mini_alloc_generic_virtual_trampoline (vtable, size);
- } else {
- MonoMemoryManager *mem_manager = m_class_get_mem_manager (vtable->klass);
- code = mono_mem_manager_code_reserve (mem_manager, size);
- }
- start = code;
-
- /* t7 points to the vtable */
- mips_load_const (code, mips_t7, (gsize)(& (vtable->vtable [0])));
-
- for (i = 0; i < count; ++i) {
- MonoIMTCheckItem *item = imt_entries [i];
-
- item->code_target = code;
- if (item->is_equals) {
- if (item->check_target_idx) {
- mips_load_const (code, mips_temp, (gsize)item->key);
- item->jmp_code = code;
- mips_bne (code, mips_temp, MONO_ARCH_IMT_REG, 0);
- mips_nop (code);
- if (item->has_target_code) {
- mips_load_const (code, mips_t9,
- item->value.target_code);
- }
- else {
- mips_lw (code, mips_t9, mips_t7,
- (sizeof (target_mgreg_t) * item->value.vtable_slot));
- }
- mips_jr (code, mips_t9);
- mips_nop (code);
- } else {
- if (fail_tramp) {
- mips_load_const (code, mips_temp, (gsize)item->key);
- patch = code;
- mips_bne (code, mips_temp, MONO_ARCH_IMT_REG, 0);
- mips_nop (code);
- if (item->has_target_code) {
- mips_load_const (code, mips_t9,
- item->value.target_code);
- } else {
- g_assert (vtable);
- mips_load_const (code, mips_at,
- & (vtable->vtable [item->value.vtable_slot]));
- mips_lw (code, mips_t9, mips_at, 0);
- }
- mips_jr (code, mips_t9);
- mips_nop (code);
- mips_patch ((guint32 *)(void *)patch, (guint32)code);
- mips_load_const (code, mips_t9, fail_tramp);
- mips_jr (code, mips_t9);
- mips_nop (code);
- } else {
- /* enable the commented code to assert on wrong method */
-#if ENABLE_WRONG_METHOD_CHECK
- ppc_load (code, ppc_r0, (guint32)item->key);
- ppc_compare_log (code, 0, MONO_ARCH_IMT_REG, ppc_r0);
- patch = code;
- ppc_bc (code, PPC_BR_FALSE, PPC_BR_EQ, 0);
-#endif
- mips_lw (code, mips_t9, mips_t7,
- (sizeof (target_mgreg_t) * item->value.vtable_slot));
- mips_jr (code, mips_t9);
- mips_nop (code);
-
-#if ENABLE_WRONG_METHOD_CHECK
- ppc_patch (patch, code);
- ppc_break (code);
-#endif
- }
- }
- } else {
- mips_load_const (code, mips_temp, (gulong)item->key);
- mips_slt (code, mips_temp, MONO_ARCH_IMT_REG, mips_temp);
-
- item->jmp_code = code;
- mips_beq (code, mips_temp, mips_zero, 0);
- mips_nop (code);
- }
- }
- /* patch the branches to get to the target items */
- for (i = 0; i < count; ++i) {
- MonoIMTCheckItem *item = imt_entries [i];
- if (item->jmp_code && item->check_target_idx) {
- mips_patch ((guint32 *)item->jmp_code,
- (guint32)imt_entries [item->check_target_idx]->code_target);
- }
- }
-
- if (!fail_tramp)
- UnlockedAdd (&mono_stats.imt_trampolines_size, code - start);
- g_assert (code - start <= size);
- mono_arch_flush_icache (start, size);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
-
- mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), NULL);
-
- return start;
-}
-
-MonoMethod*
-mono_arch_find_imt_method (host_mgreg_t *regs, guint8 *code)
-{
- return (MonoMethod*) regs [MONO_ARCH_IMT_REG];
-}
-
-MonoVTable*
-mono_arch_find_static_call_vtable (host_mgreg_t *regs, guint8 *code)
-{
- return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
-}
-
-/* Soft Debug support */
-#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
-
-/*
- * mono_arch_set_breakpoint:
- *
- * See mini-amd64.c for docs.
- */
-void
-mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
-{
- guint8 *code = ip;
- guint32 addr = (guint32)bp_trigger_page;
-
- mips_load_const (code, mips_t9, addr);
- mips_lw (code, mips_t9, mips_t9, 0);
-
- mono_arch_flush_icache (ip, code - ip);
-}
-
-/*
- * mono_arch_clear_breakpoint:
- *
- * See mini-amd64.c for docs.
- */
-void
-mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
-{
- guint8 *code = ip;
-
- mips_nop (code);
- mips_nop (code);
- mips_nop (code);
-
- mono_arch_flush_icache (ip, code - ip);
-}
-
-/*
- * mono_arch_start_single_stepping:
- *
- * See mini-amd64.c for docs.
- */
-void
-mono_arch_start_single_stepping (void)
-{
- mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
-}
-
-/*
- * mono_arch_stop_single_stepping:
- *
- * See mini-amd64.c for docs.
- */
-void
-mono_arch_stop_single_stepping (void)
-{
- mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
-}
-
-/*
- * mono_arch_is_single_step_event:
- *
- * See mini-amd64.c for docs.
- */
-gboolean
-mono_arch_is_single_step_event (void *info, void *sigctx)
-{
- siginfo_t* sinfo = (siginfo_t*) info;
- /* Sometimes the address is off by 4 */
- if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
- return TRUE;
- else
- return FALSE;
-}
-
-/*
- * mono_arch_is_breakpoint_event:
- *
- * See mini-amd64.c for docs.
- */
-gboolean
-mono_arch_is_breakpoint_event (void *info, void *sigctx)
-{
- siginfo_t* sinfo = (siginfo_t*) info;
- /* Sometimes the address is off by 4 */
- if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
- return TRUE;
- else
- return FALSE;
-}
-
-/*
- * mono_arch_skip_breakpoint:
- *
- * See mini-amd64.c for docs.
- */
-void
-mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
-{
- MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + 4);
-}
-
-/*
- * mono_arch_skip_single_step:
- *
- * See mini-amd64.c for docs.
- */
-void
-mono_arch_skip_single_step (MonoContext *ctx)
-{
- MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + 4);
-}
-
-/*
- * mono_arch_get_seq_point_info:
- *
- * See mini-amd64.c for docs.
- */
-SeqPointInfo*
-mono_arch_get_seq_point_info (guint8 *code)
-{
- NOT_IMPLEMENTED;
- return NULL;
-}
-
-#endif /* MONO_ARCH_SOFT_DEBUG_SUPPORTED */
-
-gboolean
-mono_arch_opcode_supported (int opcode)
-{
- return FALSE;
-}
-
-gboolean
-mono_arch_tailcall_supported (MonoCompile *cfg, MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig, gboolean virtual_)
-{
- return FALSE;
-}
-
-gpointer
-mono_arch_load_function (MonoJitICallId jit_icall_id)
-{
- return NULL;
-}
-
-GSList*
-mono_arch_get_cie_program (void)
-{
- NOT_IMPLEMENTED;
- return NULL;
-}
+++ /dev/null
-/**
- * \file
- */
-
-#ifndef __MONO_MINI_MIPS_H__
-#define __MONO_MINI_MIPS_H__
-
-#include <glib.h>
-#include <mono/arch/mips/mips-codegen.h>
-#include <mono/utils/mono-context.h>
-
-#if _MIPS_SIM == _ABIO32
-/* o32 fully supported */
-#elif _MIPS_SIM == _ABIN32
-/* n32 under development */
-#warning "MIPS using n32 - under development"
-#else
-/* o64 not supported */
-/* n64 not supported */
-#error "MIPS unsupported ABI"
-#endif
-
-
-#define MONO_ARCH_CPU_SPEC mono_mips_desc
-
-#define MONO_MAX_IREGS 32
-#define MONO_MAX_FREGS 32
-
-#define MONO_SAVED_GREGS 32
-#define MONO_SAVED_FREGS 32
-
-
-#if SIZEOF_REGISTER == 4
-#define IREG_SIZE 4
-#define FREG_SIZE 4
-typedef gfloat mips_freg;
-
-#elif SIZEOF_REGISTER == 8
-
-#define IREG_SIZE 8
-#define FREG_SIZE 8
-typedef gdouble mips_freg;
-
-#else
-#error Unknown REGISTER_SIZE
-#endif
-
-/*
- * at and t0 used internally
- * v0, v1 aren't here for clarity reasons
- * a0, a1, a2, a3 are for arguments
- * Use t9 for indirect calls to match the ABI
- */
-
-#define MIPS_V_REGS ((1 << mips_v0) | \
- (1 << mips_v1))
-#if _MIPS_SIM == _ABIO32
-#define MIPS_T_REGS ((1 << mips_t0) | \
- (1 << mips_t1) | \
- (1 << mips_t2) | \
- (1 << mips_t3) | \
- (1 << mips_t4) | \
- (1 << mips_t5) | \
- (1 << mips_t6) | \
- (1 << mips_t7))
-#elif _MIPS_SIM == _ABIN32
-#define MIPS_T_REGS ((1 << mips_t0) | \
- (1 << mips_t1) | \
- (1 << mips_t2) | \
- (1 << mips_t3))
-#endif
-
-
-#define MIPS_S_REGS ((1 << mips_s0) | \
- (1 << mips_s1) | \
- (1 << mips_s2) | \
- (1 << mips_s3) | \
- (1 << mips_s4) | \
- (1 << mips_s5) | \
- (1 << mips_s6) | \
- (1 << mips_s7) | \
- (1 << mips_fp))
-#if _MIPS_SIM == _ABIO32
-#define MIPS_A_REGS ((1 << mips_a0) | \
- (1 << mips_a1) | \
- (1 << mips_a2) | \
- (1 << mips_a3))
-#elif _MIPS_SIM == _ABIN32
-#define MIPS_A_REGS ((1 << mips_a0) | \
- (1 << mips_a1) | \
- (1 << mips_a2) | \
- (1 << mips_a3) | \
- (1 << mips_a4) | \
- (1 << mips_a5) | \
- (1 << mips_a6) | \
- (1 << mips_a7))
-#endif
-
-#define mips_temp mips_t8
-
-#define MONO_ARCH_CALLEE_REGS (MIPS_T_REGS | MIPS_V_REGS | MIPS_A_REGS)
-#define MONO_ARCH_CALLEE_SAVED_REGS MIPS_S_REGS
-#define MIPS_ARG_REGS MIPS_A_REGS
-
-#if 0
-#define MIPS_FP_PAIR(reg) ((1 << (reg)) | (1 << ((reg)+1)))
-#else
-/* Only put the even regs in */
-#define MIPS_FP_PAIR(reg) (1 << (reg))
-#endif
-
-#if _MIPS_SIM == _ABIO32
-#define MONO_ARCH_CALLEE_FREGS (MIPS_FP_PAIR(mips_f0) | \
- MIPS_FP_PAIR(mips_f2) | \
- MIPS_FP_PAIR(mips_f4) | \
- MIPS_FP_PAIR(mips_f6) | \
- MIPS_FP_PAIR(mips_f8) | \
- MIPS_FP_PAIR(mips_f10) | \
- MIPS_FP_PAIR(mips_f12) | \
- MIPS_FP_PAIR(mips_f14) | \
- MIPS_FP_PAIR(mips_f16) | \
- MIPS_FP_PAIR(mips_f18))
-
-#define MONO_ARCH_CALLEE_SAVED_FREGS (MIPS_FP_PAIR(mips_f20) | \
- MIPS_FP_PAIR(mips_f22) | \
- MIPS_FP_PAIR(mips_f24) | \
- MIPS_FP_PAIR(mips_f26) | \
- MIPS_FP_PAIR(mips_f28) | \
- MIPS_FP_PAIR(mips_f30))
-#elif _MIPS_SIM == _ABIN32
-#define MONO_ARCH_CALLEE_FREGS (MIPS_FP_PAIR(mips_f0) | \
- MIPS_FP_PAIR(mips_f1) | \
- MIPS_FP_PAIR(mips_f2) | \
- MIPS_FP_PAIR(mips_f3) | \
- MIPS_FP_PAIR(mips_f4) | \
- MIPS_FP_PAIR(mips_f5) | \
- MIPS_FP_PAIR(mips_f6) | \
- MIPS_FP_PAIR(mips_f7) | \
- MIPS_FP_PAIR(mips_f8) | \
- MIPS_FP_PAIR(mips_f9) | \
- MIPS_FP_PAIR(mips_f10) | \
- MIPS_FP_PAIR(mips_f11) | \
- MIPS_FP_PAIR(mips_f12) | \
- MIPS_FP_PAIR(mips_f13) | \
- MIPS_FP_PAIR(mips_f14) | \
- MIPS_FP_PAIR(mips_f15) | \
- MIPS_FP_PAIR(mips_f16) | \
- MIPS_FP_PAIR(mips_f17) | \
- MIPS_FP_PAIR(mips_f18) | \
- MIPS_FP_PAIR(mips_f19))
-
-#define MONO_ARCH_CALLEE_SAVED_FREGS (MIPS_FP_PAIR(mips_f20) | \
- MIPS_FP_PAIR(mips_f21) | \
- MIPS_FP_PAIR(mips_f22) | \
- MIPS_FP_PAIR(mips_f23) | \
- MIPS_FP_PAIR(mips_f24) | \
- MIPS_FP_PAIR(mips_f25) | \
- MIPS_FP_PAIR(mips_f26) | \
- MIPS_FP_PAIR(mips_f27) | \
- MIPS_FP_PAIR(mips_f28) | \
- MIPS_FP_PAIR(mips_f29) | \
- MIPS_FP_PAIR(mips_f30) | \
- MIPS_FP_PAIR(mips_f31))
-#endif
-
-#define mips_ftemp mips_f18
-
-#define MONO_ARCH_USE_FPSTACK FALSE
-
-/* Parameters used by the register allocator */
-
-/* On Mips, for regpairs, the lower-numbered reg is most significant
- * This is true in both big and little endian
- */
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-#define RET_REG1 mips_v0
-#define RET_REG2 mips_v1
-#else
-#define RET_REG1 mips_v1
-#define RET_REG2 mips_v0
-#endif
-
-#define MONO_ARCH_INST_SREG2_MASK(ins) (0)
-#define MONO_ARCH_INST_IS_REGPAIR(desc) ((desc) == 'V' || (desc) == 'l')
-#define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (((desc) == 'l') ? ((hreg1) + 1) : (((desc) == 'V') ? RET_REG2 : -1))
-#define MONO_ARCH_INST_IS_FLOAT(desc) ((desc == 'f') || (desc == 'g'))
-
-// This define is called to get specific dest register as defined
-// by md file (letter after "dest"). Overwise return -1
-
-#define MONO_ARCH_INST_FIXED_REG(desc) (((desc) == '0') ? mips_zero : (((desc) == 'a') ? mips_at : ((((desc) == 'v')) ? mips_v0 : (((desc) == 'V') ? RET_REG1 : (((desc) == 'g') ? mips_f0 : -1)))))
-
-#define MONO_ARCH_FRAME_ALIGNMENT 8
-
-/* fixme: align to 16byte instead of 32byte (we align to 32byte to get
- * reproduceable results for benchmarks */
-#define MONO_ARCH_CODE_ALIGNMENT 32
-
-void mips_patch (guint32 *code, guint32 target);
-
-#define MIPS_LMF_MAGIC1 0xa5a5a5a5
-#define MIPS_LMF_MAGIC2 0xc3c3c3c3
-
-/* Registers saved in lmf->iregs */
-#define MIPS_LMF_IREGMASK (0xffffffff & ~((1 << mips_zero) | (1 << mips_at) | MONO_ARCH_CALLEE_REGS))
-
-struct MonoLMF {
- gpointer previous_lmf;
- gpointer lmf_addr;
- MonoMethod *method;
- gpointer eip;
- host_mgreg_t iregs [MONO_SAVED_GREGS];
- mips_freg fregs [MONO_SAVED_FREGS];
- gulong magic;
-};
-
-typedef struct MonoCompileArch {
- CallInfo *cinfo;
- guint iregs_offset;
- guint lmf_offset;
- guint local_alloc_offset;
- guint spillvar_offset;
- guint spillvar_offset_float;
- guint tracing_offset;
- guint long_branch;
- gboolean omit_fp;
- gboolean omit_fp_computed;
-} MonoCompileArch;
-
-#if SIZEOF_REGISTER == 4
-#define MONO_ARCH_EMULATE_FCONV_TO_I8 1
-#define MONO_ARCH_EMULATE_LCONV_TO_R8 1
-#define MONO_ARCH_EMULATE_LCONV_TO_R4 1
-#define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
-#define MONO_ARCH_EMULATE_FREM 1
-#endif
-
-#define MONO_ARCH_EMULATE_FCONV_TO_U8 1
-
-/*
- * mips backend misses some instructions that enable emitting of optimal
- * code on other targets and, additionally, the register allocator gets
- * confused by this optimization, failing to allocate all hw regs.
- */
-#if SIZEOF_REGISTER == 4
-#define MONO_ARCH_NO_DIV_WITH_MUL
-#endif
-
-#if SIZEOF_REGISTER == 8
-#define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
-#endif
-
-#define MIPS_RET_ADDR_OFFSET (-sizeof (target_mgreg_t))
-#define MIPS_FP_ADDR_OFFSET (-8)
-#define MIPS_STACK_ALIGNMENT 16
-#define MIPS_STACK_PARAM_OFFSET 16 /* from sp to first parameter */
-#define MIPS_MINIMAL_STACK_SIZE (8 * sizeof (target_mgreg_t))
-#define MIPS_EXTRA_STACK_SIZE 16 /* from last parameter to top of frame */
-
-#if _MIPS_SIM == _ABIO32
-#define MIPS_FIRST_ARG_REG mips_a0
-#define MIPS_LAST_ARG_REG mips_a3
-#define MIPS_FIRST_FPARG_REG mips_f12
-#define MIPS_LAST_FPARG_REG mips_f14
-#elif _MIPS_SIM == _ABIN32
-#define MIPS_FIRST_ARG_REG mips_a0
-#define MIPS_LAST_ARG_REG mips_t3
-#define MIPS_FIRST_FPARG_REG mips_f12
-#define MIPS_LAST_FPARG_REG mips_f19
-#endif
-
-#define MONO_ARCH_IMT_REG mips_t0
-
-#define MONO_ARCH_VTABLE_REG mips_a0
-#define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG
-
-#define MONO_ARCH_HAVE_DECOMPOSE_OPTS 1
-#define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
-
-#define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
-#define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
-#define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
-#define MONO_ARCH_GSHARED_SUPPORTED 1
-
-/* set the next to 0 once inssel-mips.brg is updated */
-#define MIPS_PASS_STRUCTS_BY_VALUE 1
-
-#define MONO_ARCH_USE_SIGACTION
-#define MONO_ARCH_NEED_DIV_CHECK 1
-#define MONO_ARCH_NO_IOV_CHECK 1
-
-// Does the ABI have a volatile non-parameter register, so tailcall
-// can pass context to generics or interfaces?
-#define MONO_ARCH_HAVE_VOLATILE_NON_PARAM_REGISTER 0 // FIXME?
-
-#define MIPS_NUM_REG_ARGS (MIPS_LAST_ARG_REG-MIPS_FIRST_ARG_REG+1)
-#define MIPS_NUM_REG_FPARGS (MIPS_LAST_FPARG_REG-MIPS_FIRST_FPARG_REG+1)
-
-typedef struct {
- unsigned long zero;
- unsigned long at; /* assembler temp */
- unsigned long v0; /* return values */
- unsigned long v1;
- unsigned long a0; /* 4 - func arguments */
- unsigned long a1;
- unsigned long a2;
- unsigned long a3;
- unsigned long t0; /* 8 temporaries */
- unsigned long t1;
- unsigned long t2;
- unsigned long t3;
- unsigned long t4;
- unsigned long t5;
- unsigned long t6;
- unsigned long t7;
- unsigned long s0; /* 16 calle saved */
- unsigned long s1;
- unsigned long s2;
- unsigned long s3;
- unsigned long s4;
- unsigned long s5;
- unsigned long s6;
- unsigned long s7;
- unsigned long t8; /* 24 temps */
- unsigned long t9; /* 25 temp / pic call-through register */
- unsigned long k0; /* 26 kernel-reserved */
- unsigned long k1;
- unsigned long gp; /* 28 */
- unsigned long sp; /* stack pointer */
- unsigned long fp; /* frame pointer */
- unsigned long ra; /* return address */
-} MonoMipsStackFrame;
-
-#define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do { \
- MONO_CONTEXT_SET_BP ((ctx), __builtin_frame_address (0)); \
- MONO_CONTEXT_SET_SP ((ctx), __builtin_frame_address (0)); \
- MONO_CONTEXT_SET_IP ((ctx), (func)); \
- } while (0)
-
-#define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
-
-/* re-attaches with gdb - sometimes causes executable to hang */
-#undef HAVE_BACKTRACE_SYMBOLS
-
-#undef DEBUG_EXCEPTIONS
-
-#define MONO_EMIT_NEW_MIPS_COND_EXC(cfg,cond,sr1,sr2,name) do { \
- MonoInst *inst; \
- MONO_INST_NEW ((cfg), (inst), cond); \
- inst->inst_p1 = (char*)name; \
- inst->sreg1 = sr1; \
- inst->sreg2 = sr2; \
- MONO_ADD_INS ((cfg)->cbb, inst); \
- } while (0)
-
-#ifndef MONO_EMIT_NEW_COMPARE_EXC
-#define MONO_EMIT_NEW_COMPARE_EXC(cfg, cmp_op, sreg1, sreg2, exc) do { \
- switch (OP_MIPS_COND_EXC_##cmp_op) { \
- case OP_MIPS_COND_EXC_EQ: \
- MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, sreg1, sreg2, exc); \
- break; \
- case OP_MIPS_COND_EXC_NE_UN: \
- MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, sreg1, sreg2, exc); \
- break; \
- case OP_MIPS_COND_EXC_GT: \
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
- MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
- break; \
- case OP_MIPS_COND_EXC_GT_UN: \
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
- MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
- break; \
- case OP_MIPS_COND_EXC_LE: \
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
- MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
- break; \
- case OP_MIPS_COND_EXC_LE_UN: \
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
- MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
- break; \
- case OP_MIPS_COND_EXC_LT: \
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
- MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
- break; \
- case OP_MIPS_COND_EXC_LT_UN: \
- MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
- MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
- break; \
- default: \
- g_warning ("unknown comparison %s\n", #cmp_op); \
- g_assert_not_reached (); \
- } \
- } while (0)
-#endif
-
-#ifndef MONO_EMIT_NEW_COMPARE_IMM_EXC
-#define MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
- guint32 cmp_reg; \
- if (!(imm)) { \
- cmp_reg = mips_zero; \
- } \
- else { \
- cmp_reg = mips_at; \
- MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
- } \
- MONO_EMIT_NEW_COMPARE_EXC (cfg, cmp_op, sreg1, cmp_reg, exc); \
- } while (0)
-#endif
-
-#ifndef MONO_EMIT_NEW_ICOMPARE_IMM_EXC
-#define MONO_EMIT_NEW_ICOMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
- MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc); \
- } while (0)
-#endif
-
-typedef struct {
- gint8 reg;
- gint8 size;
- int vtsize;
- int offset;
-} MonoMIPSArgInfo;
-
-guint8 *mips_emit_load_const (guint8 *code, int dreg, target_mgreg_t v);
-
-#endif /* __MONO_MINI_MIPS_H__ */
MINI_OP(OP_ARM_SETFREG_R4, "arm_setfreg_r4", FREG, FREG, NONE)
#endif
-#if defined(TARGET_SPARC)
-MINI_OP(OP_SPARC_BRZ, "sparc_brz", NONE, NONE, NONE)
-MINI_OP(OP_SPARC_BRLEZ, "sparc_brlez", NONE, NONE, NONE)
-MINI_OP(OP_SPARC_BRLZ, "sparc_brlz", NONE, NONE, NONE)
-MINI_OP(OP_SPARC_BRNZ, "sparc_brnz", NONE, NONE, NONE)
-MINI_OP(OP_SPARC_BRGZ, "sparc_brgz", NONE, NONE, NONE)
-MINI_OP(OP_SPARC_BRGEZ, "sparc_brgez", NONE, NONE, NONE)
-MINI_OP(OP_SPARC_COND_EXC_EQZ, "sparc_cond_exc_eqz", NONE, NONE, NONE)
-MINI_OP(OP_SPARC_COND_EXC_GEZ, "sparc_cond_exc_gez", NONE, NONE, NONE)
-MINI_OP(OP_SPARC_COND_EXC_GTZ, "sparc_cond_exc_gtz", NONE, NONE, NONE)
-MINI_OP(OP_SPARC_COND_EXC_LEZ, "sparc_cond_exc_lez", NONE, NONE, NONE)
-MINI_OP(OP_SPARC_COND_EXC_LTZ, "sparc_cond_exc_ltz", NONE, NONE, NONE)
-MINI_OP(OP_SPARC_COND_EXC_NEZ, "sparc_cond_exc_nez", NONE, NONE, NONE)
-#endif
-
#if defined(TARGET_S390X)
MINI_OP(OP_S390_LOADARG, "s390_loadarg", NONE, NONE, NONE)
MINI_OP(OP_S390_ARGREG, "s390_argreg", NONE, NONE, NONE)
MINI_OP(OP_S390_CLGIJ, "s390_cgij_un", LREG, NONE, NONE)
#endif
-#if defined(TARGET_MIPS)
-MINI_OP(OP_MIPS_BEQ, "mips_beq", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_BGEZ, "mips_bgez", NONE, IREG, NONE)
-MINI_OP(OP_MIPS_BGTZ, "mips_bgtz", NONE, IREG, NONE)
-MINI_OP(OP_MIPS_BLEZ, "mips_blez", NONE, IREG, NONE)
-MINI_OP(OP_MIPS_BLTZ, "mips_bltz", NONE, IREG, NONE)
-MINI_OP(OP_MIPS_BNE, "mips_bne", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_CVTSD, "mips_cvtsd", FREG, FREG, NONE)
-MINI_OP(OP_MIPS_FBEQ, "mips_fbeq", NONE, FREG, FREG)
-MINI_OP(OP_MIPS_FBGE, "mips_fbge", NONE, FREG, FREG)
-MINI_OP(OP_MIPS_FBGE_UN, "mips_fbge_un", NONE, FREG, FREG)
-MINI_OP(OP_MIPS_FBGT, "mips_fbgt", NONE, FREG, FREG)
-MINI_OP(OP_MIPS_FBGT_UN, "mips_fbgt_un", NONE, FREG, FREG)
-MINI_OP(OP_MIPS_FBLE, "mips_fble", NONE, FREG, FREG)
-MINI_OP(OP_MIPS_FBLE_UN, "mips_fble_un", NONE, FREG, FREG)
-MINI_OP(OP_MIPS_FBLT, "mips_fblt", NONE, FREG, FREG)
-MINI_OP(OP_MIPS_FBLT_UN, "mips_fblt_un", NONE, FREG, FREG)
-MINI_OP(OP_MIPS_FBNE, "mips_fbne", NONE, FREG, FREG)
-MINI_OP(OP_MIPS_FBFALSE, "mips_fbfalse", NONE, NONE, NONE)
-MINI_OP(OP_MIPS_FBTRUE, "mips_fbtrue", NONE, NONE, NONE)
-MINI_OP(OP_MIPS_LWC1, "mips_lwc1", NONE, NONE, NONE)
-MINI_OP(OP_MIPS_MTC1S, "mips_mtc1_s", FREG, IREG, NONE)
-MINI_OP(OP_MIPS_MTC1S_2, "mips_mtc1_s2", FREG, IREG, IREG)
-MINI_OP(OP_MIPS_MFC1S, "mips_mfc1_s", IREG, FREG, NONE)
-MINI_OP(OP_MIPS_MTC1D, "mips_mtc1_d", FREG, IREG, NONE)
-MINI_OP(OP_MIPS_MFC1D, "mips_mfc1_d", IREG, FREG, NONE)
-MINI_OP(OP_MIPS_NOP, "mips_nop", NONE, NONE, NONE)
-MINI_OP(OP_MIPS_SLTI, "mips_slti", IREG, IREG, NONE)
-MINI_OP(OP_MIPS_SLT, "mips_slt", IREG, IREG, IREG)
-MINI_OP(OP_MIPS_SLTIU, "mips_sltiu", IREG, IREG, NONE)
-MINI_OP(OP_MIPS_SLTU, "mips_sltu", IREG, IREG, IREG)
-
-MINI_OP(OP_MIPS_COND_EXC_EQ, "mips_cond_exc_eq", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_GE, "mips_cond_exc_ge", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_GT, "mips_cond_exc_gt", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_LE, "mips_cond_exc_le", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_LT, "mips_cond_exc_lt", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_NE_UN, "mips_cond_exc_ne_un", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_GE_UN, "mips_cond_exc_ge_un", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_GT_UN, "mips_cond_exc_gt_un", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_LE_UN, "mips_cond_exc_le_un", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_LT_UN, "mips_cond_exc_lt_un", NONE, IREG, IREG)
-
-MINI_OP(OP_MIPS_COND_EXC_OV, "mips_cond_exc_ov", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_NO, "mips_cond_exc_no", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_C, "mips_cond_exc_c", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_NC, "mips_cond_exc_nc", NONE, IREG, IREG)
-
-MINI_OP(OP_MIPS_COND_EXC_IEQ, "mips_cond_exc_ieq", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_IGE, "mips_cond_exc_ige", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_IGT, "mips_cond_exc_igt", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_ILE, "mips_cond_exc_ile", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_ILT, "mips_cond_exc_ilt", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_INE_UN, "mips_cond_exc_ine_un", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_IGE_UN, "mips_cond_exc_ige_un", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_IGT_UN, "mips_cond_exc_igt_un", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_ILE_UN, "mips_cond_exc_ile_un", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_ILT_UN, "mips_cond_exc_ilt_un", NONE, IREG, IREG)
-
-MINI_OP(OP_MIPS_COND_EXC_IOV, "mips_cond_exc_iov", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_INO, "mips_cond_exc_ino", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_IC, "mips_cond_exc_ic", NONE, IREG, IREG)
-MINI_OP(OP_MIPS_COND_EXC_INC, "mips_cond_exc_inc", NONE, IREG, IREG)
-
-#endif
-
#if defined(TARGET_ARM64)
/* Branch if sreg1 == 0 */
MINI_OP(OP_ARM64_CBZW, "arm64_cbzw", NONE, IREG, NONE)
ELF_MACHINE = EM_S390,
#elif HOST_RISCV
ELF_MACHINE = EM_RISCV,
-#elif HOST_MIPS
- ELF_MACHINE = EM_MIPS,
#endif
JIT_CODE_LOAD = 0
};
+++ /dev/null
-/**
- * \file
- * Sparc backend for the Mono code generator
- *
- * Authors:
- * Paolo Molaro (lupus@ximian.com)
- * Dietmar Maurer (dietmar@ximian.com)
- *
- * Modified for SPARC:
- * Christopher Taylor (ct@gentoo.org)
- * Mark Crichton (crichton@gimp.org)
- * Zoltan Varga (vargaz@freemail.hu)
- *
- * (C) 2003 Ximian, Inc.
- */
-#include "mini.h"
-#include <string.h>
-#include <pthread.h>
-#include <unistd.h>
-
-#ifndef __linux__
-#include <thread.h>
-#endif
-
-#include <unistd.h>
-#include <sys/mman.h>
-
-#include <mono/metadata/appdomain.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/tokentype.h>
-#include <mono/utils/mono-math.h>
-#include <mono/utils/mono-hwcap.h>
-#include <mono/utils/unlocked.h>
-
-#include "mini-sparc.h"
-#include "trace.h"
-#include "cpu-sparc.h"
-#include "jit-icalls.h"
-#include "ir-emit.h"
-#include "mono/utils/mono-tls-inline.h"
-
-/*
- * Sparc V9 means two things:
- * - the instruction set
- * - the ABI
- *
- * V9 instructions are only usable if the underlying processor is 64 bit. Most Sparc
- * processors in use are 64 bit processors. The V9 ABI is only usable if the
- * mono executable is a 64 bit executable. So it would make sense to use the 64 bit
- * instructions without using the 64 bit ABI.
- */
-
-/*
- * Register usage:
- * - %i0..%i<n> hold the incoming arguments, these are never written by JITted
- * code. Unused input registers are used for global register allocation.
- * - %o0..%o5 and %l7 is used for local register allocation and passing arguments
- * - %l0..%l6 is used for global register allocation
- * - %o7 and %g1 is used as scratch registers in opcodes
- * - all floating point registers are used for local register allocation except %f0.
- * Only double precision registers are used.
- * In 64 bit mode:
- * - fp registers %d0..%d30 are used for parameter passing, and %d32..%d62 are
- * used for local allocation.
- */
-
-/*
- * Alignment:
- * - doubles and longs must be stored in dword aligned locations
- */
-
-/*
- * The following things are not implemented or do not work:
- * - some fp arithmetic corner cases
- * The following tests in mono/mini are expected to fail:
- * - test_0_simple_double_casts
- * This test casts (guint64)-1 to double and then back to guint64 again.
- * Under x86, it returns 0, while under sparc it returns -1.
- *
- * In addition to this, the runtime requires the trunc function, or its
- * solaris counterpart, aintl, to do some double->int conversions. If this
- * function is not available, it is emulated somewhat, but the results can be
- * strange.
- */
-
-/*
- * SPARCV9 FIXME:
- * - optimize sparc_set according to the memory model
- * - when non-AOT compiling, compute patch targets immediately so we don't
- * have to emit the 6 byte template.
- * - varags
- * - struct arguments/returns
- */
-
-/*
- * SPARCV9 ISSUES:
- * - sparc_call_simple can't be used in a lot of places since the displacement
- * might not fit into an imm30.
- * - g1 can't be used in a lot of places since it is used as a scratch reg in
- * sparc_set.
- * - sparc_f0 can't be used as a scratch register on V9
- * - the %d34..%d62 fp registers are encoded as: %dx = %f(x - 32 + 1), ie.
- * %d36 = %f5.
- * - ldind.i4/u4 needs to sign extend/clear out upper word -> slows things down
- * - ins->dreg can't be used as a scatch register in r4 opcodes since it might
- * be a double precision register which has no single precision part.
- * - passing/returning structs is hard to implement, because:
- * - the spec is very hard to understand
- * - it requires knowledge about the fields of structure, needs to handle
- * nested structures etc.
- */
-
-/*
- * Possible optimizations:
- * - delay slot scheduling
- * - allocate large constants to registers
- * - add more mul/div/rem optimizations
- */
-
-#ifndef __linux__
-#define MONO_SPARC_THR_TLS 1
-#endif
-
-/*
- * There was a 64 bit bug in glib-2.2: g_bit_nth_msf (0, -1) would return 32,
- * causing infinite loops in dominator computation. So glib-2.4 is required.
- */
-#ifdef SPARCV9
-#if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 4
-#error "glib 2.4 or later is required for 64 bit mode."
-#endif
-#endif
-
-#define SIGNAL_STACK_SIZE (64 * 1024)
-
-#define STACK_BIAS MONO_SPARC_STACK_BIAS
-
-#ifdef SPARCV9
-
-/* %g1 is used by sparc_set */
-#define GP_SCRATCH_REG sparc_g4
-/* %f0 is used for parameter passing */
-#define FP_SCRATCH_REG sparc_f30
-#define ARGS_OFFSET (STACK_BIAS + 128)
-
-#else
-
-#define FP_SCRATCH_REG sparc_f0
-#define ARGS_OFFSET 68
-#define GP_SCRATCH_REG sparc_g1
-
-#endif
-
-/* Whenever this is a 64bit executable */
-#if SPARCV9
-static gboolean v64 = TRUE;
-#else
-static gboolean v64 = FALSE;
-#endif
-
-static gpointer mono_arch_get_lmf_addr (void);
-
-const char*
-mono_arch_regname (int reg) {
- static const char * rnames[] = {
- "sparc_g0", "sparc_g1", "sparc_g2", "sparc_g3", "sparc_g4",
- "sparc_g5", "sparc_g6", "sparc_g7", "sparc_o0", "sparc_o1",
- "sparc_o2", "sparc_o3", "sparc_o4", "sparc_o5", "sparc_sp",
- "sparc_call", "sparc_l0", "sparc_l1", "sparc_l2", "sparc_l3",
- "sparc_l4", "sparc_l5", "sparc_l6", "sparc_l7", "sparc_i0",
- "sparc_i1", "sparc_i2", "sparc_i3", "sparc_i4", "sparc_i5",
- "sparc_fp", "sparc_retadr"
- };
- if (reg >= 0 && reg < 32)
- return rnames [reg];
- return "unknown";
-}
-
-const char*
-mono_arch_fregname (int reg) {
- static const char *rnames [] = {
- "sparc_f0", "sparc_f1", "sparc_f2", "sparc_f3", "sparc_f4",
- "sparc_f5", "sparc_f6", "sparc_f7", "sparc_f8", "sparc_f9",
- "sparc_f10", "sparc_f11", "sparc_f12", "sparc_f13", "sparc_f14",
- "sparc_f15", "sparc_f16", "sparc_f17", "sparc_f18", "sparc_f19",
- "sparc_f20", "sparc_f21", "sparc_f22", "sparc_f23", "sparc_f24",
- "sparc_f25", "sparc_f26", "sparc_f27", "sparc_f28", "sparc_f29",
- "sparc_f30", "sparc_f31"
- };
-
- if (reg >= 0 && reg < 32)
- return rnames [reg];
- else
- return "unknown";
-}
-
-/*
- * Initialize the cpu to execute managed code.
- */
-void
-mono_arch_cpu_init (void)
-{
-}
-
-/*
- * Initialize architecture specific code.
- */
-void
-mono_arch_init (void)
-{
-}
-
-/*
- * Cleanup architecture specific code.
- */
-void
-mono_arch_cleanup (void)
-{
-}
-
-gboolean
-mono_arch_have_fast_tls (void)
-{
- return FALSE;
-}
-
-/*
- * This function returns the optimizations supported on this cpu.
- */
-guint32
-mono_arch_cpu_optimizations (guint32 *exclude_mask)
-{
- guint32 opts = 0;
-
- *exclude_mask = 0;
-
- /*
- * On some processors, the cmov instructions are even slower than the
- * normal ones...
- */
- if (mono_hwcap_sparc_is_v9)
- opts |= MONO_OPT_CMOV | MONO_OPT_FCMOV;
- else
- *exclude_mask |= MONO_OPT_CMOV | MONO_OPT_FCMOV;
-
- return opts;
-}
-
-#ifdef __GNUC__
-#define flushi(addr) __asm__ __volatile__ ("iflush %0"::"r"(addr):"memory")
-#else /* assume Sun's compiler */
-static void flushi(void *addr)
-{
- asm("flush %i0");
-}
-#endif
-
-#ifndef __linux__
-void sync_instruction_memory(caddr_t addr, int len);
-#endif
-
-void
-mono_arch_flush_icache (guint8 *code, gint size)
-{
-#ifndef __linux__
- /* Hopefully this is optimized based on the actual CPU */
- sync_instruction_memory (code, size);
-#else
- gulong start = (gulong) code;
- gulong end = start + size;
- gulong align;
-
- /* Sparcv9 chips only need flushes on 32 byte
- * cacheline boundaries.
- *
- * Sparcv8 needs a flush every 8 bytes.
- */
- align = (mono_hwcap_sparc_is_v9 ? 32 : 8);
-
- start &= ~(align - 1);
- end = (end + (align - 1)) & ~(align - 1);
-
- while (start < end) {
-#ifdef __GNUC__
- __asm__ __volatile__ ("iflush %0"::"r"(start));
-#else
- flushi (start);
-#endif
- start += align;
- }
-#endif
-}
-
-/*
- * mono_sparc_flushw:
- *
- * Flush all register windows to memory. Every register window is saved to
- * a 16 word area on the stack pointed to by its %sp register.
- */
-void
-mono_sparc_flushw (void)
-{
- static guint32 start [64];
- static int inited = 0;
- guint32 *code;
- static void (*flushw) (void);
-
- if (!inited) {
- code = start;
-
- sparc_save_imm (code, sparc_sp, -160, sparc_sp);
- sparc_flushw (code);
- sparc_ret (code);
- sparc_restore_simple (code);
-
- g_assert ((code - start) < 64);
-
- mono_arch_flush_icache ((guint8*)start, (guint8*)code - (guint8*)start);
-
- flushw = (gpointer)start;
-
- inited = 1;
- }
-
- flushw ();
-}
-
-void
-mono_arch_flush_register_windows (void)
-{
- mono_sparc_flushw ();
-}
-
-gboolean
-mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm)
-{
- return sparc_is_imm13 (imm);
-}
-
-gboolean
-mono_sparc_is_v9 (void) {
- return mono_hwcap_sparc_is_v9;
-}
-
-gboolean
-mono_sparc_is_sparc64 (void) {
- return v64;
-}
-
-typedef enum {
- ArgInIReg,
- ArgInIRegPair,
- ArgInSplitRegStack,
- ArgInFReg,
- ArgInFRegPair,
- ArgOnStack,
- ArgOnStackPair,
- ArgInFloatReg, /* V9 only */
- ArgInDoubleReg /* V9 only */
-} ArgStorage;
-
-typedef struct {
- gint16 offset;
- /* This needs to be offset by %i0 or %o0 depending on caller/callee */
- gint8 reg;
- ArgStorage storage;
- guint32 vt_offset; /* for valuetypes */
-} ArgInfo;
-
-struct CallInfo {
- int nargs;
- guint32 stack_usage;
- guint32 reg_usage;
- ArgInfo ret;
- ArgInfo sig_cookie;
- ArgInfo args [1];
-};
-
-#define DEBUG(a)
-
-/* %o0..%o5 */
-#define PARAM_REGS 6
-
-static void inline
-add_general (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo, gboolean pair)
-{
- ainfo->offset = *stack_size;
-
- if (!pair) {
- if (*gr >= PARAM_REGS) {
- ainfo->storage = ArgOnStack;
- }
- else {
- ainfo->storage = ArgInIReg;
- ainfo->reg = *gr;
- (*gr) ++;
- }
-
- /* Allways reserve stack space for parameters passed in registers */
- (*stack_size) += sizeof (target_mgreg_t);
- }
- else {
- if (*gr < PARAM_REGS - 1) {
- /* A pair of registers */
- ainfo->storage = ArgInIRegPair;
- ainfo->reg = *gr;
- (*gr) += 2;
- }
- else if (*gr >= PARAM_REGS) {
- /* A pair of stack locations */
- ainfo->storage = ArgOnStackPair;
- }
- else {
- ainfo->storage = ArgInSplitRegStack;
- ainfo->reg = *gr;
- (*gr) ++;
- }
-
- (*stack_size) += 2 * sizeof (target_mgreg_t);
- }
-}
-
-#ifdef SPARCV9
-
-#define FLOAT_PARAM_REGS 32
-
-static void inline
-add_float (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo, gboolean single)
-{
- ainfo->offset = *stack_size;
-
- if (single) {
- if (*gr >= FLOAT_PARAM_REGS) {
- ainfo->storage = ArgOnStack;
- }
- else {
- /* A single is passed in an even numbered fp register */
- ainfo->storage = ArgInFloatReg;
- ainfo->reg = *gr + 1;
- (*gr) += 2;
- }
- }
- else {
- if (*gr < FLOAT_PARAM_REGS) {
- /* A double register */
- ainfo->storage = ArgInDoubleReg;
- ainfo->reg = *gr;
- (*gr) += 2;
- }
- else {
- ainfo->storage = ArgOnStack;
- }
- }
-
- (*stack_size) += sizeof (target_mgreg_t);
-}
-
-#endif
-
-/*
- * get_call_info:
- *
- * Obtain information about a call according to the calling convention.
- * For V8, see the "System V ABI, Sparc Processor Supplement" Sparc V8 version
- * document for more information.
- * For V9, see the "Low Level System Information (64-bit psABI)" chapter in
- * the 'Sparc Compliance Definition 2.4' document.
- */
-static CallInfo*
-get_call_info (MonoCompile *cfg, MonoMethodSignature *sig, gboolean is_pinvoke)
-{
- guint32 i, gr, fr;
- int n = sig->hasthis + sig->param_count;
- guint32 stack_size = 0;
- CallInfo *cinfo;
- MonoType *ret_type;
-
- cinfo = g_malloc0 (sizeof (CallInfo) + (sizeof (ArgInfo) * n));
-
- gr = 0;
- fr = 0;
-
-#ifdef SPARCV9
- if (MONO_TYPE_ISSTRUCT ((sig->ret))) {
- /* The address of the return value is passed in %o0 */
- add_general (&gr, &stack_size, &cinfo->ret, FALSE);
- cinfo->ret.reg += sparc_i0;
- /* FIXME: Pass this after this as on other platforms */
- NOT_IMPLEMENTED;
- }
-#endif
-
- /* this */
- if (sig->hasthis)
- add_general (&gr, &stack_size, cinfo->args + 0, FALSE);
-
- if ((sig->call_convention == MONO_CALL_VARARG) && (n == 0)) {
- gr = PARAM_REGS;
-
- /* Emit the signature cookie just before the implicit arguments */
- add_general (&gr, &stack_size, &cinfo->sig_cookie, FALSE);
- }
-
- for (i = 0; i < sig->param_count; ++i) {
- ArgInfo *ainfo = &cinfo->args [sig->hasthis + i];
- MonoType *ptype;
-
- if ((sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
- gr = PARAM_REGS;
-
- /* Emit the signature cookie just before the implicit arguments */
- add_general (&gr, &stack_size, &cinfo->sig_cookie, FALSE);
- }
-
- DEBUG(printf("param %d: ", i));
- if (m_type_is_byref (sig->params [i])) {
- DEBUG(printf("byref\n"));
-
- add_general (&gr, &stack_size, ainfo, FALSE);
- continue;
- }
- ptype = mini_get_underlying_type (sig->params [i]);
- switch (ptype->type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- add_general (&gr, &stack_size, ainfo, FALSE);
- /* the value is in the ls byte */
- ainfo->offset += sizeof (target_mgreg_t) - 1;
- break;
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
- add_general (&gr, &stack_size, ainfo, FALSE);
- /* the value is in the ls word */
- ainfo->offset += sizeof (target_mgreg_t) - 2;
- break;
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- add_general (&gr, &stack_size, ainfo, FALSE);
- /* the value is in the ls dword */
- ainfo->offset += sizeof (target_mgreg_t) - 4;
- break;
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_PTR:
- case MONO_TYPE_FNPTR:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- add_general (&gr, &stack_size, ainfo, FALSE);
- break;
- case MONO_TYPE_GENERICINST:
- if (!mono_type_generic_inst_is_valuetype (ptype)) {
- add_general (&gr, &stack_size, ainfo, FALSE);
- break;
- }
- /* Fall through */
- case MONO_TYPE_VALUETYPE:
-#ifdef SPARCV9
- if (sig->pinvoke)
- NOT_IMPLEMENTED;
-#endif
- add_general (&gr, &stack_size, ainfo, FALSE);
- break;
- case MONO_TYPE_TYPEDBYREF:
- add_general (&gr, &stack_size, ainfo, FALSE);
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
-#ifdef SPARCV9
- add_general (&gr, &stack_size, ainfo, FALSE);
-#else
- add_general (&gr, &stack_size, ainfo, TRUE);
-#endif
- break;
- case MONO_TYPE_R4:
-#ifdef SPARCV9
- add_float (&fr, &stack_size, ainfo, TRUE);
- gr ++;
-#else
- /* single precision values are passed in integer registers */
- add_general (&gr, &stack_size, ainfo, FALSE);
-#endif
- break;
- case MONO_TYPE_R8:
-#ifdef SPARCV9
- add_float (&fr, &stack_size, ainfo, FALSE);
- gr ++;
-#else
- /* double precision values are passed in a pair of registers */
- add_general (&gr, &stack_size, ainfo, TRUE);
-#endif
- break;
- default:
- g_assert_not_reached ();
- }
- }
-
- if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n > 0) && (sig->sentinelpos == sig->param_count)) {
- gr = PARAM_REGS;
-
- /* Emit the signature cookie just before the implicit arguments */
- add_general (&gr, &stack_size, &cinfo->sig_cookie, FALSE);
- }
-
- /* return value */
- ret_type = mini_get_underlying_type (sig->ret);
- switch (ret_type->type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_PTR:
- case MONO_TYPE_FNPTR:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_STRING:
- cinfo->ret.storage = ArgInIReg;
- cinfo->ret.reg = sparc_i0;
- if (gr < 1)
- gr = 1;
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
-#ifdef SPARCV9
- cinfo->ret.storage = ArgInIReg;
- cinfo->ret.reg = sparc_i0;
- if (gr < 1)
- gr = 1;
-#else
- cinfo->ret.storage = ArgInIRegPair;
- cinfo->ret.reg = sparc_i0;
- if (gr < 2)
- gr = 2;
-#endif
- break;
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- cinfo->ret.storage = ArgInFReg;
- cinfo->ret.reg = sparc_f0;
- break;
- case MONO_TYPE_GENERICINST:
- if (!mono_type_generic_inst_is_valuetype (ret_type)) {
- cinfo->ret.storage = ArgInIReg;
- cinfo->ret.reg = sparc_i0;
- if (gr < 1)
- gr = 1;
- break;
- }
- /* Fall through */
- case MONO_TYPE_VALUETYPE:
- if (v64) {
- if (sig->pinvoke)
- NOT_IMPLEMENTED;
- else
- /* Already done */
- ;
- }
- else
- cinfo->ret.storage = ArgOnStack;
- break;
- case MONO_TYPE_TYPEDBYREF:
- if (v64) {
- if (sig->pinvoke)
- /* Same as a valuetype with size 24 */
- NOT_IMPLEMENTED;
- else
- /* Already done */
- ;
- }
- else
- cinfo->ret.storage = ArgOnStack;
- break;
- case MONO_TYPE_VOID:
- break;
- default:
- g_error ("Can't handle as return value 0x%x", sig->ret->type);
- }
-
- cinfo->stack_usage = stack_size;
- cinfo->reg_usage = gr;
- return cinfo;
-}
-
-GList *
-mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
-{
- GList *vars = NULL;
- int i;
-
- /*
- * FIXME: If an argument is allocated to a register, then load it from the
- * stack in the prolog.
- */
-
- for (i = 0; i < cfg->num_varinfo; i++) {
- MonoInst *ins = cfg->varinfo [i];
- MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
-
- /* unused vars */
- if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
- continue;
-
- /* FIXME: Make arguments on stack allocateable to registers */
- if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || (ins->opcode == OP_REGVAR) || (ins->opcode == OP_ARG))
- continue;
-
- if (mono_is_regsize_var (ins->inst_vtype)) {
- g_assert (MONO_VARINFO (cfg, i)->reg == -1);
- g_assert (i == vmv->idx);
-
- vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
- }
- }
-
- return vars;
-}
-
-GList *
-mono_arch_get_global_int_regs (MonoCompile *cfg)
-{
- GList *regs = NULL;
- int i;
- MonoMethodSignature *sig;
- CallInfo *cinfo;
-
- sig = mono_method_signature_internal (cfg->method);
-
- cinfo = get_call_info (cfg, sig, FALSE);
-
- /* Use unused input registers */
- for (i = cinfo->reg_usage; i < 6; ++i)
- regs = g_list_prepend (regs, GUINT_TO_POINTER (sparc_i0 + i));
-
- /* Use %l0..%l6 as global registers */
- for (i = sparc_l0; i < sparc_l7; ++i)
- regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
-
- g_free (cinfo);
-
- return regs;
-}
-
-/*
- * mono_arch_regalloc_cost:
- *
- * Return the cost, in number of memory references, of the action of
- * allocating the variable VMV into a register during global register
- * allocation.
- */
-guint32
-mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
-{
- return 0;
-}
-
-/*
- * Set var information according to the calling convention. sparc version.
- * The locals var stuff should most likely be split in another method.
- */
-
-void
-mono_arch_allocate_vars (MonoCompile *cfg)
-{
- MonoMethodSignature *sig;
- MonoMethodHeader *header;
- MonoInst *inst;
- int i, offset, size, align, curinst;
- CallInfo *cinfo;
-
- header = cfg->header;
-
- sig = mono_method_signature_internal (cfg->method);
-
- cinfo = get_call_info (cfg, sig, FALSE);
-
- if (sig->ret->type != MONO_TYPE_VOID) {
- switch (cinfo->ret.storage) {
- case ArgInIReg:
- case ArgInFReg:
- cfg->ret->opcode = OP_REGVAR;
- cfg->ret->inst_c0 = cinfo->ret.reg;
- break;
- case ArgInIRegPair: {
- MonoType *t = mini_get_underlying_type (sig->ret);
- if (((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) {
- MonoInst *low = get_vreg_to_inst (cfg, MONO_LVREG_LS (cfg->ret->dreg));
- MonoInst *high = get_vreg_to_inst (cfg, MONO_LVREG_MS (cfg->ret->dreg));
-
- low->opcode = OP_REGVAR;
- low->dreg = cinfo->ret.reg + 1;
- high->opcode = OP_REGVAR;
- high->dreg = cinfo->ret.reg;
- }
- cfg->ret->opcode = OP_REGVAR;
- cfg->ret->inst_c0 = cinfo->ret.reg;
- break;
- }
- case ArgOnStack:
-#ifdef SPARCV9
- g_assert_not_reached ();
-#else
- /* valuetypes */
- cfg->vret_addr->opcode = OP_REGOFFSET;
- cfg->vret_addr->inst_basereg = sparc_fp;
- cfg->vret_addr->inst_offset = 64;
-#endif
- break;
- default:
- NOT_IMPLEMENTED;
- }
- cfg->ret->dreg = cfg->ret->inst_c0;
- }
-
- /*
- * We use the ABI calling conventions for managed code as well.
- * Exception: valuetypes are never returned in registers on V9.
- * FIXME: Use something more optimized.
- */
-
- /* Locals are allocated backwards from %fp */
- cfg->frame_reg = sparc_fp;
- offset = 0;
-
- /*
- * Reserve a stack slot for holding information used during exception
- * handling.
- */
- if (header->num_clauses)
- offset += sizeof (target_mgreg_t) * 2;
-
- if (cfg->method->save_lmf) {
- offset += sizeof (MonoLMF);
- cfg->arch.lmf_offset = offset;
- }
-
- curinst = cfg->locals_start;
- for (i = curinst; i < cfg->num_varinfo; ++i) {
- inst = cfg->varinfo [i];
-
- if ((inst->opcode == OP_REGVAR) || (inst->opcode == OP_REGOFFSET)) {
- //g_print ("allocating local %d to %s\n", i, mono_arch_regname (inst->dreg));
- continue;
- }
-
- if (inst->flags & MONO_INST_IS_DEAD)
- continue;
-
- /* inst->backend.is_pinvoke indicates native sized value types, this is used by the
- * pinvoke wrappers when they call functions returning structure */
- if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF)
- size = mono_class_native_size (mono_class_from_mono_type_internal (inst->inst_vtype), &align);
- else
- size = mini_type_stack_size (inst->inst_vtype, &align);
-
- /*
- * This is needed since structures containing doubles must be doubleword
- * aligned.
- * FIXME: Do this only if needed.
- */
- if (MONO_TYPE_ISSTRUCT (inst->inst_vtype))
- align = 8;
-
- /*
- * variables are accessed as negative offsets from %fp, so increase
- * the offset before assigning it to a variable
- */
- offset += size;
-
- offset += align - 1;
- offset &= ~(align - 1);
- inst->opcode = OP_REGOFFSET;
- inst->inst_basereg = sparc_fp;
- inst->inst_offset = STACK_BIAS + -offset;
-
- //g_print ("allocating local %d to [%s - %d]\n", i, mono_arch_regname (inst->inst_basereg), - inst->inst_offset);
- }
-
- if (sig->call_convention == MONO_CALL_VARARG) {
- cfg->sig_cookie = cinfo->sig_cookie.offset + ARGS_OFFSET;
- }
-
- for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
- inst = cfg->args [i];
- if (inst->opcode != OP_REGVAR) {
- ArgInfo *ainfo = &cinfo->args [i];
- gboolean inreg = TRUE;
- MonoType *arg_type;
- ArgStorage storage;
-
- if (sig->hasthis && (i == 0))
- arg_type = mono_get_object_type ();
- else
- arg_type = sig->params [i - sig->hasthis];
-
-#ifndef SPARCV9
- if (!m_type_is_byref (arg_type) && ((arg_type->type == MONO_TYPE_R4)
- || (arg_type->type == MONO_TYPE_R8)))
- /*
- * Since float arguments are passed in integer registers, we need to
- * save them to the stack in the prolog.
- */
- inreg = FALSE;
-#endif
-
- /* FIXME: Allocate volatile arguments to registers */
- /* FIXME: This makes the argument holding a vtype address into volatile */
- if (inst->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT))
- inreg = FALSE;
-
- if (MONO_TYPE_ISSTRUCT (arg_type))
- /* FIXME: this isn't needed */
- inreg = FALSE;
-
- inst->opcode = OP_REGOFFSET;
-
- if (!inreg)
- storage = ArgOnStack;
- else
- storage = ainfo->storage;
-
- switch (storage) {
- case ArgInIReg:
- inst->opcode = OP_REGVAR;
- inst->dreg = sparc_i0 + ainfo->reg;
- break;
- case ArgInIRegPair:
- if (inst->type == STACK_I8) {
- MonoInst *low = get_vreg_to_inst (cfg, MONO_LVREG_LS (inst->dreg));
- MonoInst *high = get_vreg_to_inst (cfg, MONO_LVREG_MS (inst->dreg));
-
- low->opcode = OP_REGVAR;
- low->dreg = sparc_i0 + ainfo->reg + 1;
- high->opcode = OP_REGVAR;
- high->dreg = sparc_i0 + ainfo->reg;
- }
- inst->opcode = OP_REGVAR;
- inst->dreg = sparc_i0 + ainfo->reg;
- break;
- case ArgInFloatReg:
- case ArgInDoubleReg:
- /*
- * Since float regs are volatile, we save the arguments to
- * the stack in the prolog.
- * FIXME: Avoid this if the method contains no calls.
- */
- case ArgOnStack:
- case ArgOnStackPair:
- case ArgInSplitRegStack:
- /* Split arguments are saved to the stack in the prolog */
- inst->opcode = OP_REGOFFSET;
- /* in parent frame */
- inst->inst_basereg = sparc_fp;
- inst->inst_offset = ainfo->offset + ARGS_OFFSET;
-
- if (!m_type_is_byref (arg_type) && (arg_type->type == MONO_TYPE_R8)) {
- /*
- * It is very hard to load doubles from non-doubleword aligned
- * memory locations. So if the offset is misaligned, we copy the
- * argument to a stack location in the prolog.
- */
- if ((inst->inst_offset - STACK_BIAS) % 8) {
- inst->inst_basereg = sparc_fp;
- offset += 8;
- align = 8;
- offset += align - 1;
- offset &= ~(align - 1);
- inst->inst_offset = STACK_BIAS + -offset;
-
- }
- }
- break;
- default:
- NOT_IMPLEMENTED;
- }
-
- if (MONO_TYPE_ISSTRUCT (arg_type)) {
- /* Add a level of indirection */
- /*
- * It would be easier to add OP_LDIND_I here, but ldind_i instructions
- * are destructively modified in a lot of places in inssel.brg.
- */
- MonoInst *indir;
- MONO_INST_NEW (cfg, indir, 0);
- *indir = *inst;
- inst->opcode = OP_VTARG_ADDR;
- inst->inst_left = indir;
- }
- }
- }
-
- /*
- * spillvars are stored between the normal locals and the storage reserved
- * by the ABI.
- */
-
- cfg->stack_offset = offset;
-
- g_free (cinfo);
-}
-
-void
-mono_arch_create_vars (MonoCompile *cfg)
-{
- MonoMethodSignature *sig;
-
- sig = mono_method_signature_internal (cfg->method);
-
- if (MONO_TYPE_ISSTRUCT ((sig->ret))) {
- cfg->vret_addr = mono_compile_create_var (cfg, mono_get_int_type (), OP_ARG);
- if (G_UNLIKELY (cfg->verbose_level > 1)) {
- printf ("vret_addr = ");
- mono_print_ins (cfg->vret_addr);
- }
- }
-
- if (!m_type_is_byref (sig->ret) && (sig->ret->type == MONO_TYPE_I8 || sig->ret->type == MONO_TYPE_U8)) {
- MonoInst *low = get_vreg_to_inst (cfg, MONO_LVREG_LS (cfg->ret->dreg));
- MonoInst *high = get_vreg_to_inst (cfg, MONO_LVREG_MS (cfg->ret->dreg));
-
- low->flags |= MONO_INST_VOLATILE;
- high->flags |= MONO_INST_VOLATILE;
- }
-
- /* Add a properly aligned dword for use by int<->float conversion opcodes */
- cfg->arch.float_spill_slot = mono_compile_create_var (cfg, m_class_get_byval_arg (mono_defaults.double_class), OP_ARG);
- ((MonoInst*)cfg->arch.float_spill_slot)->flags |= MONO_INST_VOLATILE;
-}
-
-static void
-add_outarg_reg (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, guint32 sreg)
-{
- MonoInst *arg;
-
- MONO_INST_NEW (cfg, arg, 0);
-
- arg->sreg1 = sreg;
-
- switch (storage) {
- case ArgInIReg:
- arg->opcode = OP_MOVE;
- arg->dreg = mono_alloc_ireg (cfg);
-
- mono_call_inst_add_outarg_reg (cfg, call, arg->dreg, reg, FALSE);
- break;
- case ArgInFloatReg:
- arg->opcode = OP_FMOVE;
- arg->dreg = mono_alloc_freg (cfg);
-
- mono_call_inst_add_outarg_reg (cfg, call, arg->dreg, reg, TRUE);
- break;
- default:
- g_assert_not_reached ();
- }
-
- MONO_ADD_INS (cfg->cbb, arg);
-}
-
-static void
-add_outarg_load (MonoCompile *cfg, MonoCallInst *call, int opcode, int basereg, int offset, int reg)
-{
- int dreg = mono_alloc_ireg (cfg);
-
- MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, sparc_sp, offset);
-
- mono_call_inst_add_outarg_reg (cfg, call, dreg, reg, FALSE);
-}
-
-static void
-emit_pass_long (MonoCompile *cfg, MonoCallInst *call, ArgInfo *ainfo, MonoInst *in)
-{
- int offset = ARGS_OFFSET + ainfo->offset;
-
- switch (ainfo->storage) {
- case ArgInIRegPair:
- add_outarg_reg (cfg, call, ArgInIReg, sparc_o0 + ainfo->reg + 1, MONO_LVREG_LS (in->dreg));
- add_outarg_reg (cfg, call, ArgInIReg, sparc_o0 + ainfo->reg, MONO_LVREG_MS (in->dreg));
- break;
- case ArgOnStackPair:
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, sparc_sp, offset, MONO_LVREG_MS (in->dreg));
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, sparc_sp, offset + 4, MONO_LVREG_LS (in->dreg));
- break;
- case ArgInSplitRegStack:
- add_outarg_reg (cfg, call, ArgInIReg, sparc_o0 + ainfo->reg, MONO_LVREG_MS (in->dreg));
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, sparc_sp, offset + 4, MONO_LVREG_LS (in->dreg));
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
-static void
-emit_pass_double (MonoCompile *cfg, MonoCallInst *call, ArgInfo *ainfo, MonoInst *in)
-{
- int offset = ARGS_OFFSET + ainfo->offset;
-
- switch (ainfo->storage) {
- case ArgInIRegPair:
- /* floating-point <-> integer transfer must go through memory */
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, sparc_sp, offset, in->dreg);
-
- /* Load into a register pair */
- add_outarg_load (cfg, call, OP_LOADI4_MEMBASE, sparc_sp, offset, sparc_o0 + ainfo->reg);
- add_outarg_load (cfg, call, OP_LOADI4_MEMBASE, sparc_sp, offset + 4, sparc_o0 + ainfo->reg + 1);
- break;
- case ArgOnStackPair:
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, sparc_sp, offset, in->dreg);
- break;
- case ArgInSplitRegStack:
- /* floating-point <-> integer transfer must go through memory */
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, sparc_sp, offset, in->dreg);
- /* Load most significant word into register */
- add_outarg_load (cfg, call, OP_LOADI4_MEMBASE, sparc_sp, offset, sparc_o0 + ainfo->reg);
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
-static void
-emit_pass_float (MonoCompile *cfg, MonoCallInst *call, ArgInfo *ainfo, MonoInst *in)
-{
- int offset = ARGS_OFFSET + ainfo->offset;
-
- switch (ainfo->storage) {
- case ArgInIReg:
- /* floating-point <-> integer transfer must go through memory */
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, sparc_sp, offset, in->dreg);
- add_outarg_load (cfg, call, OP_LOADI4_MEMBASE, sparc_sp, offset, sparc_o0 + ainfo->reg);
- break;
- case ArgOnStack:
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, sparc_sp, offset, in->dreg);
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
-static void
-emit_pass_other (MonoCompile *cfg, MonoCallInst *call, ArgInfo *ainfo, MonoType *arg_type, MonoInst *in);
-
-static void
-emit_pass_vtype (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo, ArgInfo *ainfo, MonoType *arg_type, MonoInst *in, gboolean pinvoke)
-{
- MonoInst *arg;
- guint32 align, offset, pad, size;
-
- if (arg_type->type == MONO_TYPE_TYPEDBYREF) {
- size = MONO_ABI_SIZEOF (MonoTypedRef);
- align = sizeof (target_mgreg_t);
- }
- else if (pinvoke)
- size = mono_type_native_stack_size (m_class_get_byval_arg (in->klass), &align);
- else {
- /*
- * Other backends use mono_type_stack_size (), but that
- * aligns the size to 8, which is larger than the size of
- * the source, leading to reads of invalid memory if the
- * source is at the end of address space.
- */
- size = mono_class_value_size (in->klass, &align);
- }
-
- /* The first 6 argument locations are reserved */
- if (cinfo->stack_usage < 6 * sizeof (target_mgreg_t))
- cinfo->stack_usage = 6 * sizeof (target_mgreg_t);
-
- offset = ALIGN_TO ((ARGS_OFFSET - STACK_BIAS) + cinfo->stack_usage, align);
- pad = offset - ((ARGS_OFFSET - STACK_BIAS) + cinfo->stack_usage);
-
- cinfo->stack_usage += size;
- cinfo->stack_usage += pad;
-
- /*
- * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
- * use the normal OUTARG opcodes to pass the address of the location to
- * the callee.
- */
- if (size > 0) {
- MONO_INST_NEW (cfg, arg, OP_OUTARG_VT);
- arg->sreg1 = in->dreg;
- arg->klass = in->klass;
- arg->backend.size = size;
- arg->inst_p0 = call;
- arg->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
- memcpy (arg->inst_p1, ainfo, sizeof (ArgInfo));
- ((ArgInfo*)(arg->inst_p1))->offset = STACK_BIAS + offset;
- MONO_ADD_INS (cfg->cbb, arg);
-
- MONO_INST_NEW (cfg, arg, OP_ADD_IMM);
- arg->dreg = mono_alloc_preg (cfg);
- arg->sreg1 = sparc_sp;
- arg->inst_imm = STACK_BIAS + offset;
- MONO_ADD_INS (cfg->cbb, arg);
-
- emit_pass_other (cfg, call, ainfo, NULL, arg);
- }
-}
-
-static void
-emit_pass_other (MonoCompile *cfg, MonoCallInst *call, ArgInfo *ainfo, MonoType *arg_type, MonoInst *in)
-{
- int offset = ARGS_OFFSET + ainfo->offset;
- int opcode;
-
- switch (ainfo->storage) {
- case ArgInIReg:
- add_outarg_reg (cfg, call, ArgInIReg, sparc_o0 + ainfo->reg, in->dreg);
- break;
- case ArgOnStack:
-#ifdef SPARCV9
- NOT_IMPLEMENTED;
-#else
- if (offset & 0x1)
- opcode = OP_STOREI1_MEMBASE_REG;
- else if (offset & 0x2)
- opcode = OP_STOREI2_MEMBASE_REG;
- else
- opcode = OP_STOREI4_MEMBASE_REG;
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, opcode, sparc_sp, offset, in->dreg);
-#endif
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
-static void
-emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
-{
- MonoMethodSignature *tmp_sig;
-
- /*
- * mono_ArgIterator_Setup assumes the signature cookie is
- * passed first and all the arguments which were before it are
- * passed on the stack after the signature. So compensate by
- * passing a different signature.
- */
- tmp_sig = mono_metadata_signature_dup (call->signature);
- tmp_sig->param_count -= call->signature->sentinelpos;
- tmp_sig->sentinelpos = 0;
- memcpy (tmp_sig->params, call->signature->params + call->signature->sentinelpos, tmp_sig->param_count * sizeof (MonoType*));
-
- /* FIXME: Add support for signature tokens to AOT */
- cfg->disable_aot = TRUE;
- /* We allways pass the signature on the stack for simplicity */
- MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, sparc_sp, ARGS_OFFSET + cinfo->sig_cookie.offset, tmp_sig);
-}
-
-void
-mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
-{
- MonoInst *in;
- MonoMethodSignature *sig;
- int i, n;
- CallInfo *cinfo;
- ArgInfo *ainfo;
- guint32 extra_space = 0;
-
- sig = call->signature;
- n = sig->param_count + sig->hasthis;
-
- cinfo = get_call_info (cfg, sig, sig->pinvoke);
-
- if (sig->ret && MONO_TYPE_ISSTRUCT (sig->ret)) {
- /* Set the 'struct/union return pointer' location on the stack */
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, sparc_sp, 64, call->vret_var->dreg);
- }
-
- for (i = 0; i < n; ++i) {
- MonoType *arg_type;
-
- ainfo = cinfo->args + i;
-
- if ((sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
- /* Emit the signature cookie just before the first implicit argument */
- emit_sig_cookie (cfg, call, cinfo);
- }
-
- in = call->args [i];
-
- if (sig->hasthis && (i == 0))
- arg_type = mono_get_object_type ();
- else
- arg_type = sig->params [i - sig->hasthis];
-
- arg_type = mini_get_underlying_type (arg_type);
- if ((i >= sig->hasthis) && (MONO_TYPE_ISSTRUCT(sig->params [i - sig->hasthis])))
- emit_pass_vtype (cfg, call, cinfo, ainfo, arg_type, in, sig->pinvoke && !sig->marshalling_disabled);
- else if (!m_type_is_byref (arg_type) && ((arg_type->type == MONO_TYPE_I8) || (arg_type->type == MONO_TYPE_U8)))
- emit_pass_long (cfg, call, ainfo, in);
- else if (!m_type_is_byref (arg_type) && (arg_type->type == MONO_TYPE_R8))
- emit_pass_double (cfg, call, ainfo, in);
- else if (!m_type_is_byref (arg_type) && (arg_type->type == MONO_TYPE_R4))
- emit_pass_float (cfg, call, ainfo, in);
- else
- emit_pass_other (cfg, call, ainfo, arg_type, in);
- }
-
- /* Handle the case where there are no implicit arguments */
- if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == sig->sentinelpos)) {
- emit_sig_cookie (cfg, call, cinfo);
- }
-
- call->stack_usage = cinfo->stack_usage + extra_space;
-
- g_free (cinfo);
-}
-
-void
-mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
-{
- ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
- int size = ins->backend.size;
-
- mini_emit_memcpy (cfg, sparc_sp, ainfo->offset, src->dreg, 0, size, TARGET_SIZEOF_VOID_P);
-}
-
-void
-mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
-{
- CallInfo *cinfo = get_call_info (cfg, mono_method_signature_internal (method), FALSE);
- MonoType *ret = mini_get_underlying_type (mono_method_signature_internal (method)->ret);
-
- switch (cinfo->ret.storage) {
- case ArgInIReg:
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
- break;
- case ArgInIRegPair:
- if (ret->type == MONO_TYPE_I8 || ret->type == MONO_TYPE_U8) {
- MONO_EMIT_NEW_UNALU (cfg, OP_LMOVE, cfg->ret->dreg, val->dreg);
- } else {
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (cfg->ret->dreg), MONO_LVREG_MS (val->dreg));
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (cfg->ret->dreg), MONO_LVREG_LS (val->dreg));
- }
- break;
- case ArgInFReg:
- if (ret->type == MONO_TYPE_R4)
- MONO_EMIT_NEW_UNALU (cfg, OP_SETFRET, cfg->ret->dreg, val->dreg);
- else
- MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
- break;
- default:
- g_assert_not_reached ();
- }
-
- g_assert (cinfo);
-}
-
-int cond_to_sparc_cond [][3] = {
- {sparc_be, sparc_be, sparc_fbe},
- {sparc_bne, sparc_bne, 0},
- {sparc_ble, sparc_ble, sparc_fble},
- {sparc_bge, sparc_bge, sparc_fbge},
- {sparc_bl, sparc_bl, sparc_fbl},
- {sparc_bg, sparc_bg, sparc_fbg},
- {sparc_bleu, sparc_bleu, 0},
- {sparc_beu, sparc_beu, 0},
- {sparc_blu, sparc_blu, sparc_fbl},
- {sparc_bgu, sparc_bgu, sparc_fbg}
-};
-
-/* Map opcode to the sparc condition codes */
-static SparcCond
-opcode_to_sparc_cond (int opcode)
-{
- CompRelation rel;
- CompType t;
-
- switch (opcode) {
- case OP_COND_EXC_OV:
- case OP_COND_EXC_IOV:
- return sparc_bvs;
- case OP_COND_EXC_C:
- case OP_COND_EXC_IC:
- return sparc_bcs;
- case OP_COND_EXC_NO:
- case OP_COND_EXC_NC:
- NOT_IMPLEMENTED;
- default:
- rel = mono_opcode_to_cond (opcode);
- t = mono_opcode_to_type (opcode, -1);
-
- return cond_to_sparc_cond [rel][t];
- break;
- }
-
- return -1;
-}
-
-#define COMPUTE_DISP(ins) \
-if (ins->inst_true_bb->native_offset) \
- disp = (ins->inst_true_bb->native_offset - ((guint8*)code - cfg->native_code)) >> 2; \
-else { \
- disp = 0; \
- mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); \
-}
-
-#ifdef SPARCV9
-#define DEFAULT_ICC sparc_xcc_short
-#else
-#define DEFAULT_ICC sparc_icc_short
-#endif
-
-#ifdef SPARCV9
-#define EMIT_COND_BRANCH_ICC(ins,cond,annul,filldelay,icc) \
- do { \
- gint32 disp; \
- guint32 predict; \
- COMPUTE_DISP(ins); \
- predict = (disp != 0) ? 1 : 0; \
- g_assert (sparc_is_imm19 (disp)); \
- sparc_branchp (code, (annul), cond, icc, (predict), disp); \
- if (filldelay) sparc_nop (code); \
- } while (0)
-#define EMIT_COND_BRANCH(ins,cond,annul,filldelay) EMIT_COND_BRANCH_ICC ((ins), (cond), (annul), (filldelay), (sparc_xcc_short))
-#define EMIT_FLOAT_COND_BRANCH(ins,cond,annul,filldelay) \
- do { \
- gint32 disp; \
- guint32 predict; \
- COMPUTE_DISP(ins); \
- predict = (disp != 0) ? 1 : 0; \
- g_assert (sparc_is_imm19 (disp)); \
- sparc_fbranch (code, (annul), cond, disp); \
- if (filldelay) sparc_nop (code); \
- } while (0)
-#else
-#define EMIT_COND_BRANCH_ICC(ins,cond,annul,filldelay,icc) g_assert_not_reached ()
-#define EMIT_COND_BRANCH_GENERAL(ins,bop,cond,annul,filldelay) \
- do { \
- gint32 disp; \
- COMPUTE_DISP(ins); \
- g_assert (sparc_is_imm22 (disp)); \
- sparc_ ## bop (code, (annul), cond, disp); \
- if (filldelay) sparc_nop (code); \
- } while (0)
-#define EMIT_COND_BRANCH(ins,cond,annul,filldelay) EMIT_COND_BRANCH_GENERAL((ins),branch,(cond),annul,filldelay)
-#define EMIT_FLOAT_COND_BRANCH(ins,cond,annul,filldelay) EMIT_COND_BRANCH_GENERAL((ins),fbranch,(cond),annul,filldelay)
-#endif
-
-#define EMIT_COND_BRANCH_PREDICTED(ins,cond,annul,filldelay) \
- do { \
- gint32 disp; \
- guint32 predict; \
- COMPUTE_DISP(ins); \
- predict = (disp != 0) ? 1 : 0; \
- g_assert (sparc_is_imm19 (disp)); \
- sparc_branchp (code, (annul), (cond), DEFAULT_ICC, (predict), disp); \
- if (filldelay) sparc_nop (code); \
- } while (0)
-
-#define EMIT_COND_BRANCH_BPR(ins,bop,predict,annul,filldelay) \
- do { \
- gint32 disp; \
- COMPUTE_DISP(ins); \
- g_assert (sparc_is_imm22 (disp)); \
- sparc_ ## bop (code, (annul), (predict), ins->sreg1, disp); \
- if (filldelay) sparc_nop (code); \
- } while (0)
-
-/* emit an exception if condition is fail */
-/*
- * We put the exception throwing code out-of-line, at the end of the method
- */
-#define EMIT_COND_SYSTEM_EXCEPTION_GENERAL(ins,cond,sexc_name,filldelay,icc) do { \
- mono_add_patch_info (cfg, (guint8*)(code) - (cfg)->native_code, \
- MONO_PATCH_INFO_EXC, sexc_name); \
- if (mono_hwcap_sparc_is_v9 && ((icc) != sparc_icc_short)) { \
- sparc_branchp (code, 0, (cond), (icc), 0, 0); \
- } \
- else { \
- sparc_branch (code, 0, cond, 0); \
- } \
- if (filldelay) sparc_nop (code); \
- } while (0);
-
-#define EMIT_COND_SYSTEM_EXCEPTION(ins,cond,sexc_name) EMIT_COND_SYSTEM_EXCEPTION_GENERAL(ins,cond,sexc_name,TRUE,DEFAULT_ICC)
-
-#define EMIT_COND_SYSTEM_EXCEPTION_BPR(ins,bop,sexc_name) do { \
- mono_add_patch_info (cfg, (guint8*)(code) - (cfg)->native_code, \
- MONO_PATCH_INFO_EXC, sexc_name); \
- sparc_ ## bop (code, FALSE, FALSE, ins->sreg1, 0); \
- sparc_nop (code); \
-} while (0);
-
-#define EMIT_ALU_IMM(ins,op,setcc) do { \
- if (sparc_is_imm13 ((ins)->inst_imm)) \
- sparc_ ## op ## _imm (code, (setcc), (ins)->sreg1, ins->inst_imm, (ins)->dreg); \
- else { \
- sparc_set (code, ins->inst_imm, sparc_o7); \
- sparc_ ## op (code, (setcc), (ins)->sreg1, sparc_o7, (ins)->dreg); \
- } \
-} while (0);
-
-#define EMIT_LOAD_MEMBASE(ins,op) do { \
- if (sparc_is_imm13 (ins->inst_offset)) \
- sparc_ ## op ## _imm (code, ins->inst_basereg, ins->inst_offset, ins->dreg); \
- else { \
- sparc_set (code, ins->inst_offset, sparc_o7); \
- sparc_ ## op (code, ins->inst_basereg, sparc_o7, ins->dreg); \
- } \
-} while (0);
-
-/* max len = 5 */
-#define EMIT_STORE_MEMBASE_IMM(ins,op) do { \
- guint32 sreg; \
- if (ins->inst_imm == 0) \
- sreg = sparc_g0; \
- else { \
- sparc_set (code, ins->inst_imm, sparc_o7); \
- sreg = sparc_o7; \
- } \
- if (!sparc_is_imm13 (ins->inst_offset)) { \
- sparc_set (code, ins->inst_offset, GP_SCRATCH_REG); \
- sparc_ ## op (code, sreg, ins->inst_destbasereg, GP_SCRATCH_REG); \
- } \
- else \
- sparc_ ## op ## _imm (code, sreg, ins->inst_destbasereg, ins->inst_offset); \
- } while (0);
-
-#define EMIT_STORE_MEMBASE_REG(ins,op) do { \
- if (!sparc_is_imm13 (ins->inst_offset)) { \
- sparc_set (code, ins->inst_offset, sparc_o7); \
- sparc_ ## op (code, ins->sreg1, ins->inst_destbasereg, sparc_o7); \
- } \
- else \
- sparc_ ## op ## _imm (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset); \
- } while (0);
-
-#define EMIT_CALL() do { \
- if (v64) { \
- sparc_set_template (code, sparc_o7); \
- sparc_jmpl (code, sparc_o7, sparc_g0, sparc_o7); \
- } \
- else { \
- sparc_call_simple (code, 0); \
- } \
- sparc_nop (code); \
-} while (0);
-
-/*
- * A call template is 7 instructions long, so we want to avoid it if possible.
- */
-static guint32*
-emit_call (MonoCompile *cfg, guint32 *code, guint32 patch_type, gconstpointer data)
-{
- ERROR_DECL (error);
- gpointer target;
-
- /* FIXME: This only works if the target method is already compiled */
- if (0 && v64 && !cfg->compile_aot) {
- MonoJumpInfo patch_info;
-
- patch_info.type = patch_type;
- patch_info.data.target = data;
-
- target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, &patch_info, FALSE, error);
- mono_error_raise_exception_deprecated (error); /* FIXME: don't raise here */
-
- /* FIXME: Add optimizations if the target is close enough */
- sparc_set (code, target, sparc_o7);
- sparc_jmpl (code, sparc_o7, sparc_g0, sparc_o7);
- sparc_nop (code);
- }
- else {
- mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, patch_type, data);
- EMIT_CALL ();
- }
-
- return code;
-}
-
-void
-mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
-{
-}
-
-void
-mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
-{
- MonoInst *ins, *n, *last_ins = NULL;
- ins = bb->code;
-
- MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
- switch (ins->opcode) {
- case OP_MUL_IMM:
- /* remove unnecessary multiplication with 1 */
- if (ins->inst_imm == 1) {
- if (ins->dreg != ins->sreg1) {
- ins->opcode = OP_MOVE;
- } else {
- MONO_DELETE_INS (bb, ins);
- continue;
- }
- }
- break;
-#ifndef SPARCV9
- case OP_LOAD_MEMBASE:
- case OP_LOADI4_MEMBASE:
- /*
- * OP_STORE_MEMBASE_REG reg, offset(basereg)
- * OP_LOAD_MEMBASE offset(basereg), reg
- */
- if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG
- || last_ins->opcode == OP_STORE_MEMBASE_REG) &&
- ins->inst_basereg == last_ins->inst_destbasereg &&
- ins->inst_offset == last_ins->inst_offset) {
- if (ins->dreg == last_ins->sreg1) {
- MONO_DELETE_INS (bb, ins);
- continue;
- } else {
- //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
- ins->opcode = OP_MOVE;
- ins->sreg1 = last_ins->sreg1;
- }
-
- /*
- * Note: reg1 must be different from the basereg in the second load
- * OP_LOAD_MEMBASE offset(basereg), reg1
- * OP_LOAD_MEMBASE offset(basereg), reg2
- * -->
- * OP_LOAD_MEMBASE offset(basereg), reg1
- * OP_MOVE reg1, reg2
- */
- } if (last_ins && (last_ins->opcode == OP_LOADI4_MEMBASE
- || last_ins->opcode == OP_LOAD_MEMBASE) &&
- ins->inst_basereg != last_ins->dreg &&
- ins->inst_basereg == last_ins->inst_basereg &&
- ins->inst_offset == last_ins->inst_offset) {
-
- if (ins->dreg == last_ins->dreg) {
- MONO_DELETE_INS (bb, ins);
- continue;
- } else {
- ins->opcode = OP_MOVE;
- ins->sreg1 = last_ins->dreg;
- }
-
- //g_assert_not_reached ();
-
-#if 0
- /*
- * OP_STORE_MEMBASE_IMM imm, offset(basereg)
- * OP_LOAD_MEMBASE offset(basereg), reg
- * -->
- * OP_STORE_MEMBASE_IMM imm, offset(basereg)
- * OP_ICONST reg, imm
- */
- } else if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_IMM
- || last_ins->opcode == OP_STORE_MEMBASE_IMM) &&
- ins->inst_basereg == last_ins->inst_destbasereg &&
- ins->inst_offset == last_ins->inst_offset) {
- //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
- ins->opcode = OP_ICONST;
- ins->inst_c0 = last_ins->inst_imm;
- g_assert_not_reached (); // check this rule
-#endif
- }
- break;
-#endif
- case OP_LOADI1_MEMBASE:
- if (last_ins && (last_ins->opcode == OP_STOREI1_MEMBASE_REG) &&
- ins->inst_basereg == last_ins->inst_destbasereg &&
- ins->inst_offset == last_ins->inst_offset) {
- if (ins->dreg == last_ins->sreg1) {
- MONO_DELETE_INS (bb, ins);
- continue;
- } else {
- //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
- ins->opcode = OP_MOVE;
- ins->sreg1 = last_ins->sreg1;
- }
- }
- break;
- case OP_LOADI2_MEMBASE:
- if (last_ins && (last_ins->opcode == OP_STOREI2_MEMBASE_REG) &&
- ins->inst_basereg == last_ins->inst_destbasereg &&
- ins->inst_offset == last_ins->inst_offset) {
- if (ins->dreg == last_ins->sreg1) {
- MONO_DELETE_INS (bb, ins);
- continue;
- } else {
- //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
- ins->opcode = OP_MOVE;
- ins->sreg1 = last_ins->sreg1;
- }
- }
- break;
- case OP_STOREI4_MEMBASE_IMM:
- /* Convert pairs of 0 stores to a dword 0 store */
- /* Used when initializing temporaries */
- /* We know sparc_fp is dword aligned */
- if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_IMM) &&
- (ins->inst_destbasereg == last_ins->inst_destbasereg) &&
- (ins->inst_destbasereg == sparc_fp) &&
- (ins->inst_offset < 0) &&
- ((ins->inst_offset % 8) == 0) &&
- ((ins->inst_offset == last_ins->inst_offset - 4)) &&
- (ins->inst_imm == 0) &&
- (last_ins->inst_imm == 0)) {
- if (mono_hwcap_sparc_is_v9) {
- last_ins->opcode = OP_STOREI8_MEMBASE_IMM;
- last_ins->inst_offset = ins->inst_offset;
- MONO_DELETE_INS (bb, ins);
- continue;
- }
- }
- break;
- case OP_IBEQ:
- case OP_IBNE_UN:
- case OP_IBLT:
- case OP_IBGT:
- case OP_IBGE:
- case OP_IBLE:
- case OP_COND_EXC_EQ:
- case OP_COND_EXC_GE:
- case OP_COND_EXC_GT:
- case OP_COND_EXC_LE:
- case OP_COND_EXC_LT:
- case OP_COND_EXC_NE_UN:
- /*
- * Convert compare with zero+branch to BRcc
- */
- /*
- * This only works in 64 bit mode, since it examines all 64
- * bits of the register.
- * Only do this if the method is small since BPr only has a 16bit
- * displacement.
- */
- if (v64 && (cfg->header->code_size < 10000) && last_ins &&
- (last_ins->opcode == OP_COMPARE_IMM) &&
- (last_ins->inst_imm == 0)) {
- switch (ins->opcode) {
- case OP_IBEQ:
- ins->opcode = OP_SPARC_BRZ;
- break;
- case OP_IBNE_UN:
- ins->opcode = OP_SPARC_BRNZ;
- break;
- case OP_IBLT:
- ins->opcode = OP_SPARC_BRLZ;
- break;
- case OP_IBGT:
- ins->opcode = OP_SPARC_BRGZ;
- break;
- case OP_IBGE:
- ins->opcode = OP_SPARC_BRGEZ;
- break;
- case OP_IBLE:
- ins->opcode = OP_SPARC_BRLEZ;
- break;
- case OP_COND_EXC_EQ:
- ins->opcode = OP_SPARC_COND_EXC_EQZ;
- break;
- case OP_COND_EXC_GE:
- ins->opcode = OP_SPARC_COND_EXC_GEZ;
- break;
- case OP_COND_EXC_GT:
- ins->opcode = OP_SPARC_COND_EXC_GTZ;
- break;
- case OP_COND_EXC_LE:
- ins->opcode = OP_SPARC_COND_EXC_LEZ;
- break;
- case OP_COND_EXC_LT:
- ins->opcode = OP_SPARC_COND_EXC_LTZ;
- break;
- case OP_COND_EXC_NE_UN:
- ins->opcode = OP_SPARC_COND_EXC_NEZ;
- break;
- default:
- g_assert_not_reached ();
- }
- ins->sreg1 = last_ins->sreg1;
- *last_ins = *ins;
- MONO_DELETE_INS (bb, ins);
- continue;
- }
- break;
- case OP_MOVE:
- /*
- * OP_MOVE reg, reg
- */
- if (ins->dreg == ins->sreg1) {
- MONO_DELETE_INS (bb, ins);
- continue;
- }
- /*
- * OP_MOVE sreg, dreg
- * OP_MOVE dreg, sreg
- */
- if (last_ins && last_ins->opcode == OP_MOVE &&
- ins->sreg1 == last_ins->dreg &&
- ins->dreg == last_ins->sreg1) {
- MONO_DELETE_INS (bb, ins);
- continue;
- }
- break;
- }
- last_ins = ins;
- ins = ins->next;
- }
- bb->last_ins = last_ins;
-}
-
-void
-mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *ins)
-{
- switch (ins->opcode) {
- case OP_LNEG:
- MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, MONO_LVREG_LS (ins->dreg), 0, MONO_LVREG_LS (ins->sreg1));
- MONO_EMIT_NEW_BIALU (cfg, OP_SBB, MONO_LVREG_MS (ins->dreg), 0, MONO_LVREG_MS (ins->sreg1));
- NULLIFY_INS (ins);
- break;
- default:
- break;
- }
-}
-
-void
-mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
-{
-}
-
-/* FIXME: Strange loads from the stack in basic-float.cs:test_2_rem */
-
-static void
-sparc_patch (guint32 *code, const gpointer target)
-{
- guint32 *c = code;
- guint32 ins = *code;
- guint32 op = ins >> 30;
- guint32 op2 = (ins >> 22) & 0x7;
- guint32 rd = (ins >> 25) & 0x1f;
- guint8* target8 = (guint8*)target;
- gint64 disp = (target8 - (guint8*)code) >> 2;
- int reg;
-
-// g_print ("patching 0x%08x (0x%08x) to point to 0x%08x\n", code, ins, target);
-
- if ((op == 0) && (op2 == 2)) {
- if (!sparc_is_imm22 (disp))
- NOT_IMPLEMENTED;
- /* Bicc */
- *code = ((ins >> 22) << 22) | (disp & 0x3fffff);
- }
- else if ((op == 0) && (op2 == 1)) {
- if (!sparc_is_imm19 (disp))
- NOT_IMPLEMENTED;
- /* BPcc */
- *code = ((ins >> 19) << 19) | (disp & 0x7ffff);
- }
- else if ((op == 0) && (op2 == 3)) {
- if (!sparc_is_imm16 (disp))
- NOT_IMPLEMENTED;
- /* BPr */
- *code &= ~(0x180000 | 0x3fff);
- *code |= ((disp << 21) & (0x180000)) | (disp & 0x3fff);
- }
- else if ((op == 0) && (op2 == 6)) {
- if (!sparc_is_imm22 (disp))
- NOT_IMPLEMENTED;
- /* FBicc */
- *code = ((ins >> 22) << 22) | (disp & 0x3fffff);
- }
- else if ((op == 0) && (op2 == 4)) {
- guint32 ins2 = code [1];
-
- if (((ins2 >> 30) == 2) && (((ins2 >> 19) & 0x3f) == 2)) {
- /* sethi followed by or */
- guint32 *p = code;
- sparc_set (p, target8, rd);
- while (p <= (code + 1))
- sparc_nop (p);
- }
- else if (ins2 == 0x01000000) {
- /* sethi followed by nop */
- guint32 *p = code;
- sparc_set (p, target8, rd);
- while (p <= (code + 1))
- sparc_nop (p);
- }
- else if ((sparc_inst_op (ins2) == 3) && (sparc_inst_imm (ins2))) {
- /* sethi followed by load/store */
-#ifndef SPARCV9
- guint32 t = (guint32)target8;
- *code &= ~(0x3fffff);
- *code |= (t >> 10);
- *(code + 1) &= ~(0x3ff);
- *(code + 1) |= (t & 0x3ff);
-#endif
- }
- else if (v64 &&
- (sparc_inst_rd (ins) == sparc_g1) &&
- (sparc_inst_op (c [1]) == 0) && (sparc_inst_op2 (c [1]) == 4) &&
- (sparc_inst_op (c [2]) == 2) && (sparc_inst_op3 (c [2]) == 2) &&
- (sparc_inst_op (c [3]) == 2) && (sparc_inst_op3 (c [3]) == 2))
- {
- /* sparc_set */
- guint32 *p = c;
- reg = sparc_inst_rd (c [1]);
- sparc_set (p, target8, reg);
- while (p < (c + 6))
- sparc_nop (p);
- }
- else if ((sparc_inst_op (ins2) == 2) && (sparc_inst_op3 (ins2) == 0x38) &&
- (sparc_inst_imm (ins2))) {
- /* sethi followed by jmpl */
-#ifndef SPARCV9
- guint32 t = (guint32)target8;
- *code &= ~(0x3fffff);
- *code |= (t >> 10);
- *(code + 1) &= ~(0x3ff);
- *(code + 1) |= (t & 0x3ff);
-#endif
- }
- else
- NOT_IMPLEMENTED;
- }
- else if (op == 01) {
- gint64 disp = (target8 - (guint8*)code) >> 2;
-
- if (!sparc_is_imm30 (disp))
- NOT_IMPLEMENTED;
- sparc_call_simple (code, target8 - (guint8*)code);
- }
- else if ((op == 2) && (sparc_inst_op3 (ins) == 0x2) && sparc_inst_imm (ins)) {
- /* mov imm, reg */
- g_assert (sparc_is_imm13 (target8));
- *code &= ~(0x1fff);
- *code |= (guint32)target8;
- }
- else if ((sparc_inst_op (ins) == 2) && (sparc_inst_op3 (ins) == 0x7)) {
- /* sparc_set case 5. */
- guint32 *p = c;
-
- g_assert (v64);
- reg = sparc_inst_rd (c [3]);
- sparc_set (p, target, reg);
- while (p < (c + 6))
- sparc_nop (p);
- }
- else
- NOT_IMPLEMENTED;
-
-// g_print ("patched with 0x%08x\n", ins);
-}
-
-/*
- * mono_sparc_emit_save_lmf:
- *
- * Emit the code neccesary to push a new entry onto the lmf stack. Used by
- * trampolines as well.
- */
-guint32*
-mono_sparc_emit_save_lmf (guint32 *code, guint32 lmf_offset)
-{
- /* Save lmf_addr */
- sparc_sti_imm (code, sparc_o0, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr));
- /* Save previous_lmf */
- sparc_ldi (code, sparc_o0, sparc_g0, sparc_o7);
- sparc_sti_imm (code, sparc_o7, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf));
- /* Set new lmf */
- sparc_add_imm (code, FALSE, sparc_fp, lmf_offset, sparc_o7);
- sparc_sti (code, sparc_o7, sparc_o0, sparc_g0);
-
- return code;
-}
-
-guint32*
-mono_sparc_emit_restore_lmf (guint32 *code, guint32 lmf_offset)
-{
- /* Load previous_lmf */
- sparc_ldi_imm (code, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), sparc_l0);
- /* Load lmf_addr */
- sparc_ldi_imm (code, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), sparc_l1);
- /* *(lmf) = previous_lmf */
- sparc_sti (code, sparc_l0, sparc_l1, sparc_g0);
- return code;
-}
-
-static guint32*
-emit_save_sp_to_lmf (MonoCompile *cfg, guint32 *code)
-{
- /*
- * Since register windows are saved to the current value of %sp, we need to
- * set the sp field in the lmf before the call, not in the prolog.
- */
- if (cfg->method->save_lmf) {
- gint32 lmf_offset = MONO_SPARC_STACK_BIAS - cfg->arch.lmf_offset;
-
- /* Save sp */
- sparc_sti_imm (code, sparc_sp, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, sp));
- }
-
- return code;
-}
-
-static guint32*
-emit_vret_token (MonoInst *ins, guint32 *code)
-{
- MonoCallInst *call = (MonoCallInst*)ins;
- guint32 size;
-
- /*
- * The sparc ABI requires that calls to functions which return a structure
- * contain an additional unimpl instruction which is checked by the callee.
- */
- if (call->signature->pinvoke && !call->signature->marshalling_disabled && MONO_TYPE_ISSTRUCT(call->signature->ret)) {
- if (call->signature->ret->type == MONO_TYPE_TYPEDBYREF)
- size = mini_type_stack_size (call->signature->ret, NULL);
- else
- size = mono_class_native_size (call->signature->ret->data.klass, NULL);
- sparc_unimp (code, size & 0xfff);
- }
-
- return code;
-}
-
-static guint32*
-emit_move_return_value (MonoInst *ins, guint32 *code)
-{
- /* Move return value to the target register */
- /* FIXME: do more things in the local reg allocator */
- switch (ins->opcode) {
- case OP_VOIDCALL:
- case OP_VOIDCALL_REG:
- case OP_VOIDCALL_MEMBASE:
- break;
- case OP_CALL:
- case OP_CALL_REG:
- case OP_CALL_MEMBASE:
- g_assert (ins->dreg == sparc_o0);
- break;
- case OP_LCALL:
- case OP_LCALL_REG:
- case OP_LCALL_MEMBASE:
- /*
- * ins->dreg is the least significant reg due to the lreg: LCALL rule
- * in inssel-long32.brg.
- */
-#ifdef SPARCV9
- sparc_mov_reg_reg (code, sparc_o0, ins->dreg);
-#else
- g_assert (ins->dreg == sparc_o1);
-#endif
- break;
- case OP_FCALL:
- case OP_FCALL_REG:
- case OP_FCALL_MEMBASE:
-#ifdef SPARCV9
- if (((MonoCallInst*)ins)->signature->ret->type == MONO_TYPE_R4) {
- sparc_fmovs (code, sparc_f0, ins->dreg);
- sparc_fstod (code, ins->dreg, ins->dreg);
- }
- else
- sparc_fmovd (code, sparc_f0, ins->dreg);
-#else
- sparc_fmovs (code, sparc_f0, ins->dreg);
- if (((MonoCallInst*)ins)->signature->ret->type == MONO_TYPE_R4)
- sparc_fstod (code, ins->dreg, ins->dreg);
- else
- sparc_fmovs (code, sparc_f1, ins->dreg + 1);
-#endif
- break;
- case OP_VCALL:
- case OP_VCALL_REG:
- case OP_VCALL_MEMBASE:
- case OP_VCALL2:
- case OP_VCALL2_REG:
- case OP_VCALL2_MEMBASE:
- break;
- default:
- NOT_IMPLEMENTED;
- }
-
- return code;
-}
-
-/*
- * emit_load_volatile_arguments:
- *
- * Load volatile arguments from the stack to the original input registers.
- * Required before a tailcall.
- */
-static guint32*
-emit_load_volatile_arguments (MonoCompile *cfg, guint32 *code)
-{
- MonoMethod *method = cfg->method;
- MonoMethodSignature *sig;
- MonoInst *inst;
- CallInfo *cinfo;
- guint32 i, ireg;
-
- /* FIXME: Generate intermediate code instead */
-
- sig = mono_method_signature_internal (method);
-
- cinfo = get_call_info (cfg, sig, FALSE);
-
- /* This is the opposite of the code in emit_prolog */
-
- for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
- ArgInfo *ainfo = cinfo->args + i;
- gint32 stack_offset;
- MonoType *arg_type;
-
- inst = cfg->args [i];
-
- if (sig->hasthis && (i == 0))
- arg_type = mono_get_object_type ();
- else
- arg_type = sig->params [i - sig->hasthis];
-
- stack_offset = ainfo->offset + ARGS_OFFSET;
- ireg = sparc_i0 + ainfo->reg;
-
- if (ainfo->storage == ArgInSplitRegStack) {
- g_assert (inst->opcode == OP_REGOFFSET);
-
- if (!sparc_is_imm13 (stack_offset))
- NOT_IMPLEMENTED;
- sparc_st_imm (code, inst->inst_basereg, stack_offset, sparc_i5);
- }
-
- if (!v64 && !m_type_is_byref (arg_type) && (arg_type->type == MONO_TYPE_R8)) {
- if (ainfo->storage == ArgInIRegPair) {
- if (!sparc_is_imm13 (inst->inst_offset + 4))
- NOT_IMPLEMENTED;
- sparc_ld_imm (code, inst->inst_basereg, inst->inst_offset, ireg);
- sparc_ld_imm (code, inst->inst_basereg, inst->inst_offset + 4, ireg + 1);
- }
- else
- if (ainfo->storage == ArgInSplitRegStack) {
- if (stack_offset != inst->inst_offset) {
- sparc_ld_imm (code, inst->inst_basereg, inst->inst_offset, sparc_i5);
- sparc_ld_imm (code, inst->inst_basereg, inst->inst_offset + 4, sparc_o7);
- sparc_st_imm (code, sparc_o7, sparc_fp, stack_offset + 4);
-
- }
- }
- else
- if (ainfo->storage == ArgOnStackPair) {
- if (stack_offset != inst->inst_offset) {
- /* stack_offset is not dword aligned, so we need to make a copy */
- sparc_ld_imm (code, inst->inst_basereg, inst->inst_offset, sparc_o7);
- sparc_st_imm (code, sparc_o7, sparc_fp, stack_offset);
-
- sparc_ld_imm (code, inst->inst_basereg, inst->inst_offset + 4, sparc_o7);
- sparc_st_imm (code, sparc_o7, sparc_fp, stack_offset + 4);
-
- }
- }
- else
- g_assert_not_reached ();
- }
- else
- if ((ainfo->storage == ArgInIReg) && (inst->opcode != OP_REGVAR)) {
- /* Argument in register, but need to be saved to stack */
- if (!sparc_is_imm13 (stack_offset))
- NOT_IMPLEMENTED;
- if ((stack_offset - ARGS_OFFSET) & 0x1)
- /* FIXME: Is this ldsb or ldub ? */
- sparc_ldsb_imm (code, inst->inst_basereg, stack_offset, ireg);
- else
- if ((stack_offset - ARGS_OFFSET) & 0x2)
- sparc_ldsh_imm (code, inst->inst_basereg, stack_offset, ireg);
- else
- if ((stack_offset - ARGS_OFFSET) & 0x4)
- sparc_ld_imm (code, inst->inst_basereg, stack_offset, ireg);
- else {
- if (v64)
- sparc_ldx_imm (code, inst->inst_basereg, stack_offset, ireg);
- else
- sparc_ld_imm (code, inst->inst_basereg, stack_offset, ireg);
- }
- }
- else if ((ainfo->storage == ArgInIRegPair) && (inst->opcode != OP_REGVAR)) {
- /* Argument in regpair, but need to be saved to stack */
- if (!sparc_is_imm13 (inst->inst_offset + 4))
- NOT_IMPLEMENTED;
- sparc_ld_imm (code, inst->inst_basereg, inst->inst_offset, ireg);
- sparc_st_imm (code, inst->inst_basereg, inst->inst_offset + 4, ireg + 1);
- }
- else if ((ainfo->storage == ArgInFloatReg) && (inst->opcode != OP_REGVAR)) {
- NOT_IMPLEMENTED;
- }
- else if ((ainfo->storage == ArgInDoubleReg) && (inst->opcode != OP_REGVAR)) {
- NOT_IMPLEMENTED;
- }
-
- if ((ainfo->storage == ArgInSplitRegStack) || (ainfo->storage == ArgOnStack))
- if (inst->opcode == OP_REGVAR)
- /* FIXME: Load the argument into memory */
- NOT_IMPLEMENTED;
- }
-
- g_free (cinfo);
-
- return code;
-}
-
-/*
- * mono_sparc_is_virtual_call:
- *
- * Determine whenever the instruction at CODE is a virtual call.
- */
-gboolean
-mono_sparc_is_virtual_call (guint32 *code)
-{
- guint32 buf[1];
- guint32 *p;
-
- p = buf;
-
- if ((sparc_inst_op (*code) == 0x2) && (sparc_inst_op3 (*code) == 0x38)) {
- /*
- * Register indirect call. If it is a virtual call, then the
- * instruction in the delay slot is a special kind of nop.
- */
-
- /* Construct special nop */
- sparc_or_imm (p, FALSE, sparc_g0, 0xca, sparc_g0);
- p --;
-
- if (code [1] == p [0])
- return TRUE;
- }
-
- return FALSE;
-}
-
-#define CMP_SIZE 3
-#define BR_SMALL_SIZE 2
-#define BR_LARGE_SIZE 2
-#define JUMP_IMM_SIZE 5
-#define ENABLE_WRONG_METHOD_CHECK 0
-
-gpointer
-mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoIMTCheckItem **imt_entries, int count,
- gpointer fail_tramp)
-{
- int i;
- int size = 0;
- guint32 *code, *start;
-
- for (i = 0; i < count; ++i) {
- MonoIMTCheckItem *item = imt_entries [i];
- if (item->is_equals) {
- if (item->check_target_idx) {
- if (!item->compare_done)
- item->chunk_size += CMP_SIZE;
- item->chunk_size += BR_SMALL_SIZE + JUMP_IMM_SIZE;
- } else {
- if (fail_tramp)
- item->chunk_size += 16;
- item->chunk_size += JUMP_IMM_SIZE;
-#if ENABLE_WRONG_METHOD_CHECK
- item->chunk_size += CMP_SIZE + BR_SMALL_SIZE + 1;
-#endif
- }
- } else {
- item->chunk_size += CMP_SIZE + BR_LARGE_SIZE;
- imt_entries [item->check_target_idx]->compare_done = TRUE;
- }
- size += item->chunk_size;
- }
- if (fail_tramp) {
- code = (guint8 *)mini_alloc_generic_virtual_trampoline (vtable, size * 4);
- } else {
- MonoMemoryManager *mem_manager = m_class_get_mem_manager (vtable->klass);
- code = mono_mem_manager_code_reserve (mem_manager, size * 4);
- }
- start = code;
- for (i = 0; i < count; ++i) {
- MonoIMTCheckItem *item = imt_entries [i];
- item->code_target = (guint8*)code;
- if (item->is_equals) {
- gboolean fail_case = !item->check_target_idx && fail_tramp;
-
- if (item->check_target_idx || fail_case) {
- if (!item->compare_done || fail_case) {
- sparc_set (code, (guint32)item->key, sparc_g5);
- sparc_cmp (code, MONO_ARCH_IMT_REG, sparc_g5);
- }
- item->jmp_code = (guint8*)code;
- sparc_branch (code, 0, sparc_bne, 0);
- sparc_nop (code);
- if (item->has_target_code) {
- sparc_set (code, item->value.target_code, sparc_f5);
- } else {
- sparc_set (code, ((guint32)(&(vtable->vtable [item->value.vtable_slot]))), sparc_g5);
- sparc_ld (code, sparc_g5, 0, sparc_g5);
- }
- sparc_jmpl (code, sparc_g5, sparc_g0, sparc_g0);
- sparc_nop (code);
-
- if (fail_case) {
- sparc_patch (item->jmp_code, code);
- sparc_set (code, fail_tramp, sparc_g5);
- sparc_jmpl (code, sparc_g5, sparc_g0, sparc_g0);
- sparc_nop (code);
- item->jmp_code = NULL;
- }
- } else {
- /* enable the commented code to assert on wrong method */
-#if ENABLE_WRONG_METHOD_CHECK
- g_assert_not_reached ();
-#endif
- sparc_set (code, ((guint32)(&(vtable->vtable [item->value.vtable_slot]))), sparc_g5);
- sparc_ld (code, sparc_g5, 0, sparc_g5);
- sparc_jmpl (code, sparc_g5, sparc_g0, sparc_g0);
- sparc_nop (code);
-#if ENABLE_WRONG_METHOD_CHECK
- g_assert_not_reached ();
-#endif
- }
- } else {
- sparc_set (code, (guint32)item->key, sparc_g5);
- sparc_cmp (code, MONO_ARCH_IMT_REG, sparc_g5);
- item->jmp_code = (guint8*)code;
- sparc_branch (code, 0, sparc_beu, 0);
- sparc_nop (code);
- }
- }
- /* patch the branches to get to the target items */
- for (i = 0; i < count; ++i) {
- MonoIMTCheckItem *item = imt_entries [i];
- if (item->jmp_code) {
- if (item->check_target_idx) {
- sparc_patch ((guint32*)item->jmp_code, imt_entries [item->check_target_idx]->code_target);
- }
- }
- }
-
- mono_arch_flush_icache ((guint8*)start, (code - start));
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
-
- UnlockedAdd (&mono_stats.imt_trampolines_size, (code - start));
- g_assert (code - start <= size);
-
- mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), NULL);
-
- return start;
-}
-
-MonoMethod*
-mono_arch_find_imt_method (host_mgreg_t *regs, guint8 *code)
-{
-#ifdef SPARCV9
- g_assert_not_reached ();
-#endif
-
- return (MonoMethod*)regs [sparc_g1];
-}
-
-gpointer
-mono_arch_get_this_arg_from_call (host_mgreg_t *regs, guint8 *code)
-{
- mono_sparc_flushw ();
-
- return (gpointer)regs [sparc_o0];
-}
-
-/*
- * Some conventions used in the following code.
- * 2) The only scratch registers we have are o7 and g1. We try to
- * stick to o7 when we can, and use g1 when necessary.
- */
-
-void
-mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
-{
- MonoInst *ins;
- MonoCallInst *call;
- guint offset;
- guint32 *code = (guint32*)(cfg->native_code + cfg->code_len);
- MonoInst *last_ins = NULL;
- int max_len, cpos;
- const char *spec;
-
- if (cfg->verbose_level > 2)
- g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
-
- cpos = bb->max_offset;
-
- MONO_BB_FOR_EACH_INS (bb, ins) {
- guint8* code_start;
-
- offset = (guint8*)code - cfg->native_code;
- spec = ins_get_spec (ins->opcode);
- max_len = ins_get_size (ins->opcode);
- code = realloc_code (cfg, max_len);
- code_start = (guint8*)code;
- // if (ins->cil_code)
- // g_print ("cil code\n");
- mono_debug_record_line_number (cfg, ins, offset);
-
- switch (ins->opcode) {
- case OP_STOREI1_MEMBASE_IMM:
- EMIT_STORE_MEMBASE_IMM (ins, stb);
- break;
- case OP_STOREI2_MEMBASE_IMM:
- EMIT_STORE_MEMBASE_IMM (ins, sth);
- break;
- case OP_STORE_MEMBASE_IMM:
- EMIT_STORE_MEMBASE_IMM (ins, sti);
- break;
- case OP_STOREI4_MEMBASE_IMM:
- EMIT_STORE_MEMBASE_IMM (ins, st);
- break;
- case OP_STOREI8_MEMBASE_IMM:
-#ifdef SPARCV9
- EMIT_STORE_MEMBASE_IMM (ins, stx);
-#else
- /* Only generated by peephole opts */
- g_assert ((ins->inst_offset % 8) == 0);
- g_assert (ins->inst_imm == 0);
- EMIT_STORE_MEMBASE_IMM (ins, stx);
-#endif
- break;
- case OP_STOREI1_MEMBASE_REG:
- EMIT_STORE_MEMBASE_REG (ins, stb);
- break;
- case OP_STOREI2_MEMBASE_REG:
- EMIT_STORE_MEMBASE_REG (ins, sth);
- break;
- case OP_STOREI4_MEMBASE_REG:
- EMIT_STORE_MEMBASE_REG (ins, st);
- break;
- case OP_STOREI8_MEMBASE_REG:
-#ifdef SPARCV9
- EMIT_STORE_MEMBASE_REG (ins, stx);
-#else
- /* Only used by OP_MEMSET */
- EMIT_STORE_MEMBASE_REG (ins, std);
-#endif
- break;
- case OP_STORE_MEMBASE_REG:
- EMIT_STORE_MEMBASE_REG (ins, sti);
- break;
- case OP_LOADU4_MEM:
- sparc_set (code, ins->inst_c0, ins->dreg);
- sparc_ld (code, ins->dreg, sparc_g0, ins->dreg);
- break;
- case OP_LOADI4_MEMBASE:
-#ifdef SPARCV9
- EMIT_LOAD_MEMBASE (ins, ldsw);
-#else
- EMIT_LOAD_MEMBASE (ins, ld);
-#endif
- break;
- case OP_LOADU4_MEMBASE:
- EMIT_LOAD_MEMBASE (ins, ld);
- break;
- case OP_LOADU1_MEMBASE:
- EMIT_LOAD_MEMBASE (ins, ldub);
- break;
- case OP_LOADI1_MEMBASE:
- EMIT_LOAD_MEMBASE (ins, ldsb);
- break;
- case OP_LOADU2_MEMBASE:
- EMIT_LOAD_MEMBASE (ins, lduh);
- break;
- case OP_LOADI2_MEMBASE:
- EMIT_LOAD_MEMBASE (ins, ldsh);
- break;
- case OP_LOAD_MEMBASE:
-#ifdef SPARCV9
- EMIT_LOAD_MEMBASE (ins, ldx);
-#else
- EMIT_LOAD_MEMBASE (ins, ld);
-#endif
- break;
-#ifdef SPARCV9
- case OP_LOADI8_MEMBASE:
- EMIT_LOAD_MEMBASE (ins, ldx);
- break;
-#endif
- case OP_ICONV_TO_I1:
- sparc_sll_imm (code, ins->sreg1, 24, sparc_o7);
- sparc_sra_imm (code, sparc_o7, 24, ins->dreg);
- break;
- case OP_ICONV_TO_I2:
- sparc_sll_imm (code, ins->sreg1, 16, sparc_o7);
- sparc_sra_imm (code, sparc_o7, 16, ins->dreg);
- break;
- case OP_ICONV_TO_U1:
- sparc_and_imm (code, FALSE, ins->sreg1, 0xff, ins->dreg);
- break;
- case OP_ICONV_TO_U2:
- sparc_sll_imm (code, ins->sreg1, 16, sparc_o7);
- sparc_srl_imm (code, sparc_o7, 16, ins->dreg);
- break;
- case OP_LCONV_TO_OVF_U4:
- case OP_ICONV_TO_OVF_U4:
- /* Only used on V9 */
- sparc_cmp_imm (code, ins->sreg1, 0);
- mono_add_patch_info (cfg, (guint8*)(code) - (cfg)->native_code,
- MONO_PATCH_INFO_EXC, "OverflowException");
- sparc_branchp (code, 0, sparc_bl, sparc_xcc_short, 0, 0);
- /* Delay slot */
- sparc_set (code, 1, sparc_o7);
- sparc_sllx_imm (code, sparc_o7, 32, sparc_o7);
- sparc_cmp (code, ins->sreg1, sparc_o7);
- mono_add_patch_info (cfg, (guint8*)(code) - (cfg)->native_code,
- MONO_PATCH_INFO_EXC, "OverflowException");
- sparc_branchp (code, 0, sparc_bge, sparc_xcc_short, 0, 0);
- sparc_nop (code);
- sparc_mov_reg_reg (code, ins->sreg1, ins->dreg);
- break;
- case OP_LCONV_TO_OVF_I4_UN:
- case OP_ICONV_TO_OVF_I4_UN:
- /* Only used on V9 */
- NOT_IMPLEMENTED;
- break;
- case OP_COMPARE:
- case OP_LCOMPARE:
- case OP_ICOMPARE:
- sparc_cmp (code, ins->sreg1, ins->sreg2);
- break;
- case OP_COMPARE_IMM:
- case OP_ICOMPARE_IMM:
- if (sparc_is_imm13 (ins->inst_imm))
- sparc_cmp_imm (code, ins->sreg1, ins->inst_imm);
- else {
- sparc_set (code, ins->inst_imm, sparc_o7);
- sparc_cmp (code, ins->sreg1, sparc_o7);
- }
- break;
- case OP_BREAK:
- /*
- * gdb does not like encountering 'ta 1' in the debugged code. So
- * instead of emitting a trap, we emit a call a C function and place a
- * breakpoint there.
- */
- //sparc_ta (code, 1);
- mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_JIT_ICALL_ID,
- GUINT_TO_POINTER (MONO_JIT_ICALL_mono_break));
- EMIT_CALL();
- break;
- case OP_ADDCC:
- case OP_IADDCC:
- sparc_add (code, TRUE, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_IADD:
- sparc_add (code, FALSE, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_ADDCC_IMM:
- case OP_ADD_IMM:
- case OP_IADD_IMM:
- /* according to inssel-long32.brg, this should set cc */
- EMIT_ALU_IMM (ins, add, TRUE);
- break;
- case OP_ADC:
- case OP_IADC:
- /* according to inssel-long32.brg, this should set cc */
- sparc_addx (code, TRUE, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_ADC_IMM:
- case OP_IADC_IMM:
- EMIT_ALU_IMM (ins, addx, TRUE);
- break;
- case OP_SUBCC:
- case OP_ISUBCC:
- sparc_sub (code, TRUE, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_ISUB:
- sparc_sub (code, FALSE, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_SUBCC_IMM:
- case OP_SUB_IMM:
- case OP_ISUB_IMM:
- /* according to inssel-long32.brg, this should set cc */
- EMIT_ALU_IMM (ins, sub, TRUE);
- break;
- case OP_SBB:
- case OP_ISBB:
- /* according to inssel-long32.brg, this should set cc */
- sparc_subx (code, TRUE, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_SBB_IMM:
- case OP_ISBB_IMM:
- EMIT_ALU_IMM (ins, subx, TRUE);
- break;
- case OP_IAND:
- sparc_and (code, FALSE, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_AND_IMM:
- case OP_IAND_IMM:
- EMIT_ALU_IMM (ins, and, FALSE);
- break;
- case OP_IDIV:
- /* Sign extend sreg1 into %y */
- sparc_sra_imm (code, ins->sreg1, 31, sparc_o7);
- sparc_wry (code, sparc_o7, sparc_g0);
- sparc_sdiv (code, TRUE, ins->sreg1, ins->sreg2, ins->dreg);
- EMIT_COND_SYSTEM_EXCEPTION_GENERAL (code, sparc_boverflow, "ArithmeticException", TRUE, sparc_icc_short);
- break;
- case OP_IDIV_UN:
- sparc_wry (code, sparc_g0, sparc_g0);
- sparc_udiv (code, FALSE, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_DIV_IMM:
- case OP_IDIV_IMM: {
- int i, imm;
-
- /* Transform division into a shift */
- for (i = 1; i < 30; ++i) {
- imm = (1 << i);
- if (ins->inst_imm == imm)
- break;
- }
- if (i < 30) {
- if (i == 1) {
- /* gcc 2.95.3 */
- sparc_srl_imm (code, ins->sreg1, 31, sparc_o7);
- sparc_add (code, FALSE, ins->sreg1, sparc_o7, ins->dreg);
- sparc_sra_imm (code, ins->dreg, 1, ins->dreg);
- }
- else {
- /* http://compilers.iecc.com/comparch/article/93-04-079 */
- sparc_sra_imm (code, ins->sreg1, 31, sparc_o7);
- sparc_srl_imm (code, sparc_o7, 32 - i, sparc_o7);
- sparc_add (code, FALSE, ins->sreg1, sparc_o7, ins->dreg);
- sparc_sra_imm (code, ins->dreg, i, ins->dreg);
- }
- }
- else {
- /* Sign extend sreg1 into %y */
- sparc_sra_imm (code, ins->sreg1, 31, sparc_o7);
- sparc_wry (code, sparc_o7, sparc_g0);
- EMIT_ALU_IMM (ins, sdiv, TRUE);
- EMIT_COND_SYSTEM_EXCEPTION_GENERAL (code, sparc_boverflow, "ArithmeticException", TRUE, sparc_icc_short);
- }
- break;
- }
- case OP_IDIV_UN_IMM:
- sparc_wry (code, sparc_g0, sparc_g0);
- EMIT_ALU_IMM (ins, udiv, FALSE);
- break;
- case OP_IREM:
- /* Sign extend sreg1 into %y */
- sparc_sra_imm (code, ins->sreg1, 31, sparc_o7);
- sparc_wry (code, sparc_o7, sparc_g0);
- sparc_sdiv (code, TRUE, ins->sreg1, ins->sreg2, sparc_o7);
- EMIT_COND_SYSTEM_EXCEPTION_GENERAL (code, sparc_boverflow, "ArithmeticException", TRUE, sparc_icc_short);
- sparc_smul (code, FALSE, ins->sreg2, sparc_o7, sparc_o7);
- sparc_sub (code, FALSE, ins->sreg1, sparc_o7, ins->dreg);
- break;
- case OP_IREM_UN:
- sparc_wry (code, sparc_g0, sparc_g0);
- sparc_udiv (code, FALSE, ins->sreg1, ins->sreg2, sparc_o7);
- sparc_umul (code, FALSE, ins->sreg2, sparc_o7, sparc_o7);
- sparc_sub (code, FALSE, ins->sreg1, sparc_o7, ins->dreg);
- break;
- case OP_REM_IMM:
- case OP_IREM_IMM:
- /* Sign extend sreg1 into %y */
- sparc_sra_imm (code, ins->sreg1, 31, sparc_o7);
- sparc_wry (code, sparc_o7, sparc_g0);
- if (!sparc_is_imm13 (ins->inst_imm)) {
- sparc_set (code, ins->inst_imm, GP_SCRATCH_REG);
- sparc_sdiv (code, TRUE, ins->sreg1, GP_SCRATCH_REG, sparc_o7);
- EMIT_COND_SYSTEM_EXCEPTION_GENERAL (code, sparc_boverflow, "ArithmeticException", TRUE, sparc_icc_short);
- sparc_smul (code, FALSE, sparc_o7, GP_SCRATCH_REG, sparc_o7);
- }
- else {
- sparc_sdiv_imm (code, TRUE, ins->sreg1, ins->inst_imm, sparc_o7);
- EMIT_COND_SYSTEM_EXCEPTION_GENERAL (code, sparc_boverflow, "ArithmeticException", TRUE, sparc_icc_short);
- sparc_smul_imm (code, FALSE, sparc_o7, ins->inst_imm, sparc_o7);
- }
- sparc_sub (code, FALSE, ins->sreg1, sparc_o7, ins->dreg);
- break;
- case OP_IREM_UN_IMM:
- sparc_set (code, ins->inst_imm, GP_SCRATCH_REG);
- sparc_wry (code, sparc_g0, sparc_g0);
- sparc_udiv (code, FALSE, ins->sreg1, GP_SCRATCH_REG, sparc_o7);
- sparc_umul (code, FALSE, GP_SCRATCH_REG, sparc_o7, sparc_o7);
- sparc_sub (code, FALSE, ins->sreg1, sparc_o7, ins->dreg);
- break;
- case OP_IOR:
- sparc_or (code, FALSE, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_OR_IMM:
- case OP_IOR_IMM:
- EMIT_ALU_IMM (ins, or, FALSE);
- break;
- case OP_IXOR:
- sparc_xor (code, FALSE, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_XOR_IMM:
- case OP_IXOR_IMM:
- EMIT_ALU_IMM (ins, xor, FALSE);
- break;
- case OP_ISHL:
- sparc_sll (code, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_SHL_IMM:
- case OP_ISHL_IMM:
- if (ins->inst_imm < (1 << 5))
- sparc_sll_imm (code, ins->sreg1, ins->inst_imm, ins->dreg);
- else {
- sparc_set (code, ins->inst_imm, sparc_o7);
- sparc_sll (code, ins->sreg1, sparc_o7, ins->dreg);
- }
- break;
- case OP_ISHR:
- sparc_sra (code, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_ISHR_IMM:
- case OP_SHR_IMM:
- if (ins->inst_imm < (1 << 5))
- sparc_sra_imm (code, ins->sreg1, ins->inst_imm, ins->dreg);
- else {
- sparc_set (code, ins->inst_imm, sparc_o7);
- sparc_sra (code, ins->sreg1, sparc_o7, ins->dreg);
- }
- break;
- case OP_SHR_UN_IMM:
- case OP_ISHR_UN_IMM:
- if (ins->inst_imm < (1 << 5))
- sparc_srl_imm (code, ins->sreg1, ins->inst_imm, ins->dreg);
- else {
- sparc_set (code, ins->inst_imm, sparc_o7);
- sparc_srl (code, ins->sreg1, sparc_o7, ins->dreg);
- }
- break;
- case OP_ISHR_UN:
- sparc_srl (code, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_LSHL:
- sparc_sllx (code, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_LSHL_IMM:
- if (ins->inst_imm < (1 << 6))
- sparc_sllx_imm (code, ins->sreg1, ins->inst_imm, ins->dreg);
- else {
- sparc_set (code, ins->inst_imm, sparc_o7);
- sparc_sllx (code, ins->sreg1, sparc_o7, ins->dreg);
- }
- break;
- case OP_LSHR:
- sparc_srax (code, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_LSHR_IMM:
- if (ins->inst_imm < (1 << 6))
- sparc_srax_imm (code, ins->sreg1, ins->inst_imm, ins->dreg);
- else {
- sparc_set (code, ins->inst_imm, sparc_o7);
- sparc_srax (code, ins->sreg1, sparc_o7, ins->dreg);
- }
- break;
- case OP_LSHR_UN:
- sparc_srlx (code, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_LSHR_UN_IMM:
- if (ins->inst_imm < (1 << 6))
- sparc_srlx_imm (code, ins->sreg1, ins->inst_imm, ins->dreg);
- else {
- sparc_set (code, ins->inst_imm, sparc_o7);
- sparc_srlx (code, ins->sreg1, sparc_o7, ins->dreg);
- }
- break;
- case OP_INOT:
- /* can't use sparc_not */
- sparc_xnor (code, FALSE, ins->sreg1, sparc_g0, ins->dreg);
- break;
- case OP_INEG:
- /* can't use sparc_neg */
- sparc_sub (code, FALSE, sparc_g0, ins->sreg1, ins->dreg);
- break;
- case OP_IMUL:
- sparc_smul (code, FALSE, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_IMUL_IMM:
- case OP_MUL_IMM: {
- int i, imm;
-
- if ((ins->inst_imm == 1) && (ins->sreg1 == ins->dreg))
- break;
-
- /* Transform multiplication into a shift */
- for (i = 0; i < 30; ++i) {
- imm = (1 << i);
- if (ins->inst_imm == imm)
- break;
- }
- if (i < 30)
- sparc_sll_imm (code, ins->sreg1, i, ins->dreg);
- else
- EMIT_ALU_IMM (ins, smul, FALSE);
- break;
- }
- case OP_IMUL_OVF:
- sparc_smul (code, TRUE, ins->sreg1, ins->sreg2, ins->dreg);
- sparc_rdy (code, sparc_g1);
- sparc_sra_imm (code, ins->dreg, 31, sparc_o7);
- sparc_cmp (code, sparc_g1, sparc_o7);
- EMIT_COND_SYSTEM_EXCEPTION_GENERAL (ins, sparc_bne, "OverflowException", TRUE, sparc_icc_short);
- break;
- case OP_IMUL_OVF_UN:
- sparc_umul (code, TRUE, ins->sreg1, ins->sreg2, ins->dreg);
- sparc_rdy (code, sparc_o7);
- sparc_cmp (code, sparc_o7, sparc_g0);
- EMIT_COND_SYSTEM_EXCEPTION_GENERAL (ins, sparc_bne, "OverflowException", TRUE, sparc_icc_short);
- break;
- case OP_ICONST:
- sparc_set (code, ins->inst_c0, ins->dreg);
- break;
- case OP_I8CONST:
- sparc_set (code, ins->inst_l, ins->dreg);
- break;
- case OP_AOTCONST:
- mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
- sparc_set_template (code, ins->dreg);
- break;
- case OP_JUMP_TABLE:
- mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
- sparc_set_template (code, ins->dreg);
- break;
- case OP_ICONV_TO_I4:
- case OP_ICONV_TO_U4:
- case OP_MOVE:
- if (ins->sreg1 != ins->dreg)
- sparc_mov_reg_reg (code, ins->sreg1, ins->dreg);
- break;
- case OP_FMOVE:
-#ifdef SPARCV9
- if (ins->sreg1 != ins->dreg)
- sparc_fmovd (code, ins->sreg1, ins->dreg);
-#else
- sparc_fmovs (code, ins->sreg1, ins->dreg);
- sparc_fmovs (code, ins->sreg1 + 1, ins->dreg + 1);
-#endif
- break;
- case OP_CHECK_THIS:
- /* ensure ins->sreg1 is not NULL */
- /* Might be misaligned in case of vtypes so use a byte load */
- sparc_ldsb_imm (code, ins->sreg1, 0, sparc_g0);
- break;
- case OP_ARGLIST:
- sparc_add_imm (code, FALSE, sparc_fp, cfg->sig_cookie, sparc_o7);
- sparc_sti_imm (code, sparc_o7, ins->sreg1, 0);
- break;
- case OP_FCALL:
- case OP_LCALL:
- case OP_VCALL:
- case OP_VCALL2:
- case OP_VOIDCALL:
- case OP_CALL: {
- call = (MonoCallInst*)ins;
- g_assert (!call->virtual);
- code = emit_save_sp_to_lmf (cfg, code);
-
- const MonoJumpInfoTarget patch = mono_call_to_patch (call);
- code = emit_call (cfg, code, patch.type, patch.target);
- code = emit_vret_token (ins, code);
- code = emit_move_return_value (ins, code);
- break;
- }
- case OP_FCALL_REG:
- case OP_LCALL_REG:
- case OP_VCALL_REG:
- case OP_VCALL2_REG:
- case OP_VOIDCALL_REG:
- case OP_CALL_REG:
- call = (MonoCallInst*)ins;
- code = emit_save_sp_to_lmf (cfg, code);
- sparc_jmpl (code, ins->sreg1, sparc_g0, sparc_callsite);
- /*
- * We emit a special kind of nop in the delay slot to tell the
- * trampoline code that this is a virtual call, thus an unbox
- * trampoline might need to be called.
- */
- if (call->virtual)
- sparc_or_imm (code, FALSE, sparc_g0, 0xca, sparc_g0);
- else
- sparc_nop (code);
-
- code = emit_vret_token (ins, code);
- code = emit_move_return_value (ins, code);
- break;
- case OP_FCALL_MEMBASE:
- case OP_LCALL_MEMBASE:
- case OP_VCALL_MEMBASE:
- case OP_VCALL2_MEMBASE:
- case OP_VOIDCALL_MEMBASE:
- case OP_CALL_MEMBASE:
- call = (MonoCallInst*)ins;
- code = emit_save_sp_to_lmf (cfg, code);
- if (sparc_is_imm13 (ins->inst_offset)) {
- sparc_ldi_imm (code, ins->inst_basereg, ins->inst_offset, sparc_o7);
- } else {
- sparc_set (code, ins->inst_offset, sparc_o7);
- sparc_ldi (code, ins->inst_basereg, sparc_o7, sparc_o7);
- }
- sparc_jmpl (code, sparc_o7, sparc_g0, sparc_callsite);
- if (call->virtual)
- sparc_or_imm (code, FALSE, sparc_g0, 0xca, sparc_g0);
- else
- sparc_nop (code);
-
- code = emit_vret_token (ins, code);
- code = emit_move_return_value (ins, code);
- break;
- case OP_SETFRET:
- if (mono_method_signature_internal (cfg->method)->ret->type == MONO_TYPE_R4)
- sparc_fdtos (code, ins->sreg1, sparc_f0);
- else {
-#ifdef SPARCV9
- sparc_fmovd (code, ins->sreg1, ins->dreg);
-#else
- /* FIXME: Why not use fmovd ? */
- sparc_fmovs (code, ins->sreg1, ins->dreg);
- sparc_fmovs (code, ins->sreg1 + 1, ins->dreg + 1);
-#endif
- }
- break;
- case OP_LOCALLOC: {
- guint32 size_reg;
- gint32 offset2;
-
-#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
- /* Perform stack touching */
- NOT_IMPLEMENTED;
-#endif
-
- /* Keep alignment */
- /* Add 4 to compensate for the rounding of localloc_offset */
- sparc_add_imm (code, FALSE, ins->sreg1, 4 + MONO_ARCH_LOCALLOC_ALIGNMENT - 1, ins->dreg);
- sparc_set (code, ~(MONO_ARCH_LOCALLOC_ALIGNMENT - 1), sparc_o7);
- sparc_and (code, FALSE, ins->dreg, sparc_o7, ins->dreg);
-
- if ((ins->flags & MONO_INST_INIT) && (ins->sreg1 == ins->dreg)) {
-#ifdef SPARCV9
- size_reg = sparc_g4;
-#else
- size_reg = sparc_g1;
-#endif
- sparc_mov_reg_reg (code, ins->dreg, size_reg);
- }
- else
- size_reg = ins->sreg1;
-
- sparc_sub (code, FALSE, sparc_sp, ins->dreg, ins->dreg);
- /* Keep %sp valid at all times */
- sparc_mov_reg_reg (code, ins->dreg, sparc_sp);
- /* Round localloc_offset too so the result is at least 8 aligned */
- offset2 = ALIGN_TO (cfg->arch.localloc_offset, 8);
- g_assert (sparc_is_imm13 (MONO_SPARC_STACK_BIAS + offset2));
- sparc_add_imm (code, FALSE, ins->dreg, MONO_SPARC_STACK_BIAS + offset2, ins->dreg);
-
- if (ins->flags & MONO_INST_INIT) {
- guint32 *br [3];
- /* Initialize memory region */
- sparc_cmp_imm (code, size_reg, 0);
- br [0] = code;
- sparc_branch (code, 0, sparc_be, 0);
- /* delay slot */
- sparc_set (code, 0, sparc_o7);
- sparc_sub_imm (code, 0, size_reg, mono_hwcap_sparc_is_v9 ? 8 : 4, size_reg);
- /* start of loop */
- br [1] = code;
- if (mono_hwcap_sparc_is_v9)
- sparc_stx (code, sparc_g0, ins->dreg, sparc_o7);
- else
- sparc_st (code, sparc_g0, ins->dreg, sparc_o7);
- sparc_cmp (code, sparc_o7, size_reg);
- br [2] = code;
- sparc_branch (code, 0, sparc_bl, 0);
- sparc_patch (br [2], br [1]);
- /* delay slot */
- sparc_add_imm (code, 0, sparc_o7, mono_hwcap_sparc_is_v9 ? 8 : 4, sparc_o7);
- sparc_patch (br [0], code);
- }
- break;
- }
- case OP_LOCALLOC_IMM: {
- gint32 offset = ins->inst_imm;
- gint32 offset2;
-
-#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
- /* Perform stack touching */
- NOT_IMPLEMENTED;
-#endif
-
- /* To compensate for the rounding of localloc_offset */
- offset += sizeof (target_mgreg_t);
- offset = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
- if (sparc_is_imm13 (offset))
- sparc_sub_imm (code, FALSE, sparc_sp, offset, sparc_sp);
- else {
- sparc_set (code, offset, sparc_o7);
- sparc_sub (code, FALSE, sparc_sp, sparc_o7, sparc_sp);
- }
- /* Round localloc_offset too so the result is at least 8 aligned */
- offset2 = ALIGN_TO (cfg->arch.localloc_offset, 8);
- g_assert (sparc_is_imm13 (MONO_SPARC_STACK_BIAS + offset2));
- sparc_add_imm (code, FALSE, sparc_sp, MONO_SPARC_STACK_BIAS + offset2, ins->dreg);
- if ((ins->flags & MONO_INST_INIT) && (offset > 0)) {
- guint32 *br [2];
- int i;
-
- if (offset <= 16) {
- i = 0;
- while (i < offset) {
- if (mono_hwcap_sparc_is_v9) {
- sparc_stx_imm (code, sparc_g0, ins->dreg, i);
- i += 8;
- }
- else {
- sparc_st_imm (code, sparc_g0, ins->dreg, i);
- i += 4;
- }
- }
- }
- else {
- sparc_set (code, offset, sparc_o7);
- sparc_sub_imm (code, 0, sparc_o7, mono_hwcap_sparc_is_v9 ? 8 : 4, sparc_o7);
- /* beginning of loop */
- br [0] = code;
- if (mono_hwcap_sparc_is_v9)
- sparc_stx (code, sparc_g0, ins->dreg, sparc_o7);
- else
- sparc_st (code, sparc_g0, ins->dreg, sparc_o7);
- sparc_cmp_imm (code, sparc_o7, 0);
- br [1] = code;
- sparc_branch (code, 0, sparc_bne, 0);
- /* delay slot */
- sparc_sub_imm (code, 0, sparc_o7, mono_hwcap_sparc_is_v9 ? 8 : 4, sparc_o7);
- sparc_patch (br [1], br [0]);
- }
- }
- break;
- }
- case OP_THROW:
- sparc_mov_reg_reg (code, ins->sreg1, sparc_o0);
- mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID,
- GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_throw_exception));
- EMIT_CALL ();
- break;
- case OP_RETHROW:
- sparc_mov_reg_reg (code, ins->sreg1, sparc_o0);
- mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID,
- GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_rethrow_exception));
- EMIT_CALL ();
- break;
- case OP_START_HANDLER: {
- /*
- * The START_HANDLER instruction marks the beginning of a handler
- * block. It is called using a call instruction, so %o7 contains
- * the return address. Since the handler executes in the same stack
- * frame as the method itself, we can't use save/restore to save
- * the return address. Instead, we save it into a dedicated
- * variable.
- */
- MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
- if (!sparc_is_imm13 (spvar->inst_offset)) {
- sparc_set (code, spvar->inst_offset, GP_SCRATCH_REG);
- sparc_sti (code, sparc_o7, spvar->inst_basereg, GP_SCRATCH_REG);
- }
- else
- sparc_sti_imm (code, sparc_o7, spvar->inst_basereg, spvar->inst_offset);
- break;
- }
- case OP_ENDFILTER: {
- MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
- if (!sparc_is_imm13 (spvar->inst_offset)) {
- sparc_set (code, spvar->inst_offset, GP_SCRATCH_REG);
- sparc_ldi (code, spvar->inst_basereg, GP_SCRATCH_REG, sparc_o7);
- }
- else
- sparc_ldi_imm (code, spvar->inst_basereg, spvar->inst_offset, sparc_o7);
- sparc_jmpl_imm (code, sparc_o7, 8, sparc_g0);
- /* Delay slot */
- sparc_mov_reg_reg (code, ins->sreg1, sparc_o0);
- break;
- }
- case OP_ENDFINALLY: {
- MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
- if (!sparc_is_imm13 (spvar->inst_offset)) {
- sparc_set (code, spvar->inst_offset, GP_SCRATCH_REG);
- sparc_ldi (code, spvar->inst_basereg, GP_SCRATCH_REG, sparc_o7);
- }
- else
- sparc_ldi_imm (code, spvar->inst_basereg, spvar->inst_offset, sparc_o7);
- sparc_jmpl_imm (code, sparc_o7, 8, sparc_g0);
- sparc_nop (code);
- break;
- }
- case OP_CALL_HANDLER:
- mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb);
- /* This is a jump inside the method, so call_simple works even on V9 */
- sparc_call_simple (code, 0);
- sparc_nop (code);
- for (GList *tmp = ins->inst_eh_blocks; tmp != bb->clause_holes; tmp = tmp->prev)
- mono_cfg_add_try_hole (cfg, ((MonoLeaveClause *) tmp->data)->clause, code, bb);
- break;
- case OP_LABEL:
- ins->inst_c0 = (guint8*)code - cfg->native_code;
- break;
- case OP_RELAXED_NOP:
- case OP_NOP:
- case OP_DUMMY_USE:
- case OP_DUMMY_ICONST:
- case OP_DUMMY_I8CONST:
- case OP_DUMMY_R8CONST:
- case OP_DUMMY_R4CONST:
- case OP_NOT_REACHED:
- case OP_NOT_NULL:
- break;
- case OP_BR:
- //g_print ("target: %p, next: %p, curr: %p, last: %p\n", ins->inst_target_bb, bb->next_bb, ins, bb->last_ins);
- if ((ins->inst_target_bb == bb->next_bb) && ins == bb->last_ins)
- break;
- if (ins->inst_target_bb->native_offset) {
- gint32 disp = (ins->inst_target_bb->native_offset - ((guint8*)code - cfg->native_code)) >> 2;
- g_assert (sparc_is_imm22 (disp));
- sparc_branch (code, 1, sparc_ba, disp);
- } else {
- mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb);
- sparc_branch (code, 1, sparc_ba, 0);
- }
- sparc_nop (code);
- break;
- case OP_BR_REG:
- sparc_jmp (code, ins->sreg1, sparc_g0);
- sparc_nop (code);
- break;
- case OP_CEQ:
- case OP_CLT:
- case OP_CLT_UN:
- case OP_CGT:
- case OP_CGT_UN:
- if (v64 && (cfg->opt & MONO_OPT_CMOV)) {
- sparc_clr_reg (code, ins->dreg);
- sparc_movcc_imm (code, sparc_xcc, opcode_to_sparc_cond (ins->opcode), 1, ins->dreg);
- }
- else {
- sparc_clr_reg (code, ins->dreg);
-#ifdef SPARCV9
- sparc_branchp (code, 1, opcode_to_sparc_cond (ins->opcode), DEFAULT_ICC, 0, 2);
-#else
- sparc_branch (code, 1, opcode_to_sparc_cond (ins->opcode), 2);
-#endif
- /* delay slot */
- sparc_set (code, 1, ins->dreg);
- }
- break;
- case OP_ICEQ:
- case OP_ICLT:
- case OP_ICLT_UN:
- case OP_ICGT:
- case OP_ICGT_UN:
- if (v64 && (cfg->opt & MONO_OPT_CMOV)) {
- sparc_clr_reg (code, ins->dreg);
- sparc_movcc_imm (code, sparc_icc, opcode_to_sparc_cond (ins->opcode), 1, ins->dreg);
- }
- else {
- sparc_clr_reg (code, ins->dreg);
- sparc_branchp (code, 1, opcode_to_sparc_cond (ins->opcode), sparc_icc_short, 0, 2);
- /* delay slot */
- sparc_set (code, 1, ins->dreg);
- }
- break;
- case OP_COND_EXC_EQ:
- case OP_COND_EXC_NE_UN:
- case OP_COND_EXC_LT:
- case OP_COND_EXC_LT_UN:
- case OP_COND_EXC_GT:
- case OP_COND_EXC_GT_UN:
- case OP_COND_EXC_GE:
- case OP_COND_EXC_GE_UN:
- case OP_COND_EXC_LE:
- case OP_COND_EXC_LE_UN:
- case OP_COND_EXC_OV:
- case OP_COND_EXC_NO:
- case OP_COND_EXC_C:
- case OP_COND_EXC_NC:
- case OP_COND_EXC_IEQ:
- case OP_COND_EXC_INE_UN:
- case OP_COND_EXC_ILT:
- case OP_COND_EXC_ILT_UN:
- case OP_COND_EXC_IGT:
- case OP_COND_EXC_IGT_UN:
- case OP_COND_EXC_IGE:
- case OP_COND_EXC_IGE_UN:
- case OP_COND_EXC_ILE:
- case OP_COND_EXC_ILE_UN:
- case OP_COND_EXC_IOV:
- case OP_COND_EXC_INO:
- case OP_COND_EXC_IC:
- case OP_COND_EXC_INC:
-#ifdef SPARCV9
- NOT_IMPLEMENTED;
-#else
- EMIT_COND_SYSTEM_EXCEPTION (ins, opcode_to_sparc_cond (ins->opcode), ins->inst_p1);
-#endif
- break;
- case OP_SPARC_COND_EXC_EQZ:
- EMIT_COND_SYSTEM_EXCEPTION_BPR (ins, brz, ins->inst_p1);
- break;
- case OP_SPARC_COND_EXC_GEZ:
- EMIT_COND_SYSTEM_EXCEPTION_BPR (ins, brgez, ins->inst_p1);
- break;
- case OP_SPARC_COND_EXC_GTZ:
- EMIT_COND_SYSTEM_EXCEPTION_BPR (ins, brgz, ins->inst_p1);
- break;
- case OP_SPARC_COND_EXC_LEZ:
- EMIT_COND_SYSTEM_EXCEPTION_BPR (ins, brlez, ins->inst_p1);
- break;
- case OP_SPARC_COND_EXC_LTZ:
- EMIT_COND_SYSTEM_EXCEPTION_BPR (ins, brlz, ins->inst_p1);
- break;
- case OP_SPARC_COND_EXC_NEZ:
- EMIT_COND_SYSTEM_EXCEPTION_BPR (ins, brnz, ins->inst_p1);
- break;
-
- case OP_IBEQ:
- case OP_IBNE_UN:
- case OP_IBLT:
- case OP_IBLT_UN:
- case OP_IBGT:
- case OP_IBGT_UN:
- case OP_IBGE:
- case OP_IBGE_UN:
- case OP_IBLE:
- case OP_IBLE_UN: {
- if (mono_hwcap_sparc_is_v9)
- EMIT_COND_BRANCH_PREDICTED (ins, opcode_to_sparc_cond (ins->opcode), 1, 1);
- else
- EMIT_COND_BRANCH (ins, opcode_to_sparc_cond (ins->opcode), 1, 1);
- break;
- }
-
- case OP_SPARC_BRZ:
- EMIT_COND_BRANCH_BPR (ins, brz, 1, 1, 1);
- break;
- case OP_SPARC_BRLEZ:
- EMIT_COND_BRANCH_BPR (ins, brlez, 1, 1, 1);
- break;
- case OP_SPARC_BRLZ:
- EMIT_COND_BRANCH_BPR (ins, brlz, 1, 1, 1);
- break;
- case OP_SPARC_BRNZ:
- EMIT_COND_BRANCH_BPR (ins, brnz, 1, 1, 1);
- break;
- case OP_SPARC_BRGZ:
- EMIT_COND_BRANCH_BPR (ins, brgz, 1, 1, 1);
- break;
- case OP_SPARC_BRGEZ:
- EMIT_COND_BRANCH_BPR (ins, brgez, 1, 1, 1);
- break;
-
- /* floating point opcodes */
- case OP_R8CONST:
- mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_R8, ins->inst_p0);
-#ifdef SPARCV9
- sparc_set_template (code, sparc_o7);
-#else
- sparc_sethi (code, 0, sparc_o7);
-#endif
- sparc_lddf_imm (code, sparc_o7, 0, ins->dreg);
- break;
- case OP_R4CONST:
- mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_R4, ins->inst_p0);
-#ifdef SPARCV9
- sparc_set_template (code, sparc_o7);
-#else
- sparc_sethi (code, 0, sparc_o7);
-#endif
- sparc_ldf_imm (code, sparc_o7, 0, FP_SCRATCH_REG);
-
- /* Extend to double */
- sparc_fstod (code, FP_SCRATCH_REG, ins->dreg);
- break;
- case OP_STORER8_MEMBASE_REG:
- if (!sparc_is_imm13 (ins->inst_offset + 4)) {
- sparc_set (code, ins->inst_offset, sparc_o7);
- /* SPARCV9 handles misaligned fp loads/stores */
- if (!v64 && (ins->inst_offset % 8)) {
- /* Misaligned */
- sparc_add (code, FALSE, ins->inst_destbasereg, sparc_o7, sparc_o7);
- sparc_stf (code, ins->sreg1, sparc_o7, sparc_g0);
- sparc_stf_imm (code, ins->sreg1 + 1, sparc_o7, 4);
- } else
- sparc_stdf (code, ins->sreg1, ins->inst_destbasereg, sparc_o7);
- }
- else {
- if (!v64 && (ins->inst_offset % 8)) {
- /* Misaligned */
- sparc_stf_imm (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
- sparc_stf_imm (code, ins->sreg1 + 1, ins->inst_destbasereg, ins->inst_offset + 4);
- } else
- sparc_stdf_imm (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
- }
- break;
- case OP_LOADR8_MEMBASE:
- EMIT_LOAD_MEMBASE (ins, lddf);
- break;
- case OP_STORER4_MEMBASE_REG:
- /* This requires a double->single conversion */
- sparc_fdtos (code, ins->sreg1, FP_SCRATCH_REG);
- if (!sparc_is_imm13 (ins->inst_offset)) {
- sparc_set (code, ins->inst_offset, sparc_o7);
- sparc_stf (code, FP_SCRATCH_REG, ins->inst_destbasereg, sparc_o7);
- }
- else
- sparc_stf_imm (code, FP_SCRATCH_REG, ins->inst_destbasereg, ins->inst_offset);
- break;
- case OP_LOADR4_MEMBASE: {
- /* ldf needs a single precision register */
- int dreg = ins->dreg;
- ins->dreg = FP_SCRATCH_REG;
- EMIT_LOAD_MEMBASE (ins, ldf);
- ins->dreg = dreg;
- /* Extend to double */
- sparc_fstod (code, FP_SCRATCH_REG, ins->dreg);
- break;
- }
- case OP_ICONV_TO_R4: {
- MonoInst *spill = cfg->arch.float_spill_slot;
- gint32 reg = spill->inst_basereg;
- gint32 offset = spill->inst_offset;
-
- g_assert (spill->opcode == OP_REGOFFSET);
-#ifdef SPARCV9
- if (!sparc_is_imm13 (offset)) {
- sparc_set (code, offset, sparc_o7);
- sparc_stx (code, ins->sreg1, reg, offset);
- sparc_lddf (code, reg, offset, FP_SCRATCH_REG);
- } else {
- sparc_stx_imm (code, ins->sreg1, reg, offset);
- sparc_lddf_imm (code, reg, offset, FP_SCRATCH_REG);
- }
- sparc_fxtos (code, FP_SCRATCH_REG, FP_SCRATCH_REG);
-#else
- if (!sparc_is_imm13 (offset)) {
- sparc_set (code, offset, sparc_o7);
- sparc_st (code, ins->sreg1, reg, sparc_o7);
- sparc_ldf (code, reg, sparc_o7, FP_SCRATCH_REG);
- } else {
- sparc_st_imm (code, ins->sreg1, reg, offset);
- sparc_ldf_imm (code, reg, offset, FP_SCRATCH_REG);
- }
- sparc_fitos (code, FP_SCRATCH_REG, FP_SCRATCH_REG);
-#endif
- sparc_fstod (code, FP_SCRATCH_REG, ins->dreg);
- break;
- }
- case OP_ICONV_TO_R8: {
- MonoInst *spill = cfg->arch.float_spill_slot;
- gint32 reg = spill->inst_basereg;
- gint32 offset = spill->inst_offset;
-
- g_assert (spill->opcode == OP_REGOFFSET);
-
-#ifdef SPARCV9
- if (!sparc_is_imm13 (offset)) {
- sparc_set (code, offset, sparc_o7);
- sparc_stx (code, ins->sreg1, reg, sparc_o7);
- sparc_lddf (code, reg, sparc_o7, FP_SCRATCH_REG);
- } else {
- sparc_stx_imm (code, ins->sreg1, reg, offset);
- sparc_lddf_imm (code, reg, offset, FP_SCRATCH_REG);
- }
- sparc_fxtod (code, FP_SCRATCH_REG, ins->dreg);
-#else
- if (!sparc_is_imm13 (offset)) {
- sparc_set (code, offset, sparc_o7);
- sparc_st (code, ins->sreg1, reg, sparc_o7);
- sparc_ldf (code, reg, sparc_o7, FP_SCRATCH_REG);
- } else {
- sparc_st_imm (code, ins->sreg1, reg, offset);
- sparc_ldf_imm (code, reg, offset, FP_SCRATCH_REG);
- }
- sparc_fitod (code, FP_SCRATCH_REG, ins->dreg);
-#endif
- break;
- }
- case OP_FCONV_TO_I1:
- case OP_FCONV_TO_U1:
- case OP_FCONV_TO_I2:
- case OP_FCONV_TO_U2:
- case OP_FCONV_TO_I4:
- case OP_FCONV_TO_U4: {
- MonoInst *spill = cfg->arch.float_spill_slot;
- gint32 reg = spill->inst_basereg;
- gint32 offset = spill->inst_offset;
-
- g_assert (spill->opcode == OP_REGOFFSET);
-
- sparc_fdtoi (code, ins->sreg1, FP_SCRATCH_REG);
- if (!sparc_is_imm13 (offset)) {
- sparc_set (code, offset, sparc_o7);
- sparc_stdf (code, FP_SCRATCH_REG, reg, sparc_o7);
- sparc_ld (code, reg, sparc_o7, ins->dreg);
- } else {
- sparc_stdf_imm (code, FP_SCRATCH_REG, reg, offset);
- sparc_ld_imm (code, reg, offset, ins->dreg);
- }
-
- switch (ins->opcode) {
- case OP_FCONV_TO_I1:
- case OP_FCONV_TO_U1:
- sparc_and_imm (code, 0, ins->dreg, 0xff, ins->dreg);
- break;
- case OP_FCONV_TO_I2:
- case OP_FCONV_TO_U2:
- sparc_set (code, 0xffff, sparc_o7);
- sparc_and (code, 0, ins->dreg, sparc_o7, ins->dreg);
- break;
- default:
- break;
- }
- break;
- }
- case OP_FCONV_TO_I8:
- case OP_FCONV_TO_U8:
- /* Emulated */
- g_assert_not_reached ();
- break;
- case OP_FCONV_TO_R4:
- /* FIXME: Change precision ? */
-#ifdef SPARCV9
- sparc_fmovd (code, ins->sreg1, ins->dreg);
-#else
- sparc_fmovs (code, ins->sreg1, ins->dreg);
- sparc_fmovs (code, ins->sreg1 + 1, ins->dreg + 1);
-#endif
- break;
- case OP_LCONV_TO_R_UN: {
- /* Emulated */
- g_assert_not_reached ();
- break;
- }
- case OP_LCONV_TO_OVF_I:
- case OP_LCONV_TO_OVF_I4_2: {
- guint32 *br [3], *label [1];
-
- /*
- * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
- */
- sparc_cmp_imm (code, ins->sreg1, 0);
- br [0] = code;
- sparc_branch (code, 1, sparc_bneg, 0);
- sparc_nop (code);
-
- /* positive */
- /* ms word must be 0 */
- sparc_cmp_imm (code, ins->sreg2, 0);
- br [1] = code;
- sparc_branch (code, 1, sparc_be, 0);
- sparc_nop (code);
-
- label [0] = code;
-
- EMIT_COND_SYSTEM_EXCEPTION (ins, sparc_ba, "OverflowException");
-
- /* negative */
- sparc_patch (br [0], code);
-
- /* ms word must 0xfffffff */
- sparc_cmp_imm (code, ins->sreg2, -1);
- br [2] = code;
- sparc_branch (code, 1, sparc_bne, 0);
- sparc_nop (code);
- sparc_patch (br [2], label [0]);
-
- /* Ok */
- sparc_patch (br [1], code);
- if (ins->sreg1 != ins->dreg)
- sparc_mov_reg_reg (code, ins->sreg1, ins->dreg);
- break;
- }
- case OP_FADD:
- sparc_faddd (code, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_FSUB:
- sparc_fsubd (code, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_FMUL:
- sparc_fmuld (code, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_FDIV:
- sparc_fdivd (code, ins->sreg1, ins->sreg2, ins->dreg);
- break;
- case OP_FNEG:
-#ifdef SPARCV9
- sparc_fnegd (code, ins->sreg1, ins->dreg);
-#else
- /* FIXME: why don't use fnegd ? */
- sparc_fnegs (code, ins->sreg1, ins->dreg);
-#endif
- break;
- case OP_FREM:
- sparc_fdivd (code, ins->sreg1, ins->sreg2, FP_SCRATCH_REG);
- sparc_fmuld (code, ins->sreg2, FP_SCRATCH_REG, FP_SCRATCH_REG);
- sparc_fsubd (code, ins->sreg1, FP_SCRATCH_REG, ins->dreg);
- break;
- case OP_FCOMPARE:
- sparc_fcmpd (code, ins->sreg1, ins->sreg2);
- break;
- case OP_FCEQ:
- case OP_FCLT:
- case OP_FCLT_UN:
- case OP_FCGT:
- case OP_FCGT_UN:
- sparc_fcmpd (code, ins->sreg1, ins->sreg2);
- sparc_clr_reg (code, ins->dreg);
- switch (ins->opcode) {
- case OP_FCLT_UN:
- case OP_FCGT_UN:
- sparc_fbranch (code, 1, opcode_to_sparc_cond (ins->opcode), 4);
- /* delay slot */
- sparc_set (code, 1, ins->dreg);
- sparc_fbranch (code, 1, sparc_fbu, 2);
- /* delay slot */
- sparc_set (code, 1, ins->dreg);
- break;
- default:
- sparc_fbranch (code, 1, opcode_to_sparc_cond (ins->opcode), 2);
- /* delay slot */
- sparc_set (code, 1, ins->dreg);
- }
- break;
- case OP_FBEQ:
- case OP_FBLT:
- case OP_FBGT:
- EMIT_FLOAT_COND_BRANCH (ins, opcode_to_sparc_cond (ins->opcode), 1, 1);
- break;
- case OP_FBGE: {
- /* clt.un + brfalse */
- guint32 *p = code;
- sparc_fbranch (code, 1, sparc_fbul, 0);
- /* delay slot */
- sparc_nop (code);
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fba, 1, 1);
- sparc_patch (p, (guint8*)code);
- break;
- }
- case OP_FBLE: {
- /* cgt.un + brfalse */
- guint32 *p = code;
- sparc_fbranch (code, 1, sparc_fbug, 0);
- /* delay slot */
- sparc_nop (code);
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fba, 1, 1);
- sparc_patch (p, (guint8*)code);
- break;
- }
- case OP_FBNE_UN:
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fbne, 1, 1);
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fbu, 1, 1);
- break;
- case OP_FBLT_UN:
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fbl, 1, 1);
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fbu, 1, 1);
- break;
- case OP_FBGT_UN:
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fbg, 1, 1);
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fbu, 1, 1);
- break;
- case OP_FBGE_UN:
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fbge, 1, 1);
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fbu, 1, 1);
- break;
- case OP_FBLE_UN:
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fble, 1, 1);
- EMIT_FLOAT_COND_BRANCH (ins, sparc_fbu, 1, 1);
- break;
- case OP_CKFINITE: {
- MonoInst *spill = cfg->arch.float_spill_slot;
- gint32 reg = spill->inst_basereg;
- gint32 offset = spill->inst_offset;
-
- g_assert (spill->opcode == OP_REGOFFSET);
-
- if (!sparc_is_imm13 (offset)) {
- sparc_set (code, offset, sparc_o7);
- sparc_stdf (code, ins->sreg1, reg, sparc_o7);
- sparc_lduh (code, reg, sparc_o7, sparc_o7);
- } else {
- sparc_stdf_imm (code, ins->sreg1, reg, offset);
- sparc_lduh_imm (code, reg, offset, sparc_o7);
- }
- sparc_srl_imm (code, sparc_o7, 4, sparc_o7);
- sparc_and_imm (code, FALSE, sparc_o7, 2047, sparc_o7);
- sparc_cmp_imm (code, sparc_o7, 2047);
- EMIT_COND_SYSTEM_EXCEPTION (ins, sparc_be, "OverflowException");
-#ifdef SPARCV9
- sparc_fmovd (code, ins->sreg1, ins->dreg);
-#else
- sparc_fmovs (code, ins->sreg1, ins->dreg);
- sparc_fmovs (code, ins->sreg1 + 1, ins->dreg + 1);
-#endif
- break;
- }
-
- case OP_MEMORY_BARRIER:
- sparc_membar (code, sparc_membar_all);
- break;
- case OP_LIVERANGE_START: {
- if (cfg->verbose_level > 1)
- printf ("R%d START=0x%x\n", MONO_VARINFO (cfg, ins->inst_c0)->vreg, (int)(code - cfg->native_code));
- MONO_VARINFO (cfg, ins->inst_c0)->live_range_start = code - cfg->native_code;
- break;
- }
- case OP_LIVERANGE_END: {
- if (cfg->verbose_level > 1)
- printf ("R%d END=0x%x\n", MONO_VARINFO (cfg, ins->inst_c0)->vreg, (int)(code - cfg->native_code));
- MONO_VARINFO (cfg, ins->inst_c0)->live_range_end = code - cfg->native_code;
- break;
- }
- case OP_GC_SAFE_POINT:
- break;
-
- default:
-#ifdef __GNUC__
- g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
-#else
- g_warning ("%s:%d: unknown opcode %s\n", __FILE__, __LINE__, mono_inst_name (ins->opcode));
-#endif
- g_assert_not_reached ();
- }
-
- if ((((guint8*)code) - code_start) > max_len) {
- g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %d)",
- mono_inst_name (ins->opcode), max_len, ((guint8*)code) - code_start);
- g_assert_not_reached ();
- }
-
- cpos += max_len;
-
- last_ins = ins;
- }
- set_code_cursor (cfg, code);
-}
-
-void
-mono_arch_register_lowlevel_calls (void)
-{
- mono_register_jit_icall (mono_arch_get_lmf_addr, NULL, TRUE);
-}
-
-void
-mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gboolean run_cctors, MonoError *error)
-{
- MonoJumpInfo *patch_info;
-
- error_init (error);
-
- /* FIXME: Move part of this to arch independent code */
- for (patch_info = ji; patch_info; patch_info = patch_info->next) {
- unsigned char *ip = patch_info->ip.i + code;
- gpointer target;
-
- target = mono_resolve_patch_target (method, domain, code, patch_info, run_cctors, error);
- return_if_nok (error);
-
- switch (patch_info->type) {
- case MONO_PATCH_INFO_NONE:
- continue;
- case MONO_PATCH_INFO_METHOD_JUMP: {
- guint32 *ip2 = (guint32*)ip;
- /* Might already been patched */
- sparc_set_template (ip2, sparc_o7);
- break;
- }
- default:
- break;
- }
- sparc_patch ((guint32*)ip, target);
- }
-}
-
-#error obsolete tracing?
-void*
-mono_arch_instrument_prolog (MonoCompile *cfg, MonoJitICallId func, void *p, gboolean enable_arguments)
-{
- int i;
- guint32 *code = (guint32*)p;
- MonoMethodSignature *sig = mono_method_signature_internal (cfg->method);
- CallInfo *cinfo;
-
- /* Save registers to stack */
- for (i = 0; i < 6; ++i)
- sparc_sti_imm (code, sparc_i0 + i, sparc_fp, ARGS_OFFSET + (i * sizeof (target_mgreg_t)));
-
- cinfo = get_call_info (cfg, sig, FALSE);
-
- /* Save float regs on V9, since they are caller saved */
- for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
- ArgInfo *ainfo = cinfo->args + i;
- gint32 stack_offset;
-
- stack_offset = ainfo->offset + ARGS_OFFSET;
-
- if (ainfo->storage == ArgInFloatReg) {
- if (!sparc_is_imm13 (stack_offset))
- NOT_IMPLEMENTED;
- sparc_stf_imm (code, ainfo->reg, sparc_fp, stack_offset);
- }
- else if (ainfo->storage == ArgInDoubleReg) {
- /* The offset is guaranteed to be aligned by the ABI rules */
- sparc_stdf_imm (code, ainfo->reg, sparc_fp, stack_offset);
- }
- }
-
- sparc_set (code, cfg->method, sparc_o0);
- sparc_add_imm (code, FALSE, sparc_fp, MONO_SPARC_STACK_BIAS, sparc_o1);
-
- mono_add_patch_info (cfg, (guint8*)code-cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, GUINT_TO_POINTER (func));
- EMIT_CALL ();
-
- /* Restore float regs on V9 */
- for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
- ArgInfo *ainfo = cinfo->args + i;
- gint32 stack_offset;
-
- stack_offset = ainfo->offset + ARGS_OFFSET;
-
- if (ainfo->storage == ArgInFloatReg) {
- if (!sparc_is_imm13 (stack_offset))
- NOT_IMPLEMENTED;
- sparc_ldf_imm (code, sparc_fp, stack_offset, ainfo->reg);
- }
- else if (ainfo->storage == ArgInDoubleReg) {
- /* The offset is guaranteed to be aligned by the ABI rules */
- sparc_lddf_imm (code, sparc_fp, stack_offset, ainfo->reg);
- }
- }
-
- g_free (cinfo);
-
- return code;
-}
-
-enum {
- SAVE_NONE,
- SAVE_STRUCT,
- SAVE_ONE,
- SAVE_TWO,
- SAVE_FP
-};
-
-#error obsolete tracing?
-void*
-mono_arch_instrument_epilog (MonoCompile *cfg, MonoJitICallId func, void *p, gboolean enable_arguments)
-{
- guint32 *code = (guint32*)p;
- int save_mode = SAVE_NONE;
- MonoMethod *method = cfg->method;
-
- switch (mini_get_underlying_type (mono_method_signature_internal (method)->ret)->type) {
- case MONO_TYPE_VOID:
- /* special case string .ctor icall */
- if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
- save_mode = SAVE_ONE;
- else
- save_mode = SAVE_NONE;
- break;
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
-#ifdef SPARCV9
- save_mode = SAVE_ONE;
-#else
- save_mode = SAVE_TWO;
-#endif
- break;
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- save_mode = SAVE_FP;
- break;
- case MONO_TYPE_VALUETYPE:
- save_mode = SAVE_STRUCT;
- break;
- default:
- save_mode = SAVE_ONE;
- break;
- }
-
- /* Save the result to the stack and also put it into the output registers */
-
- switch (save_mode) {
- case SAVE_TWO:
- /* V8 only */
- sparc_st_imm (code, sparc_i0, sparc_fp, 68);
- sparc_st_imm (code, sparc_i0, sparc_fp, 72);
- sparc_mov_reg_reg (code, sparc_i0, sparc_o1);
- sparc_mov_reg_reg (code, sparc_i1, sparc_o2);
- break;
- case SAVE_ONE:
- sparc_sti_imm (code, sparc_i0, sparc_fp, ARGS_OFFSET);
- sparc_mov_reg_reg (code, sparc_i0, sparc_o1);
- break;
- case SAVE_FP:
-#ifdef SPARCV9
- sparc_stdf_imm (code, sparc_f0, sparc_fp, ARGS_OFFSET);
-#else
- sparc_stdf_imm (code, sparc_f0, sparc_fp, 72);
- sparc_ld_imm (code, sparc_fp, 72, sparc_o1);
- sparc_ld_imm (code, sparc_fp, 72 + 4, sparc_o2);
-#endif
- break;
- case SAVE_STRUCT:
-#ifdef SPARCV9
- sparc_mov_reg_reg (code, sparc_i0, sparc_o1);
-#else
- sparc_ld_imm (code, sparc_fp, 64, sparc_o1);
-#endif
- break;
- case SAVE_NONE:
- default:
- break;
- }
-
- sparc_set (code, cfg->method, sparc_o0);
-
- mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, GUINT_TO_POINTER (func));
- EMIT_CALL ();
-
- /* Restore result */
-
- switch (save_mode) {
- case SAVE_TWO:
- sparc_ld_imm (code, sparc_fp, 68, sparc_i0);
- sparc_ld_imm (code, sparc_fp, 72, sparc_i0);
- break;
- case SAVE_ONE:
- sparc_ldi_imm (code, sparc_fp, ARGS_OFFSET, sparc_i0);
- break;
- case SAVE_FP:
- sparc_lddf_imm (code, sparc_fp, ARGS_OFFSET, sparc_f0);
- break;
- case SAVE_NONE:
- default:
- break;
- }
-
- return code;
-}
-
-guint8 *
-mono_arch_emit_prolog (MonoCompile *cfg)
-{
- MonoMethod *method = cfg->method;
- MonoMethodSignature *sig;
- MonoInst *inst;
- guint32 *code;
- CallInfo *cinfo;
- guint32 i, offset;
-
- cfg->code_size = 256;
- cfg->native_code = g_malloc (cfg->code_size);
- code = (guint32*)cfg->native_code;
-
- /* FIXME: Generate intermediate code instead */
-
- offset = cfg->stack_offset;
- offset += (16 * sizeof (target_mgreg_t)); /* register save area */
-#ifndef SPARCV9
- offset += 4; /* struct/union return pointer */
-#endif
-
- /* add parameter area size for called functions */
- if (cfg->param_area < (6 * sizeof (target_mgreg_t)))
- /* Reserve space for the first 6 arguments even if it is unused */
- offset += 6 * sizeof (target_mgreg_t);
- else
- offset += cfg->param_area;
-
- /* align the stack size */
- offset = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
-
- /*
- * localloc'd memory is stored between the local variables (whose
- * size is given by cfg->stack_offset), and between the space reserved
- * by the ABI.
- */
- cfg->arch.localloc_offset = offset - cfg->stack_offset;
-
- cfg->stack_offset = offset;
-
-#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
- /* Perform stack touching */
- NOT_IMPLEMENTED;
-#endif
-
- if (!sparc_is_imm13 (- cfg->stack_offset)) {
- /* Can't use sparc_o7 here, since we're still in the caller's frame */
- sparc_set (code, (- cfg->stack_offset), GP_SCRATCH_REG);
- sparc_save (code, sparc_sp, GP_SCRATCH_REG, sparc_sp);
- }
- else
- sparc_save_imm (code, sparc_sp, - cfg->stack_offset, sparc_sp);
-
-/*
- if (strstr (cfg->method->name, "foo")) {
- mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID,
- GUINT_TO_POINTER (MONO_JIT_ICALL_mono_sparc_break));
- sparc_call_simple (code, 0);
- sparc_nop (code);
- }
-*/
-
- sig = mono_method_signature_internal (method);
-
- cinfo = get_call_info (cfg, sig, FALSE);
-
- /* Keep in sync with emit_load_volatile_arguments */
- for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
- ArgInfo *ainfo = cinfo->args + i;
- gint32 stack_offset;
- MonoType *arg_type;
- inst = cfg->args [i];
-
- if (sig->hasthis && (i == 0))
- arg_type = mono_get_object_type ();
- else
- arg_type = sig->params [i - sig->hasthis];
-
- stack_offset = ainfo->offset + ARGS_OFFSET;
-
- /* Save the split arguments so they will reside entirely on the stack */
- if (ainfo->storage == ArgInSplitRegStack) {
- /* Save the register to the stack */
- g_assert (inst->opcode == OP_REGOFFSET);
- if (!sparc_is_imm13 (stack_offset))
- NOT_IMPLEMENTED;
- sparc_st_imm (code, sparc_i5, inst->inst_basereg, stack_offset);
- }
-
- if (!v64 && !m_type_is_byref (arg_type) && (arg_type->type == MONO_TYPE_R8)) {
- /* Save the argument to a dword aligned stack location */
- /*
- * stack_offset contains the offset of the argument on the stack.
- * inst->inst_offset contains the dword aligned offset where the value
- * should be stored.
- */
- if (ainfo->storage == ArgInIRegPair) {
- if (!sparc_is_imm13 (inst->inst_offset + 4))
- NOT_IMPLEMENTED;
- sparc_st_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, inst->inst_offset);
- sparc_st_imm (code, sparc_i0 + ainfo->reg + 1, inst->inst_basereg, inst->inst_offset + 4);
- }
- else
- if (ainfo->storage == ArgInSplitRegStack) {
-#ifdef SPARCV9
- g_assert_not_reached ();
-#endif
- if (stack_offset != inst->inst_offset) {
- /* stack_offset is not dword aligned, so we need to make a copy */
- sparc_st_imm (code, sparc_i5, inst->inst_basereg, inst->inst_offset);
- sparc_ld_imm (code, sparc_fp, stack_offset + 4, sparc_o7);
- sparc_st_imm (code, sparc_o7, inst->inst_basereg, inst->inst_offset + 4);
- }
- }
- else
- if (ainfo->storage == ArgOnStackPair) {
-#ifdef SPARCV9
- g_assert_not_reached ();
-#endif
- if (stack_offset != inst->inst_offset) {
- /* stack_offset is not dword aligned, so we need to make a copy */
- sparc_ld_imm (code, sparc_fp, stack_offset, sparc_o7);
- sparc_st_imm (code, sparc_o7, inst->inst_basereg, inst->inst_offset);
- sparc_ld_imm (code, sparc_fp, stack_offset + 4, sparc_o7);
- sparc_st_imm (code, sparc_o7, inst->inst_basereg, inst->inst_offset + 4);
- }
- }
- else
- g_assert_not_reached ();
- }
- else
- if ((ainfo->storage == ArgInIReg) && (inst->opcode != OP_REGVAR)) {
- /* Argument in register, but need to be saved to stack */
- if (!sparc_is_imm13 (stack_offset))
- NOT_IMPLEMENTED;
- if ((stack_offset - ARGS_OFFSET) & 0x1)
- sparc_stb_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, stack_offset);
- else
- if ((stack_offset - ARGS_OFFSET) & 0x2)
- sparc_sth_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, stack_offset);
- else
- if ((stack_offset - ARGS_OFFSET) & 0x4)
- sparc_st_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, stack_offset);
- else {
- if (v64)
- sparc_stx_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, stack_offset);
- else
- sparc_st_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, stack_offset);
- }
- }
- else
- if ((ainfo->storage == ArgInIRegPair) && (inst->opcode != OP_REGVAR)) {
-#ifdef SPARCV9
- NOT_IMPLEMENTED;
-#endif
- /* Argument in regpair, but need to be saved to stack */
- if (!sparc_is_imm13 (inst->inst_offset + 4))
- NOT_IMPLEMENTED;
- sparc_st_imm (code, sparc_i0 + ainfo->reg, inst->inst_basereg, inst->inst_offset);
- sparc_st_imm (code, sparc_i0 + ainfo->reg + 1, inst->inst_basereg, inst->inst_offset + 4);
- }
- else if ((ainfo->storage == ArgInFloatReg) && (inst->opcode != OP_REGVAR)) {
- if (!sparc_is_imm13 (stack_offset))
- NOT_IMPLEMENTED;
- sparc_stf_imm (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
- }
- else if ((ainfo->storage == ArgInDoubleReg) && (inst->opcode != OP_REGVAR)) {
- /* The offset is guaranteed to be aligned by the ABI rules */
- sparc_stdf_imm (code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
- }
-
- if ((ainfo->storage == ArgInFloatReg) && (inst->opcode == OP_REGVAR)) {
- /* Need to move into the a double precision register */
- sparc_fstod (code, ainfo->reg, ainfo->reg - 1);
- }
-
- if ((ainfo->storage == ArgInSplitRegStack) || (ainfo->storage == ArgOnStack))
- if (inst->opcode == OP_REGVAR)
- /* FIXME: Load the argument into memory */
- NOT_IMPLEMENTED;
- }
-
- g_free (cinfo);
-
- if (cfg->method->save_lmf) {
- gint32 lmf_offset = STACK_BIAS - cfg->arch.lmf_offset;
-
- /* Save ip */
- mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, MONO_PATCH_INFO_IP, NULL);
- sparc_set_template (code, sparc_o7);
- sparc_sti_imm (code, sparc_o7, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ip));
- /* Save sp */
- sparc_sti_imm (code, sparc_sp, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, sp));
- /* Save fp */
- sparc_sti_imm (code, sparc_fp, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebp));
- /* Save method */
- /* FIXME: add a relocation for this */
- sparc_set (code, cfg->method, sparc_o7);
- sparc_sti_imm (code, sparc_o7, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method));
-
- mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID,
- GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_get_lmf_addr));
- EMIT_CALL ();
-
- code = (guint32*)mono_sparc_emit_save_lmf (code, lmf_offset);
- }
-
-#error obsolete tracing?
- if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
- code = (guint32*)mono_arch_instrument_prolog (cfg, MONO_JIT_ICALL_mono_trace_enter_method, code, TRUE);
-
- set_code_cursor (cfg, code);
-
- return (guint8*)code;
-}
-
-void
-mono_arch_emit_epilog (MonoCompile *cfg)
-{
- MonoMethod *method = cfg->method;
- guint32 *code;
- int can_fold = 0;
- int max_epilog_size = 16 + 20 * 4;
-
- if (cfg->method->save_lmf)
- max_epilog_size += 128;
-
- if (mono_jit_trace_calls != NULL)
- max_epilog_size += 50;
-
- code = (guint32 *)realloc_code (cfg, max_epilog_size);
-
-#error obsolete tracing?
- if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
- code = (guint32*)mono_arch_instrument_epilog (cfg, mono_trace_leave_method, code, TRUE);
-
- if (cfg->method->save_lmf) {
- gint32 lmf_offset = STACK_BIAS - cfg->arch.lmf_offset;
-
- code = mono_sparc_emit_restore_lmf (code, lmf_offset);
- }
-
- /*
- * The V8 ABI requires that calls to functions which return a structure
- * return to %i7+12
- */
- if (!v64 && mono_method_signature_internal (cfg->method)->pinvoke && MONO_TYPE_ISSTRUCT(mono_method_signature_internal (cfg->method)->ret))
- sparc_jmpl_imm (code, sparc_i7, 12, sparc_g0);
- else
- sparc_ret (code);
-
- /* Only fold last instruction into the restore if the exit block has an in count of 1
- and the previous block hasn't been optimized away since it may have an in count > 1 */
- if (cfg->bb_exit->in_count == 1 && cfg->bb_exit->in_bb[0]->native_offset != cfg->bb_exit->native_offset)
- can_fold = 1;
-
- /*
- * FIXME: The last instruction might have a branch pointing into it like in
- * int_ceq sparc_i0 <-
- */
- can_fold = 0;
-
- /* Try folding last instruction into the restore */
- if (can_fold && (sparc_inst_op (code [-2]) == 0x2) && (sparc_inst_op3 (code [-2]) == 0x2) && sparc_inst_imm (code [-2]) && (sparc_inst_rd (code [-2]) == sparc_i0)) {
- /* or reg, imm, %i0 */
- int reg = sparc_inst_rs1 (code [-2]);
- int imm = (((gint32)(sparc_inst_imm13 (code [-2]))) << 19) >> 19;
- code [-2] = code [-1];
- code --;
- sparc_restore_imm (code, reg, imm, sparc_o0);
- }
- else
- if (can_fold && (sparc_inst_op (code [-2]) == 0x2) && (sparc_inst_op3 (code [-2]) == 0x2) && (!sparc_inst_imm (code [-2])) && (sparc_inst_rd (code [-2]) == sparc_i0)) {
- /* or reg, reg, %i0 */
- int reg1 = sparc_inst_rs1 (code [-2]);
- int reg2 = sparc_inst_rs2 (code [-2]);
- code [-2] = code [-1];
- code --;
- sparc_restore (code, reg1, reg2, sparc_o0);
- }
- else
- sparc_restore_imm (code, sparc_g0, 0, sparc_g0);
-
- set_code_cursor (cfg, code);
-}
-
-void
-mono_arch_emit_exceptions (MonoCompile *cfg)
-{
- MonoJumpInfo *patch_info;
- guint32 *code;
- int nthrows = 0, i;
- int exc_count = 0;
- guint32 code_size;
- MonoClass *exc_classes [16];
- guint8 *exc_throw_start [16], *exc_throw_end [16];
-
- /* Compute needed space */
- for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
- if (patch_info->type == MONO_PATCH_INFO_EXC)
- exc_count++;
- }
-
- /*
- * make sure we have enough space for exceptions
- */
-#ifdef SPARCV9
- code_size = exc_count * (20 * 4);
-#else
- code_size = exc_count * 24;
-#endif
- code = (guint32*)realloc_code (cfg, code_size);
-
- for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
- switch (patch_info->type) {
- case MONO_PATCH_INFO_EXC: {
- MonoClass *exc_class;
- guint32 *buf, *buf2;
- guint32 throw_ip, type_idx;
- gint32 disp;
-
- sparc_patch ((guint32*)(cfg->native_code + patch_info->ip.i), code);
-
- exc_class = mono_class_load_from_name (mono_defaults.corlib, "System", patch_info->data.name);
- type_idx = m_class_get_type_token (exc_class) - MONO_TOKEN_TYPE_DEF;
- throw_ip = patch_info->ip.i;
-
- /* Find a throw sequence for the same exception class */
- for (i = 0; i < nthrows; ++i)
- if (exc_classes [i] == exc_class)
- break;
-
- if (i < nthrows) {
- guint32 throw_offset = (((guint8*)exc_throw_end [i] - cfg->native_code) - throw_ip) >> 2;
- if (!sparc_is_imm13 (throw_offset))
- sparc_set32 (code, throw_offset, sparc_o1);
-
- disp = (exc_throw_start [i] - (guint8*)code) >> 2;
- g_assert (sparc_is_imm22 (disp));
- sparc_branch (code, 0, sparc_ba, disp);
- if (sparc_is_imm13 (throw_offset))
- sparc_set32 (code, throw_offset, sparc_o1);
- else
- sparc_nop (code);
- patch_info->type = MONO_PATCH_INFO_NONE;
- }
- else {
- /* Emit the template for setting o1 */
- buf = code;
- if (sparc_is_imm13 (((((guint8*)code - cfg->native_code) - throw_ip) >> 2) - 8))
- /* Can use a short form */
- sparc_nop (code);
- else
- sparc_set_template (code, sparc_o1);
- buf2 = code;
-
- if (nthrows < 16) {
- exc_classes [nthrows] = exc_class;
- exc_throw_start [nthrows] = (guint8*)code;
- }
-
- /*
- mono_add_patch_info (cfg, (guint8*)code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID,
- GUINT_TO_POINTER (MONO_JIT_ICALL_mono_sparc_break));
- EMIT_CALL();
- */
-
- /* first arg = type token */
- /* Pass the type index to reduce the size of the sparc_set */
- if (!sparc_is_imm13 (type_idx))
- sparc_set32 (code, type_idx, sparc_o0);
-
- /* second arg = offset between the throw ip and the current ip */
- /* On sparc, the saved ip points to the call instruction */
- disp = (((guint8*)code - cfg->native_code) - throw_ip) >> 2;
- sparc_set32 (buf, disp, sparc_o1);
- while (buf < buf2)
- sparc_nop (buf);
-
- if (nthrows < 16) {
- exc_throw_end [nthrows] = (guint8*)code;
- nthrows ++;
- }
-
- patch_info->data.jit_icall_id = MONO_JIT_ICALL_mono_arch_throw_corlib_exception;
- patch_info->type = MONO_PATCH_INFO_JIT_ICALL_ID;
- patch_info->ip.i = (guint8*)code - cfg->native_code;
-
- EMIT_CALL ();
-
- if (sparc_is_imm13 (type_idx)) {
- /* Put it into the delay slot */
- code --;
- buf = code;
- sparc_set32 (code, type_idx, sparc_o0);
- g_assert (code - buf == 1);
- }
- }
- break;
- }
- default:
- /* do nothing */
- break;
- }
-
- set_code_cursor (cfg, code);
- }
-
- set_code_cursor (cfg, code);
-}
-
-gboolean lmf_addr_key_inited = FALSE;
-
-#ifdef MONO_SPARC_THR_TLS
-thread_key_t lmf_addr_key;
-#else
-pthread_key_t lmf_addr_key;
-#endif
-
-gpointer
-mono_arch_get_lmf_addr (void)
-{
- /* This is perf critical so we bypass the IO layer */
- /* The thr_... functions seem to be somewhat faster */
-#ifdef MONO_SPARC_THR_TLS
- gpointer res;
- thr_getspecific (lmf_addr_key, &res);
- return res;
-#else
- return pthread_getspecific (lmf_addr_key);
-#endif
-}
-
-#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
-
-/*
- * There seems to be no way to determine stack boundaries under solaris,
- * so it's not possible to determine whenever a SIGSEGV is caused by stack
- * overflow or not.
- */
-#error "--with-sigaltstack=yes not supported on solaris"
-
-#endif
-
-void
-mono_arch_tls_init (void)
-{
- MonoJitTlsData *jit_tls;
-
- if (!lmf_addr_key_inited) {
- int res;
-
- lmf_addr_key_inited = TRUE;
-
-#ifdef MONO_SPARC_THR_TLS
- res = thr_keycreate (&lmf_addr_key, NULL);
-#else
- res = pthread_key_create (&lmf_addr_key, NULL);
-#endif
- g_assert (res == 0);
-
- }
-
- jit_tls = mono_get_jit_tls ();
-
-#ifdef MONO_SPARC_THR_TLS
- thr_setspecific (lmf_addr_key, &jit_tls->lmf);
-#else
- pthread_setspecific (lmf_addr_key, &jit_tls->lmf);
-#endif
-}
-
-void
-mono_arch_finish_init (void)
-{
-}
-
-MonoInst*
-mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
-{
- MonoInst *ins = NULL;
-
- return ins;
-}
-
-/*
- * mono_arch_get_argument_info:
- * @csig: a method signature
- * @param_count: the number of parameters to consider
- * @arg_info: an array to store the result infos
- *
- * Gathers information on parameters such as size, alignment and
- * padding. arg_info should be large enought to hold param_count + 1 entries.
- *
- * Returns the size of the activation frame.
- */
-int
-mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
-{
- int k, align;
- CallInfo *cinfo;
- ArgInfo *ainfo;
-
- cinfo = get_call_info (NULL, csig, FALSE);
-
- if (csig->hasthis) {
- ainfo = &cinfo->args [0];
- arg_info [0].offset = ARGS_OFFSET - MONO_SPARC_STACK_BIAS + ainfo->offset;
- }
-
- for (k = 0; k < param_count; k++) {
- ainfo = &cinfo->args [k + csig->hasthis];
-
- arg_info [k + 1].offset = ARGS_OFFSET - MONO_SPARC_STACK_BIAS + ainfo->offset;
- arg_info [k + 1].size = mono_type_size (csig->params [k], &align);
- }
-
- g_free (cinfo);
-
- return 0;
-}
-
-host_mgreg_t
-mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
-{
- /* FIXME: implement */
- g_assert_not_reached ();
-}
-
-host_mgreg_t*
-mono_arch_context_get_int_reg_address (MonoContext *ctx, int reg)
-{
- /* FIXME: implement */
- g_assert_not_reached ();
-}
-
-gboolean
-mono_arch_opcode_supported (int opcode)
-{
- return FALSE;
-}
-
-gboolean
-mono_arch_tailcall_supported (MonoCompile *cfg, MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig, gboolean virtual_)
-{
- return FALSE;
-}
-
-gpointer
-mono_arch_load_function (MonoJitICallId jit_icall_id)
-{
- return NULL;
-}
+++ /dev/null
-/**
- * \file
- */
-
-#ifndef __MONO_MINI_SPARC_H__
-#define __MONO_MINI_SPARC_H__
-
-#include <mono/arch/sparc/sparc-codegen.h>
-#include <mono/utils/mono-context.h>
-
-#include <glib.h>
-
-#define MONO_ARCH_CPU_SPEC sparc_desc
-
-#define MONO_MAX_IREGS 32
-#define MONO_MAX_FREGS 32
-
-/* Parameters used by the register allocator */
-
-/*
- * Use %o0..%o5 as local registers, plus %l7 since we need an extra register for
- * holding the sreg1 in call instructions.
- */
-#define MONO_ARCH_CALLEE_REGS ((1 << sparc_o0) | (1 << sparc_o1) | (1 << sparc_o2) | (1 << sparc_o3) | (1 << sparc_o4) | (1 << sparc_o5) | (1 << sparc_l7))
-
-#define MONO_ARCH_CALLEE_SAVED_REGS ((~MONO_ARCH_CALLEE_REGS) & ~(1 << sparc_g1))
-
-#ifdef SPARCV9
-/* Use %d34..%d62 as the double precision floating point local registers */
-/* %d32 has the same encoding as %f1, so %d36%d38 == 0b1010 == 0xa */
-#define MONO_ARCH_CALLEE_FREGS (0xaaaaaaa8)
-#else
-/* Use %f2..%f30 as the double precision floating point local registers */
-#define MONO_ARCH_CALLEE_FREGS (0x55555554)
-#endif
-
-#define MONO_ARCH_CALLEE_SAVED_FREGS 0
-
-#define MONO_ARCH_USE_FPSTACK FALSE
-#ifdef SPARCV9
-#define MONO_ARCH_INST_FIXED_REG(desc) ((desc == 'o') ? sparc_o0 : -1)
-#else
-#define MONO_ARCH_INST_FIXED_REG(desc) ((desc == 'o') ? sparc_o0 : ((desc == 'l') ? sparc_o1 : -1))
-#endif
-#define MONO_ARCH_INST_SREG2_MASK(ins) (0)
-
-#ifdef SPARCV9
-#define MONO_ARCH_INST_IS_REGPAIR(desc) FALSE
-#define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (-1)
-#else
-#define MONO_ARCH_INST_IS_REGPAIR(desc) ((desc == 'l') || (desc == 'L'))
-#define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (((desc == 'l') ? sparc_o0 : (desc == 'L' ? (hreg1 + 1) : -1)))
-#endif
-
-#if TARGET_SIZEOF_VOID_P == 8
-#define MONO_ARCH_FRAME_ALIGNMENT 16
-#else
-#define MONO_ARCH_FRAME_ALIGNMENT 8
-#endif
-
-#define MONO_ARCH_CODE_ALIGNMENT 32
-
-#ifdef SPARCV9
-#define MONO_SPARC_STACK_BIAS 2047
-#else
-#define MONO_SPARC_STACK_BIAS 0
-#endif
-
-struct MonoLMF {
- gpointer previous_lmf;
- gpointer lmf_addr;
- MonoMethod *method;
- gpointer ip;
- gpointer sp;
- gpointer ebp;
-};
-
-typedef struct MonoCompileArch {
- gint32 lmf_offset;
- gint32 localloc_offset;
- void *float_spill_slot;
-} MonoCompileArch;
-
-#define MONO_INIT_CONTEXT_FROM_FUNC(ctx,start_func) do { \
- MONO_CONTEXT_SET_IP ((ctx), (start_func)); \
- MONO_CONTEXT_SET_BP ((ctx), __builtin_frame_address (0)); \
- MONO_CONTEXT_SET_SP ((ctx), __builtin_frame_address (0)); \
- } while (0)
-
-#define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf) do { (lmf)->ebp = -1; } while (0)
-
-#define MONO_ARCH_USE_SIGACTION 1
-
-#ifdef ENABLE_SIGALTSTACK
-/*#define MONO_ARCH_SIGSEGV_ON_ALTSTACK*/
-#endif
-
-#define MONO_ARCH_EMULATE_FCONV_TO_U8 1
-#define MONO_ARCH_EMULATE_FCONV_TO_I8 1
-#define MONO_ARCH_EMULATE_LCONV_TO_R8 1
-#define MONO_ARCH_EMULATE_LCONV_TO_R4 1
-#define MONO_ARCH_EMULATE_CONV_R8_UN 1
-#define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
-#define MONO_ARCH_EMULATE_FREM 1
-#define MONO_ARCH_NEED_DIV_CHECK 1
-#define MONO_ARCH_IMT_REG sparc_g1
-#define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
-#define MONO_ARCH_HAVE_TLS_INIT 1
-
-// Does the ABI have a volatile non-parameter register, so tailcall
-// can pass context to generics or interfaces?
-#define MONO_ARCH_HAVE_VOLATILE_NON_PARAM_REGISTER 0 // FIXME?
-
-void mono_arch_tls_init (void);
-
-#ifdef SPARCV9
-#define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
-#endif
-
-#ifndef __GNUC__
-/* assume Sun compiler if not GCC */
-static void * __builtin_return_address(int depth)
-{
- asm("ta 3");
- asm("tst %i0");
- asm("be retAddr_End");
- asm("mov %fp, %l0");
- asm("retAddr_Start:");
- asm("sub %i0, 1, %i0");
- asm("tst %i0");
- asm("bne retAddr_Start");
-#if SPARCV9
- asm("ldx [%l0+2159], %l0");
- asm("retAddr_End:");
- asm("ldx [%l0+2167], %i0");
-#else
- asm("ld [%l0+56], %l0");
- asm("retAddr_End:");
- asm("ld [%l0+60], %i0");
-#endif
-}
-
-static void * __builtin_frame_address(int depth)
-{
- asm("ta 3");
- asm("tst %i0");
- asm("be frameAddr_End");
- asm("mov %fp, %l0");
- asm("frameAddr_Start:");
- asm("sub %i0, 1, %i0");
- asm("tst %i0");
- asm("bne frameAddr_Start");
-#if SPARCV9
- asm("ldx [%l0+2159], %l0");
- asm("frameAddr_End:");
- asm("ldx [%l0+2159], %i0");
-#else
- asm("ld [%l0+56], %l0");
- asm("frameAddr_End:");
- asm("ld [%l0+56], %i0");
-#endif
-}
-#endif
-
-gboolean mono_sparc_is_virtual_call (guint32 *code);
-
-void mono_sparc_flushw (void);
-
-gboolean mono_sparc_is_v9 (void);
-
-gboolean mono_sparc_is_sparc64 (void);
-
-struct MonoCompile;
-
-guint32* mono_sparc_emit_save_lmf (guint32* code, guint32 lmf_offset);
-
-guint32* mono_sparc_emit_restore_lmf (guint32 *code, guint32 lmf_offset);
-
-#endif /* __MONO_MINI_SPARC_H__ */
#endif /* ENABLE_SIGALTSTACK */
#endif /* !HOST_WIN32 */
-#define MONO_ARCH_SUPPORT_TASKLETS 1
-
/* we should lower this size and make sure we don't call heavy stack users in the segv handler */
#if defined(__APPLE__)
#define MONO_ARCH_SIGNAL_STACK_SIZE MINSIGSTKSZ
#define MINI_DEBUG(level,limit,code) do {if (G_UNLIKELY ((level) >= (limit))) code} while (0)
#endif
-#if !defined(DISABLE_TASKLETS) && defined(MONO_ARCH_SUPPORT_TASKLETS)
-#if defined(__GNUC__)
-#define MONO_SUPPORT_TASKLETS 1
-#elif defined(HOST_WIN32)
-#define MONO_SUPPORT_TASKLETS 1
-// Replace some gnu intrinsics needed for tasklets with MSVC equivalents.
-#define __builtin_extract_return_addr(x) x
-#define __builtin_return_address(x) _ReturnAddress()
-#define __builtin_frame_address(x) _AddressOfReturnAddress()
-#endif
-#endif
-
#if ENABLE_LLVM
#define COMPILE_LLVM(cfg) ((cfg)->compile_llvm)
#define LLVM_ENABLED TRUE
+++ /dev/null
-using System;
-using Mono.Simd;
-using System.Threading;
-
-class A {
- public void Print() { Console.WriteLine("A"); }
-}
-
-class B : A {
- public void Print() { Console.WriteLine("B"); }
-}
-
-class ThreadRunner {
- public Int32 Inc2(Int32 a) { return Inc1(a); }
- public Int32 Inc1(Int32 a) { return a + 2; }
- public void PrintA(A a) { a.Print(); ((B)a).Print(); }
- public void Run() {
- Console.WriteLine("Running thread" );
- B b = new B();
- Int32 a=0;
- for(int i = 0; i < 1000000; i++) {
- a = Inc2(a);
- if(i % 100000 == 0) PrintA(b);
- }
- Console.WriteLine("Ending thread");
- }
-}
-
-
-class Extensions { public static string BogusProperty { get; set; } }
-
-class RuntimeServices {
- public System.Reflection.MemberInfo[] members = typeof(Extensions).GetMembers();
- public void Run() {
- foreach (var m in members) System.Console.WriteLine(m);
- }
-}
-
-class Tests {
- struct myvt {
- public int X;
- public int Y;
- }
-
- static int test_0_vector4i_cmp_gt () {
- Vector4i a = new Vector4i (10, 5, 12, -1);
- Vector4i b = new Vector4i (-1, 5, 10, 10);
-
- Vector4i c = a.CompareGreaterThan (b);
-
- if (c.X != -1)
- return 1;
- if (c.Y != 0)
- return 2;
- if (c.Z != -1)
- return 3;
- if (c.W != 0)
- return 4;
- return 0;
- }
-
- static myvt CompareGT(myvt a, myvt b) {
- myvt r;
- r.X = a.X > b.X ? -1 : 0;
- r.Y = a.Y > b.Y ? -1 : 0;
- return r;
- }
-
- static int test_0_struct2i_cmp_gt() {
- myvt a;
- myvt b;
- a.X = 10;
- a.Y = 5;
- b.X = -1;
- b.Y = 5;
- myvt c = CompareGT(a, b);
- if (c.X != -1)
- return 1;
- if (c.Y != 0)
- return 2;
- return 0;
- }
-
- static int vararg_sum(params int[] args) {
- int sum = 0;
- foreach(int arg in args) {
- sum += arg;
- }
- return sum;
- }
- static int test_21_vararg_test() {
- int sum = 0;
- sum += vararg_sum();
- sum += vararg_sum(1);
- sum += vararg_sum(2, 3);
- sum += vararg_sum(4, 5, 6);
- return sum;
- }
-
- static int test_0_threads() {
- // Run a bunch of threads, make them JIT some code and
- // do some casts
- ThreadRunner runner = new ThreadRunner();
- Thread[] threads = new Thread[10];
- for (int i = 0; i < 10; i++) {
- threads[i] = new Thread(new ThreadStart(runner.Run));
- threads[i].Start();
- }
- for (int i = 0; i < 10; i++) {
- threads[i].Join();
- }
- return 0;
- }
-
-
- static int test_0_reflection() {
- RuntimeServices r = new RuntimeServices();
- r.Run();
- return 0;
- }
-
- public class BaseClass {
- }
-
- public class LongClass : BaseClass {
- public long Value;
- public LongClass(long val) { Value = val; }
- }
-
- static public long add_two_LongClass(BaseClass l1, BaseClass l2) {
- long l = checked (((LongClass)l1).Value + ((LongClass)l2).Value);
- return l;
- }
-
- static int test_0_laddcc() {
- long l = add_two_LongClass(new LongClass(System.Int64.MinValue), new LongClass(1234));
- if (l == 1234)
- return 1;
- return 0;
- }
-
- public static int Main(String[] args) {
- return TestDriver.RunTests(typeof(Tests));
- }
-}
+++ /dev/null
-/**
- * \file
- * JIT trampoline code for MIPS
- *
- * Authors:
- * Mark Mason (mason@broadcom.com)
- *
- * Based on tramp-ppc.c by:
- * Dietmar Maurer (dietmar@ximian.com)
- * Paolo Molaro (lupus@ximian.com)
- * Carlos Valiente <yo@virutass.net>
- *
- * (C) 2006 Broadcom
- * (C) 2001 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-
-#include <mono/metadata/abi-details.h>
-#include <mono/metadata/marshal.h>
-#include <mono/metadata/tabledefs.h>
-#include <mono/arch/mips/mips-codegen.h>
-
-#include "mini.h"
-#include "mini-mips.h"
-#include "mini-runtime.h"
-#include "mono/utils/mono-tls-inline.h"
-
-/*
- * get_unbox_trampoline:
- * @m: method pointer
- * @addr: pointer to native code for @m
- *
- * when value type methods are called through the vtable we need to unbox the
- * this argument. This method returns a pointer to a trampoline which does
- * unboxing before calling the method
- */
-gpointer
-mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
-{
- guint8 *code, *start;
- MonoMemoryManager *mem_manager = m_method_get_mem_manager (m);
-
- start = code = mono_mem_manager_code_reserve (mem_manager, 20);
-
- mips_load (code, mips_t9, addr);
- /* The this pointer is kept in a0 */
- mips_addiu (code, mips_a0, mips_a0, MONO_ABI_SIZEOF (MonoObject));
- mips_jr (code, mips_t9);
- mips_nop (code);
-
- mono_arch_flush_icache (start, code - start);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m));
-
- g_assert ((code - start) <= 20);
- /*g_print ("unbox trampoline at %d for %s:%s\n", this_pos, m->klass->name, m->name);
- g_print ("unbox code is at %p for method at %p\n", start, addr);*/
-
- mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), NULL);
-
- return start;
-}
-
-void
-mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr)
-{
- guint32 *code = (guint32*)orig_code;
-
- /* Locate the address of the method-specific trampoline.
- The call using the vtable slot that took the processing flow to
- 'arch_create_jit_trampoline' looks something like one of these:
-
- jal XXXXYYYY
- nop
-
- lui t9, XXXX
- addiu t9, YYYY
- jalr t9
- nop
-
- On entry, 'code' points just after one of the above sequences.
- */
-
- /* The jal case */
- if ((code[-2] >> 26) == 0x03) {
- //g_print ("direct patching\n");
- mips_patch ((code-2), (gsize)addr);
- return;
- }
- /* Look for the jalr */
- if ((code[-2] & 0xfc1f003f) == 0x00000009) {
- /* The lui / addiu / jalr case */
- if ((code [-4] >> 26) == 0x0f && (code [-3] >> 26) == 0x09
- && (code [-2] >> 26) == 0) {
- mips_patch ((code-4), (gsize)addr);
- return;
- }
- }
- g_print("error: bad patch at 0x%08x\n", code);
- g_assert_not_reached ();
-}
-
-void
-mono_arch_patch_plt_entry (guint8 *code, gpointer *got, host_mgreg_t *regs, guint8 *addr)
-{
- g_assert_not_reached ();
-}
-
-/* Stack size for trampoline function
- * MIPS_MINIMAL_STACK_SIZE + 16 (args + alignment to mips_magic_trampoline)
- * + MonoLMF + 14 fp regs + 13 gregs + alignment
- * #define STACK (MIPS_MINIMAL_STACK_SIZE + 4 * sizeof (gulong) + sizeof (MonoLMF) + 14 * sizeof (double) + 13 * (sizeof (gulong)))
- * STACK would be 444 for 32 bit darwin
- */
-
-#define STACK (int)(ALIGN_TO(4*IREG_SIZE + 8 + sizeof(MonoLMF) + 32, 8))
-
-/*
- * Stack frame description when the generic trampoline is called.
- * caller frame
- * --------------------
- * MonoLMF
- * -------------------
- * Saved FP registers 0-13
- * -------------------
- * Saved general registers 0-12
- * -------------------
- * param area for 3 args to mips_magic_trampoline
- * -------------------
- * linkage area
- * -------------------
- */
-guchar*
-mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot)
-{
- const char *tramp_name;
- guint8 *buf, *tramp, *code = NULL;
- int i, lmf;
- GSList *unwind_ops = NULL;
- MonoJumpInfo *ji = NULL;
- int max_code_len = 768;
-
- /* AOT not supported on MIPS yet */
- g_assert (!aot);
-
- /* Now we'll create in 'buf' the MIPS trampoline code. This
- is the trampoline code common to all methods */
-
- code = buf = mono_global_codeman_reserve (max_code_len);
-
- /* Allocate the stack frame, and save the return address */
- mips_addiu (code, mips_sp, mips_sp, -STACK);
- mips_sw (code, mips_ra, mips_sp, STACK + MIPS_RET_ADDR_OFFSET);
-
- /* we build the MonoLMF structure on the stack - see mini-mips.h */
- /* offset of MonoLMF from sp */
- lmf = STACK - sizeof (MonoLMF) - 8;
-
- for (i = 0; i < MONO_MAX_IREGS; i++)
- MIPS_SW (code, i, mips_sp, lmf + G_STRUCT_OFFSET (MonoLMF, iregs[i]));
- for (i = 0; i < MONO_MAX_FREGS; i++)
- MIPS_SWC1 (code, i, mips_sp, lmf + G_STRUCT_OFFSET (MonoLMF, fregs[i]));
-
- /* Set the magic number */
- mips_load_const (code, mips_at, MIPS_LMF_MAGIC2);
- mips_sw (code, mips_at, mips_sp, lmf + G_STRUCT_OFFSET(MonoLMF, magic));
-
- /* Save caller sp */
- mips_addiu (code, mips_at, mips_sp, STACK);
- MIPS_SW (code, mips_at, mips_sp, lmf + G_STRUCT_OFFSET (MonoLMF, iregs[mips_sp]));
-
- /* save method info (it was in t8) */
- mips_sw (code, mips_t8, mips_sp, lmf + G_STRUCT_OFFSET(MonoLMF, method));
-
- /* save the IP (caller ip) */
- if (tramp_type == MONO_TRAMPOLINE_JUMP) {
- mips_sw (code, mips_zero, mips_sp, lmf + G_STRUCT_OFFSET(MonoLMF, eip));
- } else {
- mips_sw (code, mips_ra, mips_sp, lmf + G_STRUCT_OFFSET(MonoLMF, eip));
- }
-
- /* jump to mono_get_lmf_addr here */
- mips_load (code, mips_t9, mono_get_lmf_addr);
- mips_jalr (code, mips_t9, mips_ra);
- mips_nop (code);
-
- /* v0 now points at the (MonoLMF **) for the current thread */
-
- /* new_lmf->lmf_addr = lmf_addr -- useful when unwinding */
- mips_sw (code, mips_v0, mips_sp, lmf + G_STRUCT_OFFSET(MonoLMF, lmf_addr));
-
- /* new_lmf->previous_lmf = *lmf_addr */
- mips_lw (code, mips_at, mips_v0, 0);
- mips_sw (code, mips_at, mips_sp, lmf + G_STRUCT_OFFSET(MonoLMF, previous_lmf));
-
- /* *(lmf_addr) = new_lmf */
- mips_addiu (code, mips_at, mips_sp, lmf);
- mips_sw (code, mips_at, mips_v0, 0);
-
- /*
- * Now we're ready to call mips_magic_trampoline ().
- */
-
- /* Arg 1: pointer to registers so that the magic trampoline can
- * access what we saved above
- */
- mips_addiu (code, mips_a0, mips_sp, lmf + G_STRUCT_OFFSET (MonoLMF, iregs[0]));
-
- /* Arg 2: code (next address to the instruction that called us) */
- if (tramp_type == MONO_TRAMPOLINE_JUMP) {
- mips_move (code, mips_a1, mips_zero);
- } else {
- mips_lw (code, mips_a1, mips_sp, STACK + MIPS_RET_ADDR_OFFSET);
- }
-
- /* Arg 3: MonoMethod *method. */
- mips_lw (code, mips_a2, mips_sp, lmf + G_STRUCT_OFFSET (MonoLMF, method));
-
- /* Arg 4: Trampoline */
- mips_move (code, mips_a3, mips_zero);
-
- /* Now go to the trampoline */
- tramp = (guint8*)mono_get_trampoline_func (tramp_type);
- mips_load (code, mips_t9, (guint32)tramp);
- mips_jalr (code, mips_t9, mips_ra);
- mips_nop (code);
-
- /* Code address is now in v0, move it to at */
- mips_move (code, mips_at, mips_v0);
-
- /*
- * Now unwind the MonoLMF
- */
-
- /* t0 = current_lmf->previous_lmf */
- mips_lw (code, mips_t0, mips_sp, lmf + G_STRUCT_OFFSET(MonoLMF, previous_lmf));
- /* t1 = lmf_addr */
- mips_lw (code, mips_t1, mips_sp, lmf + G_STRUCT_OFFSET(MonoLMF, lmf_addr));
- /* (*lmf_addr) = previous_lmf */
- mips_sw (code, mips_t0, mips_t1, 0);
-
- /* Restore the callee-saved & argument registers */
- for (i = 0; i < MONO_MAX_IREGS; i++) {
- if ((MONO_ARCH_CALLEE_SAVED_REGS | MONO_ARCH_CALLEE_REGS | MIPS_ARG_REGS) & (1 << i))
- MIPS_LW (code, i, mips_sp, lmf + G_STRUCT_OFFSET (MonoLMF, iregs[i]));
- }
- for (i = 0; i < MONO_MAX_FREGS; i++)
- MIPS_LWC1 (code, i, mips_sp, lmf + G_STRUCT_OFFSET (MonoLMF, fregs[i]));
-
- /* Non-standard function epilogue. Instead of doing a proper
- * return, we just jump to the compiled code.
- */
- /* Restore ra & stack pointer, and jump to the code */
-
- if (tramp_type == MONO_TRAMPOLINE_RGCTX_LAZY_FETCH)
- mips_move (code, mips_v0, mips_at);
- mips_lw (code, mips_ra, mips_sp, STACK + MIPS_RET_ADDR_OFFSET);
- mips_addiu (code, mips_sp, mips_sp, STACK);
- if (MONO_TRAMPOLINE_TYPE_MUST_RETURN (tramp_type))
- mips_jr (code, mips_ra);
- else
- mips_jr (code, mips_at);
- mips_nop (code);
-
- /* Flush instruction cache, since we've generated code */
- mono_arch_flush_icache (buf, code - buf);
- MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
-
- /* Sanity check */
- g_assert ((code - buf) <= max_code_len);
-
- g_assert (info);
- tramp_name = mono_get_generic_trampoline_name (tramp_type);
- *info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
-
- return buf;
-}
-
-gpointer
-mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoMemoryManager *mem_manager, guint32 *code_len)
-{
- guint8 *code, *buf, *tramp;
-
- tramp = mono_get_trampoline_code (tramp_type);
-
- code = buf = mono_mem_manager_code_reserve (mem_manager, 32);
-
- /* Prepare the jump to the generic trampoline code
- * mono_arch_create_trampoline_code() knows we're putting this in t8
- */
- mips_load (code, mips_t8, arg1);
-
- /* Now jump to the generic trampoline code */
- mips_load (code, mips_at, tramp);
- mips_jr (code, mips_at);
- mips_nop (code);
-
- /* Flush instruction cache, since we've generated code */
- mono_arch_flush_icache (buf, code - buf);
- MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type)));
-
- g_assert ((code - buf) <= 32);
-
- if (code_len)
- *code_len = code - buf;
-
- return buf;
-}
-
-gpointer
-mono_arch_get_static_rgctx_trampoline (MonoMemoryManager *mem_manager, gpointer arg, gpointer addr)
-{
- guint8 *code, *start;
- int buf_len;
-
- buf_len = 24;
-
- start = code = mono_mem_manager_code_reserve (mem_manager, buf_len);
-
- mips_load (code, MONO_ARCH_RGCTX_REG, arg);
- mips_load (code, mips_at, addr);
- mips_jr (code, mips_at);
- mips_nop (code);
-
- g_assert ((code - start) <= buf_len);
-
- mono_arch_flush_icache (start, code - start);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
-
- mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), NULL);
-
- return start;
-}
-
-gpointer
-mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot)
-{
- guint8 *tramp;
- guint8 *code, *buf;
- int tramp_size;
- guint32 code_len;
- guint8 **rgctx_null_jumps;
- int depth, index;
- int i, njumps;
- gboolean mrgctx;
- MonoJumpInfo *ji = NULL;
- GSList *unwind_ops = NULL;
-
- mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
- index = MONO_RGCTX_SLOT_INDEX (slot);
- if (mrgctx)
- index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (target_mgreg_t);
- for (depth = 0; ; ++depth) {
- int size = mono_class_rgctx_get_array_size (depth, mrgctx);
-
- if (index < size - 1)
- break;
- index -= size - 1;
- }
-
- tramp_size = 64 + 16 * depth;
-
- code = buf = mono_global_codeman_reserve (tramp_size);
-
- mono_add_unwind_op_def_cfa (unwind_ops, code, buf, mips_sp, 0);
-
- rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2));
- njumps = 0;
-
- /* The vtable/mrgctx is in a0 */
- g_assert (MONO_ARCH_VTABLE_REG == mips_a0);
- if (mrgctx) {
- /* get mrgctx ptr */
- mips_move (code, mips_a1, mips_a0);
- } else {
- /* load rgctx ptr from vtable */
- g_assert (mips_is_imm16 (MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context)));
- mips_lw (code, mips_a1, mips_a0, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context));
- /* is the rgctx ptr null? */
- /* if yes, jump to actual trampoline */
- rgctx_null_jumps [njumps ++] = code;
- mips_beq (code, mips_a1, mips_zero, 0);
- mips_nop (code);
- }
-
- for (i = 0; i < depth; ++i) {
- /* load ptr to next array */
- if (mrgctx && i == 0) {
- g_assert (mips_is_imm16 (MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT));
- mips_lw (code, mips_a1, mips_a1, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT);
- } else {
- mips_lw (code, mips_a1, mips_a1, 0);
- }
- /* is the ptr null? */
- /* if yes, jump to actual trampoline */
- rgctx_null_jumps [njumps ++] = code;
- mips_beq (code, mips_a1, mips_zero, 0);
- mips_nop (code);
- }
-
- /* fetch slot */
- g_assert (mips_is_imm16 (sizeof (target_mgreg_t) * (index + 1)));
- mips_lw (code, mips_a1, mips_a1, sizeof (target_mgreg_t) * (index + 1));
- /* is the slot null? */
- /* if yes, jump to actual trampoline */
- rgctx_null_jumps [njumps ++] = code;
- mips_beq (code, mips_a1, mips_zero, 0);
- mips_nop (code);
- /* otherwise return, result is in R1 */
- mips_move (code, mips_v0, mips_a1);
- mips_jr (code, mips_ra);
- mips_nop (code);
-
- g_assert (njumps <= depth + 2);
- for (i = 0; i < njumps; ++i)
- mips_patch ((guint32*)rgctx_null_jumps [i], (guint32)code);
-
- g_free (rgctx_null_jumps);
-
- /* Slowpath */
-
- /* The vtable/mrgctx is still in a0 */
-
- if (aot) {
- ji = mono_patch_info_list_prepend (ji, code - buf, MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR, GUINT_TO_POINTER (slot));
- mips_load (code, mips_at, 0);
- mips_jr (code, mips_at);
- mips_nop (code);
- } else {
- MonoMemoryManager *mem_manager = mini_get_default_mem_manager ();
- tramp = (guint8*)mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mem_manager, &code_len);
- mips_load (code, mips_at, tramp);
- mips_jr (code, mips_at);
- mips_nop (code);
- }
-
- mono_arch_flush_icache (buf, code - buf);
- MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
-
- g_assert (code - buf <= tramp_size);
-
- if (info) {
- char *name = mono_get_rgctx_fetch_trampoline_name (slot);
- *info = mono_tramp_info_create (name, buf, code - buf, ji, unwind_ops);
- g_free (name);
- }
-
- return buf;
-}
+++ /dev/null
-/**
- * \file
- * JIT trampoline code for Sparc
- *
- * Authors:
- * Mark Crichton (crichton@gimp.org)
- * Dietmar Maurer (dietmar@ximian.com)
- *
- * (C) 2003 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-
-#include <mono/arch/sparc/sparc-codegen.h>
-#include <mono/metadata/marshal.h>
-#include <mono/metadata/tabledefs.h>
-
-#include "mini.h"
-#include "mini-sparc.h"
-#include "jit-icalls.h"
-#include "mono/utils/mono-tls-inline.h"
-
-/*
- * mono_arch_get_unbox_trampoline:
- * @m: method pointer
- * @addr: pointer to native code for @m
- *
- * when value type methods are called through the vtable we need to unbox the
- * this argument. This method returns a pointer to a trampoline which does
- * unboxing before calling the method
- */
-gpointer
-mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
-{
- MonoMemoryManager *mem_manager = m_method_get_mem_manager (m);
- guint8 *code, *start;
- int reg;
-
- start = code = mono_mem_manager_code_reserve (mem_manager, 36);
-
- /* This executes in the context of the caller, hence o0 */
- sparc_add_imm (code, 0, sparc_o0, MONO_ABI_SIZEOF (MonoObject), sparc_o0);
-#ifdef SPARCV9
- reg = sparc_g4;
-#else
- reg = sparc_g1;
-#endif
- sparc_set (code, addr, reg);
- sparc_jmpl (code, reg, sparc_g0, sparc_g0);
- sparc_nop (code);
-
- g_assert ((code - start) <= 36);
-
- mono_arch_flush_icache (start, code - start);
- MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m));
-
- mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), NULL);
-
- return start;
-}
-
-void
-mono_arch_patch_callsite (guint8 *method_start, guint8 *code, guint8 *addr)
-{
- if (sparc_inst_op (*(guint32*)code) == 0x1) {
- sparc_call_simple (code, (guint8*)addr - (guint8*)code);
- }
-}
-
-void
-mono_arch_patch_plt_entry (guint8 *code, gpointer *got, host_mgreg_t *regs, guint8 *addr)
-{
- g_assert_not_reached ();
-}
-
-guchar*
-mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot)
-{
- guint8 *buf, *code, *tramp_addr;
- guint32 lmf_offset, regs_offset, method_reg, i;
- gboolean has_caller;
-
- g_assert (!aot);
- *info = NULL;
-
- if (tramp_type == MONO_TRAMPOLINE_JUMP)
- has_caller = FALSE;
- else
- has_caller = TRUE;
-
- code = buf = mono_global_codeman_reserve (1024);
-
- sparc_save_imm (code, sparc_sp, -1608, sparc_sp);
-
-#ifdef SPARCV9
- method_reg = sparc_g4;
-#else
- method_reg = sparc_g1;
-#endif
-
- regs_offset = MONO_SPARC_STACK_BIAS + 1000;
-
- /* Save r1 needed by the IMT code */
- sparc_sti_imm (code, sparc_g1, sparc_sp, regs_offset + (sparc_g1 * sizeof (target_mgreg_t)));
-
- /*
- * sparc_g5 contains the return address, the trampoline argument is stored in the
- * instruction stream after the call.
- */
- sparc_ld_imm (code, sparc_g5, 8, method_reg);
-
-#ifdef SPARCV9
- /* Save fp regs since they are not preserved by calls */
- for (i = 0; i < 16; i ++)
- sparc_stdf_imm (code, sparc_f0 + (i * 2), sparc_sp, MONO_SPARC_STACK_BIAS + 320 + (i * 8));
-#endif
-
- /* We receive the method address in %r1, so save it here */
- sparc_sti_imm (code, method_reg, sparc_sp, MONO_SPARC_STACK_BIAS + 200);
-
- /* Save lmf since compilation can raise exceptions */
- lmf_offset = MONO_SPARC_STACK_BIAS - sizeof (MonoLMF);
-
- /* Save the data for the parent (managed) frame */
-
- /* Save ip */
- sparc_sti_imm (code, sparc_i7, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ip));
- /* Save sp */
- sparc_sti_imm (code, sparc_fp, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, sp));
- /* Save fp */
- /* Load previous fp from the saved register window */
- sparc_flushw (code);
- sparc_ldi_imm (code, sparc_fp, MONO_SPARC_STACK_BIAS + (sparc_i6 - 16) * sizeof (target_mgreg_t), sparc_o7);
- sparc_sti_imm (code, sparc_o7, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebp));
- /* Save method */
- sparc_sti_imm (code, method_reg, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method));
-
- sparc_set (code, mono_get_lmf_addr, sparc_o7);
- sparc_jmpl (code, sparc_o7, sparc_g0, sparc_o7);
- sparc_nop (code);
-
- code = mono_sparc_emit_save_lmf (code, lmf_offset);
-
- if (has_caller) {
- /* Load all registers of the caller into a table inside this frame */
- /* first the out registers */
- for (i = 0; i < 8; ++i)
- sparc_sti_imm (code, sparc_i0 + i, sparc_sp, regs_offset + ((sparc_o0 + i) * sizeof (target_mgreg_t)));
- /* then the in+local registers */
- for (i = 0; i < 16; i ++) {
- sparc_ldi_imm (code, sparc_fp, MONO_SPARC_STACK_BIAS + (i * sizeof (target_mgreg_t)), sparc_o7);
- sparc_sti_imm (code, sparc_o7, sparc_sp, regs_offset + ((sparc_l0 + i) * sizeof (target_mgreg_t)));
- }
- }
-
- tramp_addr = mono_get_trampoline_func (tramp_type);
- sparc_ldi_imm (code, sparc_sp, MONO_SPARC_STACK_BIAS + 200, sparc_o2);
- /* pass address of register table as third argument */
- sparc_add_imm (code, FALSE, sparc_sp, regs_offset, sparc_o0);
- sparc_set (code, tramp_addr, sparc_o7);
- /* set %o1 to caller address */
- if (has_caller)
- sparc_mov_reg_reg (code, sparc_i7, sparc_o1);
- else
- sparc_set (code, 0, sparc_o1);
- sparc_set (code, 0, sparc_o3);
- sparc_jmpl (code, sparc_o7, sparc_g0, sparc_o7);
- sparc_nop (code);
-
- /* Save result */
- sparc_sti_imm (code, sparc_o0, sparc_sp, MONO_SPARC_STACK_BIAS + 304);
-
- /* Check for thread interruption */
- sparc_set (code, (guint8*)mono_interruption_checkpoint_from_trampoline_deprecated, sparc_o7);
- sparc_jmpl (code, sparc_o7, sparc_g0, sparc_o7);
- sparc_nop (code);
-
- /* Restore lmf */
- code = mono_sparc_emit_restore_lmf (code, lmf_offset);
-
- /* Reload result */
- sparc_ldi_imm (code, sparc_sp, MONO_SPARC_STACK_BIAS + 304, sparc_o0);
-
-#ifdef SPARCV9
- /* Reload fp regs */
- for (i = 0; i < 16; i ++)
- sparc_lddf_imm (code, sparc_sp, MONO_SPARC_STACK_BIAS + 320 + (i * 8), sparc_f0 + (i * 2));
-#endif
-
- sparc_jmpl (code, sparc_o0, sparc_g0, sparc_g0);
-
- /* restore previous frame in delay slot */
- sparc_restore_simple (code);
-
-/*
-{
- gpointer addr;
-
- sparc_save_imm (code, sparc_sp, -608, sparc_sp);
- addr = code;
- sparc_call_simple (code, 16);
- sparc_nop (code);
- sparc_rett_simple (code);
- sparc_nop (code);
-
- sparc_save_imm (code, sparc_sp, -608, sparc_sp);
- sparc_ta (code, 1);
- tramp_addr = &sparc_magic_trampoline;
- sparc_call_simple (code, tramp_addr - code);
- sparc_nop (code);
- sparc_rett_simple (code);
- sparc_nop (code);
-}
-*/
-
- g_assert ((code - buf) <= 512);
-
- mono_arch_flush_icache (buf, code - buf);
- MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
-
- return buf;
-}
-
-#define TRAMPOLINE_SIZE (SPARC_SET_MAX_SIZE + 3)
-
-gpointer
-mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoMemoryManager *mem_manager, guint32 *code_len)
-{
- guint32 *code, *buf, *tramp;
-
- tramp = mono_get_trampoline_code (tramp_type);
-
- code = buf = mono_mem_manager_code_reserve (mem_manager, TRAMPOLINE_SIZE * 4);
-
- /* We have to use g5 here because there is no other free register */
- sparc_set (code, tramp, sparc_g5);
- sparc_jmpl (code, sparc_g5, sparc_g0, sparc_g5);
- sparc_nop (code);
-#ifdef SPARCV9
- g_assert_not_reached ();
-#else
- *code = (guint32)arg1;
- code ++;
-#endif
-
- g_assert ((code - buf) <= TRAMPOLINE_SIZE);
-
- if (code_len)
- *code_len = (code - buf);
-
- mono_arch_flush_icache ((guint8*)buf, (code - buf));
- MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type)));
-
- return buf;
-}
-
-gpointer
-mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot)
-{
- /* FIXME: implement! */
- g_assert_not_reached ();
- return NULL;
-}
#define NUM_DWARF_REGS 32
#define DWARF_DATA_ALIGN (-8)
#define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (14))
-#elif defined (TARGET_MIPS)
-/* FIXME: */
-static int map_hw_reg_to_dwarf_reg [32] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31
-};
-#define NUM_DWARF_REGS 32
-#define DWARF_DATA_ALIGN (-(gint32)sizeof (target_mgreg_t))
-#define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (mips_ra))
#elif defined(TARGET_RISCV)
/*
#define REDZONE_SIZE 0
#endif
-#elif defined(__mips__)
-
-#define REDZONE_SIZE 0
-
#elif defined(__s390x__)
#define REDZONE_SIZE 0
-#elif defined(__sparc__)
-
-#define REDZONE_SIZE 0
-
#elif defined (TARGET_RISCV)
#define REDZONE_SIZE (0)
mono-once.h
mono-lazy-init.h
mono-proclib.c
- mono-proclib-windows.c
mono-proclib.h
- mono-proclib-windows-internals.h
mono-publib.c
mono-string.h
mono-time.c
mono-tls.c
mono-utils-debug.c
mono-utils-debug.h
- linux_magic.h
mono-memory-model.h
atomic.h
atomic.c
} while (gcc_sync_val_compare_and_swap (dst, old_val, val) != old_val);
}
-#if defined (TARGET_OSX) || defined (__arm__) || (defined (__mips__) && !defined (__mips64)) || (defined (__powerpc__) && !defined (__powerpc64__)) || (defined (__sparc__) && !defined (__arch64__))
+#if defined (TARGET_OSX) || defined (__arm__) || (defined (__powerpc__) && !defined (__powerpc64__))
#define BROKEN_64BIT_ATOMICS_INTRINSIC 1
#endif
+++ /dev/null
-/**
- * \file
- */
-
-#ifndef __LINUX_MAGIC_H
-#define __LINUX_MAGIC_H
-
-#if __linux__
-#if HAVE_LINUX_MAGIC_H
-#include <linux/magic.h>
-#endif
-
-#ifndef ADFS_SUPER_MAGIC
-#define ADFS_SUPER_MAGIC 0xadf5
-#endif
-
-#ifndef AFFS_SUPER_MAGIC
-#define AFFS_SUPER_MAGIC 0xadff
-#endif
-
-#ifndef AFS_SUPER_MAGIC
-#define AFS_SUPER_MAGIC 0x5346414F
-#endif
-
-#ifndef AUTOFS_SUPER_MAGIC
-#define AUTOFS_SUPER_MAGIC 0x0187
-#endif
-
-#ifndef AUTOFS_SBI_MAGIC
-#define AUTOFS_SBI_MAGIC 0x6d4a556d
-#endif
-
-#ifndef CODA_SUPER_MAGIC
-#define CODA_SUPER_MAGIC 0x73757245
-#endif
-
-#ifndef CRAMFS_MAGIC
-#define CRAMFS_MAGIC 0x28cd3d45
-#endif
-
-#ifndef CRAMFS_MAGIC_WEND
-#define CRAMFS_MAGIC_WEND 0x453dcd28
-#endif
-
-#ifndef DEBUGFS_MAGIC
-#define DEBUGFS_MAGIC 0x64626720
-#endif
-
-#ifndef SYSFS_MAGIC
-#define SYSFS_MAGIC 0x62656572
-#endif
-
-#ifndef SECURITYFS_MAGIC
-#define SECURITYFS_MAGIC 0x73636673
-#endif
-
-#ifndef SELINUX_MAGIC
-#define SELINUX_MAGIC 0xf97cff8c
-#endif
-
-#ifndef RAMFS_MAGIC
-#define RAMFS_MAGIC 0x858458f6
-#endif
-
-#ifndef TMPFS_MAGIC
-#define TMPFS_MAGIC 0x01021994
-#endif
-
-#ifndef HUGETLBFS_MAGIC
-#define HUGETLBFS_MAGIC 0x958458f6
-#endif
-
-#ifndef SQUASHFS_MAGIC
-#define SQUASHFS_MAGIC 0x73717368
-#endif
-
-#ifndef EFS_SUPER_MAGIC
-#define EFS_SUPER_MAGIC 0x414A53
-#endif
-
-#ifndef EXT2_SUPER_MAGIC
-#define EXT2_SUPER_MAGIC 0xEF53
-#endif
-
-#ifndef EXT3_SUPER_MAGIC
-#define EXT3_SUPER_MAGIC 0xEF53
-#endif
-
-#ifndef XENFS_SUPER_MAGIC
-#define XENFS_SUPER_MAGIC 0xabba1974
-#endif
-
-#ifndef EXT4_SUPER_MAGIC
-#define EXT4_SUPER_MAGIC 0xEF53
-#endif
-
-#ifndef BTRFS_SUPER_MAGIC
-#define BTRFS_SUPER_MAGIC 0x9123683E
-#endif
-
-#ifndef HPFS_SUPER_MAGIC
-#define HPFS_SUPER_MAGIC 0xf995e849
-#endif
-
-#ifndef ISOFS_SUPER_MAGIC
-#define ISOFS_SUPER_MAGIC 0x9660
-#endif
-
-#ifndef JFFS2_SUPER_MAGIC
-#define JFFS2_SUPER_MAGIC 0x72b6
-#endif
-
-#ifndef JFS_SUPER_MAGIC
-#define JFS_SUPER_MAGIC 0x3153464a
-#endif
-
-#ifndef ANON_INODE_FS_MAGIC
-#define ANON_INODE_FS_MAGIC 0x09041934
-#endif
-
-#ifndef MINIX_SUPER_MAGIC
-#define MINIX_SUPER_MAGIC 0x137F
-#endif
-
-#ifndef MINIX_SUPER_MAGIC2
-#define MINIX_SUPER_MAGIC2 0x138F
-#endif
-
-#ifndef MINIX2_SUPER_MAGIC
-#define MINIX2_SUPER_MAGIC 0x2468
-#endif
-
-#ifndef MINIX2_SUPER_MAGIC2
-#define MINIX2_SUPER_MAGIC2 0x2478
-#endif
-
-#ifndef MINIX3_SUPER_MAGIC
-#define MINIX3_SUPER_MAGIC 0x4d5a
-#endif
-
-#ifndef MSDOS_SUPER_MAGIC
-#define MSDOS_SUPER_MAGIC 0x4d44
-#endif
-
-#ifndef NCP_SUPER_MAGIC
-#define NCP_SUPER_MAGIC 0x564c
-#endif
-
-#ifndef NFS_SUPER_MAGIC
-#define NFS_SUPER_MAGIC 0x6969
-#endif
-
-#ifndef OPENPROM_SUPER_MAGIC
-#define OPENPROM_SUPER_MAGIC 0x9fa1
-#endif
-
-#ifndef PROC_SUPER_MAGIC
-#define PROC_SUPER_MAGIC 0x9fa0
-#endif
-
-#ifndef QNX4_SUPER_MAGIC
-#define QNX4_SUPER_MAGIC 0x002f
-#endif
-
-#ifndef REISERFS_SUPER_MAGIC
-#define REISERFS_SUPER_MAGIC 0x52654973
-#endif
-
-#ifndef SMB_SUPER_MAGIC
-#define SMB_SUPER_MAGIC 0x517B
-#endif
-
-#ifndef USBDEVICE_SUPER_MAGIC
-#define USBDEVICE_SUPER_MAGIC 0x9fa2
-#endif
-
-#ifndef CGROUP_SUPER_MAGIC
-#define CGROUP_SUPER_MAGIC 0x27e0eb
-#endif
-
-#ifndef FUTEXFS_SUPER_MAGIC
-#define FUTEXFS_SUPER_MAGIC 0xBAD1DEA
-#endif
-
-#ifndef DEVPTS_SUPER_MAGIC
-#define DEVPTS_SUPER_MAGIC 0x1cd1
-#endif
-
-#ifndef CIFS_MAGIC_NUMBER
-#define CIFS_MAGIC_NUMBER 0xFF534D42
-#endif
-
-#ifndef BEFS_SUPER_MAGIC1
-#define BEFS_SUPER_MAGIC1 0x42465331
-#endif
-
-#ifndef BEFS_SUPER_MAGIC2
-#define BEFS_SUPER_MAGIC2 0xdd121031
-#endif
-
-#ifndef BEFS_SUPER_MAGIC3
-#define BEFS_SUPER_MAGIC3 0x15b6830e
-#endif
-
-#ifndef BFS_MAGIC
-#define BFS_MAGIC 0x1BADFACE
-#endif
-
-#ifndef NTFS_SB_MAGIC
-#define NTFS_SB_MAGIC 0x5346544e
-#endif
-
-enum {
- MONO_SYSV_FSTYPE_NONE = 0,
- MONO_SYSV_FSTYPE_XENIX,
- MONO_SYSV_FSTYPE_SYSV4,
- MONO_SYSV_FSTYPE_SYSV2,
- MONO_SYSV_FSTYPE_COH,
-};
-
-#ifndef SYSV_MAGIC_BASE
-#define SYSV_MAGIC_BASE 0x012FF7B3
-#endif
-
-#ifndef XENIX_SUPER_MAGIC
-#define XENIX_SUPER_MAGIC (SYSV_MAGIC_BASE+MONO_SYSV_FSTYPE_XENIX)
-#endif
-
-#ifndef SYSV4_SUPER_MAGIC
-#define SYSV4_SUPER_MAGIC (SYSV_MAGIC_BASE+MONO_SYSV_FSTYPE_SYSV4)
-#endif
-
-#ifndef SYSV2_SUPER_MAGIC
-#define SYSV2_SUPER_MAGIC (SYSV_MAGIC_BASE+MONO_SYSV_FSTYPE_SYSV2)
-#endif
-
-#ifndef COH_SUPER_MAGIC
-#define COH_SUPER_MAGIC (SYSV_MAGIC_BASE+MONO_SYSV_FSTYPE_COH)
-#endif
-
-#ifndef UFS_MAGIC
-#define UFS_MAGIC 0x00011954
-#endif
-
-#ifndef UFS_MAGIC_BW
-#define UFS_MAGIC_BW 0x0f242697
-#endif
-
-#ifndef UFS2_MAGIC
-#define UFS2_MAGIC 0x19540119
-#endif
-
-#ifndef UFS_CIGAM
-#define UFS_CIGAM 0x54190100
-#endif
-
-#ifndef UDF_SUPER_MAGIC
-#define UDF_SUPER_MAGIC 0x15013346
-#endif
-
-#ifndef XFS_SB_MAGIC
-#define XFS_SB_MAGIC 0x58465342
-#endif
-
-#ifndef FUSE_SUPER_MAGIC
-#define FUSE_SUPER_MAGIC 0x65735546
-#endif
-
-#ifndef V9FS_MAGIC
-#define V9FS_MAGIC 0x01021997
-#endif
-
-#ifndef CEPH_SUPER_MAGIC
-#define CEPH_SUPER_MAGIC 0x00c36400
-#endif
-
-#ifndef CONFIGFS_MAGIC
-#define CONFIGFS_MAGIC 0x62656570
-#endif
-
-#ifndef ECRYPTFS_SUPER_MAGIC
-#define ECRYPTFS_SUPER_MAGIC 0xf15f
-#endif
-
-#ifndef EXOFS_SUPER_MAGIC
-#define EXOFS_SUPER_MAGIC 0x5df5
-#endif
-
-#ifndef VXFS_SUPER_MAGIC
-#define VXFS_SUPER_MAGIC 0xa501fcf5
-#endif
-
-#ifndef VXFS_OLT_MAGIC
-#define VXFS_OLT_MAGIC 0xa504fcf5
-#endif
-
-#ifndef GFS2_MAGIC
-#define GFS2_MAGIC 0x01161970
-#endif
-
-#ifndef HFS_SUPER_MAGIC
-#define HFS_SUPER_MAGIC 0x4244
-#endif
-
-#ifndef HFSPLUS_SUPER_MAGIC
-#define HFSPLUS_SUPER_MAGIC 0x482b
-#endif
-
-#ifndef LOGFS_MAGIC_U32
-#define LOGFS_MAGIC_U32 0xc97e8168
-#endif
-
-#ifndef OCFS2_SUPER_MAGIC
-#define OCFS2_SUPER_MAGIC 0x7461636f
-#endif
-
-#ifndef OMFS_MAGIC
-#define OMFS_MAGIC 0xc2993d87
-#endif
-
-#ifndef UBIFS_SUPER_MAGIC
-#define UBIFS_SUPER_MAGIC 0x24051905
-#endif
-
-#ifndef ROMFS_MAGIC
-#define ROMFS_MAGIC 0x7275
-#endif
-
-#endif
-#endif
#endif
}
-#elif (defined(__mips__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_MIPS))
-
-#include <mono/utils/mono-context.h>
-#include <mono/arch/mips/mips-codegen.h>
-
-void
-mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
-{
- int i;
-
- mctx->sc_pc = UCONTEXT_REG_PC (sigctx);
- for (i = 0; i < 32; ++i) {
- mctx->sc_regs[i] = UCONTEXT_GREGS (sigctx) [i];
- mctx->sc_fpregs[i] = UCONTEXT_FPREGS (sigctx) [i];
- }
-}
-
-void
-mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
-{
- int i;
-
- UCONTEXT_REG_PC (sigctx) = mctx->sc_pc;
- for (i = 0; i < 32; ++i) {
- UCONTEXT_GREGS (sigctx) [i] = mctx->sc_regs[i];
- UCONTEXT_FPREGS (sigctx) [i] = mctx->sc_fpregs[i];
- }
-}
-
#elif (((defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__)) && !defined(MONO_CROSS_COMPILE))) || (defined(TARGET_POWERPC))
#include <mono/utils/mono-context.h>
#define MONO_ARCH_HAS_MONO_CONTEXT 1
-#elif defined(__sparc__) || defined(sparc) /* defined(__mono_ppc__) */
-
-typedef struct MonoContext {
- host_mgreg_t regs [15];
- guint8 *ip;
- gpointer *sp;
- gpointer *fp;
-} MonoContext;
-
-#define MONO_CONTEXT_SET_IP(ctx,eip) do { (ctx)->ip = (gpointer)(eip); } while (0);
-#define MONO_CONTEXT_SET_BP(ctx,ebp) do { (ctx)->fp = (gpointer*)(ebp); } while (0);
-#define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->sp = (gpointer*)(esp); } while (0);
-
-#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->ip))
-#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->fp))
-#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->sp))
-
-#ifdef __sparcv9
-#define MONO_CONTEXT_GET_CURRENT(ctx) \
- __asm__ __volatile__( \
- "st %%g1,[%0]\n" \
- "st %%g2,[%0+0x08]\n" \
- "st %%g3,[%0+0x10]\n" \
- "st %%g4,[%0+0x18]\n" \
- "st %%g5,[%0+0x20]\n" \
- "st %%g6,[%0+0x28]\n" \
- "st %%g7,[%0+0x30]\n" \
- "st %%o0,[%0+0x38]\n" \
- "st %%o1,[%0+0x40]\n" \
- "st %%o2,[%0+0x48]\n" \
- "st %%o3,[%0+0x50]\n" \
- "st %%o4,[%0+0x58]\n" \
- "st %%o5,[%0+0x60]\n" \
- "st %%o6,[%0+0x68]\n" \
- "st %%o7,[%0+0x70]\n" \
- : \
- : "r" (&(ctx)) \
- : "memory" \
- )
-#else
-#define MONO_CONTEXT_GET_CURRENT(ctx) \
- __asm__ __volatile__( \
- "st %%g1,[%0]\n" \
- "st %%g2,[%0+0x04]\n" \
- "st %%g3,[%0+0x08]\n" \
- "st %%g4,[%0+0x0c]\n" \
- "st %%g5,[%0+0x10]\n" \
- "st %%g6,[%0+0x14]\n" \
- "st %%g7,[%0+0x18]\n" \
- "st %%o0,[%0+0x1c]\n" \
- "st %%o1,[%0+0x20]\n" \
- "st %%o2,[%0+0x24]\n" \
- "st %%o3,[%0+0x28]\n" \
- "st %%o4,[%0+0x2c]\n" \
- "st %%o5,[%0+0x30]\n" \
- "st %%o6,[%0+0x34]\n" \
- "st %%o7,[%0+0x38]\n" \
- : \
- : "r" (&(ctx)) \
- : "memory" \
- )
-#endif
-
-#define MONO_ARCH_HAS_MONO_CONTEXT 1
-
-#elif ((defined(__mips__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_MIPS))) && SIZEOF_REGISTER == 4
-
-#define MONO_ARCH_HAS_MONO_CONTEXT 1
-
-#include <mono/arch/mips/mips-codegen.h>
-
-typedef struct {
- host_mgreg_t sc_pc;
- host_mgreg_t sc_regs [32];
- gfloat sc_fpregs [32];
-} MonoContext;
-
-#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->sc_pc = (host_mgreg_t)(gsize)(ip); } while (0);
-#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->sc_regs[mips_fp] = (host_mgreg_t)(gsize)(bp); } while (0);
-#define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->sc_regs[mips_sp] = (host_mgreg_t)(gsize)(sp); } while (0);
-
-#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)(gsize)((ctx)->sc_pc))
-#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)(gsize)((ctx)->sc_regs[mips_fp]))
-#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)(gsize)((ctx)->sc_regs[mips_sp]))
-
-#define MONO_CONTEXT_GET_CURRENT(ctx) \
- __asm__ __volatile__( \
- "sw $0,0(%0)\n\t" \
- "sw $1,4(%0)\n\t" \
- "sw $2,8(%0)\n\t" \
- "sw $3,12(%0)\n\t" \
- "sw $4,16(%0)\n\t" \
- "sw $5,20(%0)\n\t" \
- "sw $6,24(%0)\n\t" \
- "sw $7,28(%0)\n\t" \
- "sw $8,32(%0)\n\t" \
- "sw $9,36(%0)\n\t" \
- "sw $10,40(%0)\n\t" \
- "sw $11,44(%0)\n\t" \
- "sw $12,48(%0)\n\t" \
- "sw $13,52(%0)\n\t" \
- "sw $14,56(%0)\n\t" \
- "sw $15,60(%0)\n\t" \
- "sw $16,64(%0)\n\t" \
- "sw $17,68(%0)\n\t" \
- "sw $18,72(%0)\n\t" \
- "sw $19,76(%0)\n\t" \
- "sw $20,80(%0)\n\t" \
- "sw $21,84(%0)\n\t" \
- "sw $22,88(%0)\n\t" \
- "sw $23,92(%0)\n\t" \
- "sw $24,96(%0)\n\t" \
- "sw $25,100(%0)\n\t" \
- "sw $26,104(%0)\n\t" \
- "sw $27,108(%0)\n\t" \
- "sw $28,112(%0)\n\t" \
- "sw $29,116(%0)\n\t" \
- "sw $30,120(%0)\n\t" \
- "sw $31,124(%0)\n\t" \
- : : "r" (&(ctx).sc_regs [0]) \
- : "memory" \
- )
-
#elif defined(__s390x__)
#define MONO_ARCH_HAS_MONO_CONTEXT 1
+++ /dev/null
-/**
- * \file
- * MIPS hardware feature detection
- *
- * Authors:
- * Alex Rønne Petersen (alexrp@xamarin.com)
- * Elijah Taylor (elijahtaylor@google.com)
- * Miguel de Icaza (miguel@xamarin.com)
- * Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
- * Paolo Molaro (lupus@xamarin.com)
- * Rodrigo Kumpera (kumpera@gmail.com)
- * Sebastien Pouliot (sebastien@xamarin.com)
- * Zoltan Varga (vargaz@xamarin.com)
- *
- * Copyright 2003 Ximian, Inc.
- * Copyright 2003-2011 Novell, Inc
- * Copyright 2006 Broadcom
- * Copyright 2007-2008 Andreas Faerber
- * Copyright 2011-2013 Xamarin Inc
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include "mono/utils/mono-hwcap.h"
-
-void
-mono_hwcap_arch_init (void)
-{
-}
+++ /dev/null
-/**
- * \file
- * SPARC hardware feature detection
- *
- * Authors:
- * Alex Rønne Petersen (alexrp@xamarin.com)
- * Elijah Taylor (elijahtaylor@google.com)
- * Miguel de Icaza (miguel@xamarin.com)
- * Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
- * Paolo Molaro (lupus@xamarin.com)
- * Rodrigo Kumpera (kumpera@gmail.com)
- * Sebastien Pouliot (sebastien@xamarin.com)
- * Zoltan Varga (vargaz@xamarin.com)
- *
- * Copyright 2003 Ximian, Inc.
- * Copyright 2003-2011 Novell, Inc
- * Copyright 2006 Broadcom
- * Copyright 2007-2008 Andreas Faerber
- * Copyright 2011-2013 Xamarin Inc
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include "mono/utils/mono-hwcap.h"
-
-#include <string.h>
-#if !defined(__linux__)
-#include <sys/systeminfo.h>
-#else
-#include <unistd.h>
-#endif
-
-void
-mono_hwcap_arch_init (void)
-{
- char buf [1024];
-
-#if !defined(__linux__)
- g_assert (sysinfo (SI_ISALIST, buf, 1024));
-#else
- /* If the page size is 8192, we're on a 64-bit SPARC, which
- * in turn means a v9 or better.
- */
- if (getpagesize () == 8192)
- strcpy (buf, "sparcv9");
- else
- strcpy (buf, "sparcv8");
-#endif
-
- mono_hwcap_sparc_is_v9 = strstr (buf, "sparcv9");
-}
+++ /dev/null
-/**
- * \file
- */
-
-#ifndef __MONO_UTILS_HWCAP_SPARC_H__
-#define __MONO_UTILS_HWCAP_SPARC_H__
-
-#include "mono/utils/mono-hwcap.h"
-
-extern gboolean mono_hwcap_sparc_is_v9;
-
-#endif /* __MONO_UTILS_HWCAP_SPARC_H__ */
// Nothing here yet.
-#elif defined (TARGET_MIPS)
-
-// Nothing here yet.
-
#elif defined (TARGET_POWERPC) || defined (TARGET_POWERPC64)
MONO_HWCAP_VAR(ppc_has_icache_snoop)
MONO_HWCAP_VAR(s390x_has_vef2)
MONO_HWCAP_VAR(s390x_has_eif)
-#elif defined (TARGET_SPARC) || defined (TARGET_SPARC64)
-
-MONO_HWCAP_VAR(sparc_is_v9)
-
#elif defined (TARGET_X86) || defined (TARGET_AMD64)
MONO_HWCAP_VAR(x86_has_cmov)
#if HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
-#ifdef HAVE_SYS_SYSCTL_H
-#include <sys/sysctl.h>
-#endif
#include <signal.h>
#include <fcntl.h>
#include <string.h>
+++ /dev/null
-/**
- * \file
- */
-
-#ifndef __MONO_UTILS_PROCLIB_WINDOWS_H__
-#define __MONO_UTILS_PROCLIB_WINDOWS_H__
-
-#include <config.h>
-#include <glib.h>
-
-#ifdef HOST_WIN32
-#include <process.h>
-#include "mono/utils/mono-proclib.h"
-
-#endif /* HOST_WIN32 */
-#endif /* __MONO_UTILS_PROCLIB_WINDOWS_H__ */
-
+++ /dev/null
-/**
- * \file
- * Windows proclib support for Mono.
- *
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
-*/
-
-#include <config.h>
-#include <glib.h>
-
-#ifdef HOST_WIN32
-#include <windows.h>
-#include <mono/utils/mono-proclib.h>
-#include <mono/utils/w32subset.h>
-
-int
-mono_process_current_pid ()
-{
- return (int) GetCurrentProcessId ();
-}
-
-/**
- * mono_cpu_count:
- * \returns the number of processors on the system.
- */
-int
-mono_cpu_count (void)
-{
- SYSTEM_INFO info;
- GetSystemInfo (&info);
- return info.dwNumberOfProcessors;
-}
-
-/*
- * This function returns the cpu usage in percentage,
- * normalized on the number of cores.
- */
-#if HAVE_API_SUPPORT_WIN32_GET_SYSTEM_TIMES
-gint32
-mono_cpu_usage (MonoCpuUsageState *prev)
-{
- gint32 cpu_usage = 0;
- gint64 cpu_total_time;
- gint64 cpu_busy_time;
- guint64 idle_time;
- guint64 kernel_time;
- guint64 user_time;
-
- if (!GetSystemTimes ((FILETIME*) &idle_time, (FILETIME*) &kernel_time, (FILETIME*) &user_time)) {
- g_error ("GetSystemTimes() failed, error code is %d\n", GetLastError ());
- return -1;
- }
-
- cpu_total_time = (gint64)((user_time - (prev ? prev->user_time : 0)) + (kernel_time - (prev ? prev->kernel_time : 0)));
- cpu_busy_time = (gint64)(cpu_total_time - (idle_time - (prev ? prev->idle_time : 0)));
-
- if (prev) {
- prev->idle_time = idle_time;
- prev->kernel_time = kernel_time;
- prev->user_time = user_time;
- }
-
- if (cpu_total_time > 0 && cpu_busy_time > 0)
- cpu_usage = (gint32)(cpu_busy_time * 100 / cpu_total_time);
-
- return cpu_usage;
-}
-#elif HAVE_API_SUPPORT_WIN32_GET_SYSTEM_TIME_AS_FILE_TIME && HAVE_API_SUPPORT_WIN32_GET_PROCESS_TIMES
-gint32
-mono_cpu_usage (MonoCpuUsageState *prev)
-{
- gint32 cpu_usage = 0;
- gint64 cpu_total_time;
- gint64 cpu_busy_time;
- guint64 idle_time;
- guint64 kernel_time;
- guint64 user_time;
- guint64 current_time;
- guint64 creation_time;
- guint64 exit_time;
-
- GetSystemTimeAsFileTime ((FILETIME*)¤t_time);
- if (!GetProcessTimes (GetCurrentProcess (), (FILETIME*)&creation_time, (FILETIME*)&exit_time, (FILETIME*)&kernel_time, (FILETIME*)&user_time)) {
- g_error ("GetProcessTimes() failed, error code is %d\n", GetLastError ());
- return -1;
- }
-
- // GetProcessTimes user_time is a sum of user time spend by all threads in the process.
- // This means that the total user time can be more than real time. In order to adjust for this
- // the total available time that we can be scheduled depends on the number of available cores.
- // For example, having 2 threads running 100% on a 2 core system for 100 ms will return a user_time of 200ms
- // but the current_time - creation_time will only be 100ms but by adjusting the available time based on number of
- // of availalbe cores will gives use the total load of the process.
- guint64 total_available_time = (current_time - creation_time) * mono_cpu_count ();
-
- idle_time = total_available_time - (kernel_time + user_time);
-
- cpu_total_time = (gint64)((idle_time - (prev ? prev->idle_time : 0)) + (user_time - (prev ? prev->user_time : 0)) + (kernel_time - (prev ? prev->kernel_time : 0)));
- cpu_busy_time = (gint64)(cpu_total_time - (idle_time - (prev ? prev->idle_time : 0)));
-
- if (prev) {
- prev->idle_time = idle_time;
- prev->kernel_time = kernel_time;
- prev->user_time = user_time;
- }
-
- if (cpu_total_time > 0 && cpu_busy_time > 0)
- cpu_usage = (gint32)(cpu_busy_time * 100 / cpu_total_time);
-
- return cpu_usage;
-}
-#elif !HAVE_EXTERN_DEFINED_WIN32_GET_SYSTEM_TIMES && !HAVE_EXTERN_DEFINED_WIN32_GET_SYSTEM_TIME_AS_FILE_TIME && !HAVE_EXTERN_DEFINED_WIN32_GET_PROCESS_TIMES
-gint32
-mono_cpu_usage (MonoCpuUsageState *prev)
-{
- g_unsupported_api ("GetSystemTimes, GetSystemTimeAsFileTime, GetProcessTimes");
- SetLastError (ERROR_NOT_SUPPORTED);
- return -1;
-}
-#endif /* HAVE_API_SUPPORT_WIN32_GET_SYSTEM_TIMES */
-
-#else
-
-#include <mono/utils/mono-compiler.h>
-
-MONO_EMPTY_SOURCE_FILE (mono_proclib_windows);
-
-#endif /* HOST_WIN32*/
*/
#include "config.h"
-#include "utils/mono-proclib.h"
-#include "utils/mono-time.h"
-#include "utils/mono-errno.h"
+#include <mono/utils/mono-proclib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
+
+#ifdef HOST_WIN32
+#include <windows.h>
+#include <process.h>
+#else
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SCHED_GETAFFINITY
#include <sched.h>
#endif
-
-#include <utils/mono-mmap.h>
-#include <utils/strenc-internals.h>
-#include <utils/strenc.h>
-#include <utils/mono-error-internals.h>
-#include <utils/mono-logger-internals.h>
-
-#if defined(_POSIX_VERSION)
-#ifdef HAVE_SYS_ERRNO_H
-#include <sys/errno.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <errno.h>
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
#endif
-#endif
-#if defined(__HAIKU__)
-#include <os/kernel/OS.h>
-#endif
-#if defined(_AIX)
-#include <procinfo.h>
-#endif
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
-#include <sys/proc.h>
-#if defined(__APPLE__)
-#include <mach/mach.h>
-#endif
-#ifdef HAVE_SYS_USER_H
-#include <sys/user.h>
-#endif
-#ifdef HAVE_STRUCT_KINFO_PROC_KP_PROC
-# define kinfo_starttime_member kp_proc.p_starttime
-# define kinfo_pid_member kp_proc.p_pid
-# define kinfo_name_member kp_proc.p_comm
-#elif defined(__NetBSD__)
-# define kinfo_starttime_member p_ustart_sec
-# define kinfo_pid_member p_pid
-# define kinfo_name_member p_comm
-#elif defined(__OpenBSD__)
-// Can not figure out how to get the proc's start time on OpenBSD
-# undef kinfo_starttime_member
-# define kinfo_pid_member p_pid
-# define kinfo_name_member p_comm
+
+int
+mono_process_current_pid ()
+{
+#ifdef HOST_WIN32
+ return (int) GetCurrentProcessId ();
+#elif defined(HAVE_GETPID)
+ return (int) getpid ();
+#elif defined(HOST_WASI)
+ return 0;
#else
-#define kinfo_starttime_member ki_start
-#define kinfo_pid_member ki_pid
-#define kinfo_name_member ki_comm
-#endif
-#define USE_SYSCTL 1
+#error getpid
#endif
+}
#ifdef HAVE_SCHED_GETAFFINITY
# ifndef HAVE_GNU_CPU_COUNT
#endif
/**
- * mono_process_list:
- * \param size a pointer to a location where the size of the returned array is stored
- * \returns an array of pid values for the processes currently running on the system.
- * The size of the array is stored in \p size.
- */
-gpointer*
-mono_process_list (int *size)
-{
-#if USE_SYSCTL
- int res, i;
-#ifdef KERN_PROC2
- int mib [6];
- size_t data_len = sizeof (struct kinfo_proc2) * 400;
- struct kinfo_proc2 *processes = g_malloc (data_len);
-#else
- int mib [4];
- size_t data_len = sizeof (struct kinfo_proc) * 16;
- struct kinfo_proc *processes;
- int limit = 8;
-#endif /* KERN_PROC2 */
- void **buf = NULL;
-
- if (size)
- *size = 0;
-
-#ifdef KERN_PROC2
- if (!processes)
- return NULL;
-
- mib [0] = CTL_KERN;
- mib [1] = KERN_PROC2;
- mib [2] = KERN_PROC_ALL;
- mib [3] = 0;
- mib [4] = sizeof(struct kinfo_proc2);
- mib [5] = 400; /* XXX */
-
- res = sysctl (mib, 6, processes, &data_len, NULL, 0);
- if (res < 0) {
- g_free (processes);
- return NULL;
- }
-#else
- processes = NULL;
- while (limit) {
- mib [0] = CTL_KERN;
- mib [1] = KERN_PROC;
- mib [2] = KERN_PROC_ALL;
- mib [3] = 0;
-
- res = sysctl (mib, 3, NULL, &data_len, NULL, 0);
- if (res)
- return NULL;
- processes = (struct kinfo_proc *) g_malloc (data_len);
- res = sysctl (mib, 3, processes, &data_len, NULL, 0);
- if (res < 0) {
- g_free (processes);
- if (errno != ENOMEM)
- return NULL;
- limit --;
- } else {
- break;
- }
- }
-#endif /* KERN_PROC2 */
-
-#ifdef KERN_PROC2
- res = data_len/sizeof (struct kinfo_proc2);
-#else
- res = data_len/sizeof (struct kinfo_proc);
-#endif /* KERN_PROC2 */
- buf = (void **) g_realloc (buf, res * sizeof (void*));
- for (i = 0; i < res; ++i)
- buf [i] = GINT_TO_POINTER (processes [i].kinfo_pid_member);
- g_free (processes);
- if (size)
- *size = res;
- return buf;
-#elif defined(__HAIKU__)
- int32 cookie = 0;
- int32 i = 0;
- team_info ti;
- system_info si;
-
- get_system_info(&si);
- void **buf = g_calloc(si.used_teams, sizeof(void*));
-
- while (get_next_team_info(&cookie, &ti) == B_OK && i < si.used_teams) {
- buf[i++] = GINT_TO_POINTER (ti.team);
- }
- *size = i;
-
- return buf;
-#elif defined(_AIX)
- void **buf = NULL;
- struct procentry64 *procs = NULL;
- int count = 0;
- int i = 0;
- pid_t pid = 1; // start at 1, 0 is a null process (???)
-
- // count number of procs + compensate for new ones forked in while we do it.
- // (it's not an atomic operation) 1000000 is the limit IBM ps seems to use
- // when I inspected it under truss. the second call we do to getprocs64 will
- // then only allocate what we need, instead of allocating some obscenely large
- // array on the heap.
- count = getprocs64(NULL, sizeof (struct procentry64), NULL, 0, &pid, 1000000);
- if (count < 1)
- goto cleanup;
- count += 10;
- pid = 1; // reset the pid cookie
-
- // 5026 bytes is the ideal size for the C struct. you may not like it, but
- // this is what peak allocation looks like
- procs = g_calloc (count, sizeof (struct procentry64));
- // the man page recommends you do this in a loop, but you can also just do it
- // in one shot; again, like what ps does. let the returned count (in case it's
- // less) be what we then allocate the array of pids from (in case of ANOTHER
- // system-wide race condition with processes)
- count = getprocs64 (procs, sizeof (struct procentry64), NULL, 0, &pid, count);
- if (count < 1 || procs == NULL)
- goto cleanup;
- buf = g_calloc (count, sizeof (void*));
- for (i = 0; i < count; i++) {
- buf[i] = GINT_TO_POINTER (procs[i].pi_pid);
- }
- *size = i;
-
-cleanup:
- g_free (procs);
- return buf;
-#else
- const char *name;
- void **buf = NULL;
- int count = 0;
- int i = 0;
- GDir *dir = g_dir_open ("/proc/", 0, NULL);
- if (!dir) {
- if (size)
- *size = 0;
- return NULL;
- }
- while ((name = g_dir_read_name (dir))) {
- int pid;
- char *nend;
- pid = strtol (name, &nend, 10);
- if (pid <= 0 || nend == name || *nend)
- continue;
- if (i >= count) {
- if (!count)
- count = 16;
- else
- count *= 2;
- buf = (void **)g_realloc (buf, count * sizeof (void*));
- }
- buf [i++] = GINT_TO_POINTER (pid);
- }
- g_dir_close (dir);
- if (size)
- *size = i;
- return buf;
-#endif
-}
-
-static G_GNUC_UNUSED char*
-get_pid_status_item_buf (int pid, const char *item, char *rbuf, int blen, MonoProcessError *error)
-{
- char buf [256];
- char *s;
- FILE *f;
- size_t len = strlen (item);
-
- g_snprintf (buf, sizeof (buf), "/proc/%d/status", pid);
- f = fopen (buf, "r");
- if (!f) {
- if (error)
- *error = MONO_PROCESS_ERROR_NOT_FOUND;
- return NULL;
- }
- while ((s = fgets (buf, sizeof (buf), f))) {
- if (*item != *buf)
- continue;
- if (strncmp (buf, item, len))
- continue;
- s = buf + len;
- while (g_ascii_isspace (*s)) s++;
- if (*s++ != ':')
- continue;
- while (g_ascii_isspace (*s)) s++;
- fclose (f);
- len = strlen (s);
- memcpy (rbuf, s, MIN (len, blen));
- rbuf [MIN (len, blen) - 1] = 0;
- if (error)
- *error = MONO_PROCESS_ERROR_NONE;
- return rbuf;
- }
- fclose (f);
- if (error)
- *error = MONO_PROCESS_ERROR_OTHER;
- return NULL;
-}
-
-#if USE_SYSCTL
-
-#ifdef KERN_PROC2
-#define KINFO_PROC struct kinfo_proc2
-#else
-#define KINFO_PROC struct kinfo_proc
-#endif
-
-static gboolean
-sysctl_kinfo_proc (gpointer pid, KINFO_PROC* processi)
-{
- int res;
- size_t data_len = sizeof (KINFO_PROC);
-
-#ifdef KERN_PROC2
- int mib [6];
- mib [0] = CTL_KERN;
- mib [1] = KERN_PROC2;
- mib [2] = KERN_PROC_PID;
- mib [3] = GPOINTER_TO_UINT (pid);
- mib [4] = sizeof(KINFO_PROC);
- mib [5] = 400; /* XXX */
-
- res = sysctl (mib, 6, processi, &data_len, NULL, 0);
-#else
- int mib [4];
- mib [0] = CTL_KERN;
- mib [1] = KERN_PROC;
- mib [2] = KERN_PROC_PID;
- mib [3] = GPOINTER_TO_UINT (pid);
-
- res = sysctl (mib, 4, processi, &data_len, NULL, 0);
-#endif /* KERN_PROC2 */
-
- if (res < 0 || data_len != sizeof (KINFO_PROC))
- return FALSE;
-
- return TRUE;
-}
-#endif /* USE_SYSCTL */
-
-/**
- * mono_process_get_name:
- * \param pid pid of the process
- * \param buf byte buffer where to store the name of the prcoess
- * \param len size of the buffer \p buf
- * \returns the name of the process identified by \p pid, storing it
- * inside \p buf for a maximum of len bytes (including the terminating 0).
- */
-char*
-mono_process_get_name (gpointer pid, char *buf, int len)
-{
-#if USE_SYSCTL
- KINFO_PROC processi;
-
- memset (buf, 0, len);
-
- if (sysctl_kinfo_proc (pid, &processi))
- memcpy (buf, processi.kinfo_name_member, len - 1);
-
- return buf;
-#elif defined(_AIX)
- struct procentry64 proc;
- pid_t newpid = GPOINTER_TO_INT (pid);
-
- if (getprocs64 (&proc, sizeof (struct procentry64), NULL, 0, &newpid, 1) == 1) {
- g_strlcpy (buf, proc.pi_comm, len - 1);
- }
- return buf;
-#else
- char fname [128];
- FILE *file;
- char *p;
- size_t r;
- sprintf (fname, "/proc/%d/cmdline", GPOINTER_TO_INT (pid));
- buf [0] = 0;
- file = fopen (fname, "r");
- if (!file)
- return buf;
- r = fread (buf, 1, len - 1, file);
- fclose (file);
- buf [r] = 0;
- p = strrchr (buf, '/');
- if (p)
- return p + 1;
- if (r == 0) {
- return get_pid_status_item_buf (GPOINTER_TO_INT (pid), "Name", buf, len, NULL);
- }
- return buf;
-#endif
-}
-
-void
-mono_process_get_times (gpointer pid, gint64 *start_time, gint64 *user_time, gint64 *kernel_time)
-{
- if (user_time)
- *user_time = mono_process_get_data (pid, MONO_PROCESS_USER_TIME);
-
- if (kernel_time)
- *kernel_time = mono_process_get_data (pid, MONO_PROCESS_SYSTEM_TIME);
-
- if (start_time) {
- *start_time = 0;
-
-#if USE_SYSCTL && defined(kinfo_starttime_member)
- {
- KINFO_PROC processi;
-
- if (sysctl_kinfo_proc (pid, &processi)) {
-#if defined(__NetBSD__)
- struct timeval tv;
- tv.tv_sec = processi.kinfo_starttime_member;
- tv.tv_usec = processi.p_ustart_usec;
- *start_time = mono_100ns_datetime_from_timeval(tv);
-#else
- *start_time = mono_100ns_datetime_from_timeval (processi.kinfo_starttime_member);
-#endif
- }
- }
-#endif
-
- if (*start_time == 0) {
- static guint64 boot_time = 0;
- if (!boot_time)
- boot_time = mono_100ns_datetime () - mono_msec_boottime () * 10000;
-
- *start_time = boot_time + mono_process_get_data (pid, MONO_PROCESS_ELAPSED);
- }
- }
-}
-
-/*
- * /proc/pid/stat format:
- * pid (cmdname) S
- * [0] ppid pgid sid tty_nr tty_pgrp flags min_flt cmin_flt maj_flt cmaj_flt
- * [10] utime stime cutime cstime prio nice threads 0 start_time vsize
- * [20] rss rsslim start_code end_code start_stack esp eip pending blocked sigign
- * [30] sigcatch wchan 0 0 exit_signal cpu rt_prio policy
- */
-
-#define RET_ERROR(err) do { \
- if (error) *error = (err); \
- return 0; \
- } while (0)
-
-static gint64
-get_process_stat_item (int pid, int pos, int sum, MonoProcessError *error)
-{
-#if defined(__APPLE__)
- double process_user_time = 0, process_system_time = 0;//, process_percent = 0;
- task_t task;
- struct task_basic_info t_info;
- mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT, th_count;
- thread_array_t th_array;
- size_t i;
- kern_return_t ret;
-
- if (pid == getpid ()) {
- /* task_for_pid () doesn't work on ios, even for the current process */
- task = mach_task_self ();
- } else {
- do {
- ret = task_for_pid (mach_task_self (), pid, &task);
- } while (ret == KERN_ABORTED);
-
- if (ret != KERN_SUCCESS)
- RET_ERROR (MONO_PROCESS_ERROR_NOT_FOUND);
- }
-
- do {
- ret = task_info (task, TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
- } while (ret == KERN_ABORTED);
-
- if (ret != KERN_SUCCESS) {
- if (pid != getpid ())
- mach_port_deallocate (mach_task_self (), task);
- RET_ERROR (MONO_PROCESS_ERROR_OTHER);
- }
-
- do {
- ret = task_threads (task, &th_array, &th_count);
- } while (ret == KERN_ABORTED);
-
- if (ret != KERN_SUCCESS) {
- if (pid != getpid ())
- mach_port_deallocate (mach_task_self (), task);
- RET_ERROR (MONO_PROCESS_ERROR_OTHER);
- }
-
- for (i = 0; i < th_count; i++) {
- double thread_user_time, thread_system_time;//, thread_percent;
-
- struct thread_basic_info th_info;
- mach_msg_type_number_t th_info_count = THREAD_BASIC_INFO_COUNT;
- do {
- ret = thread_info(th_array[i], THREAD_BASIC_INFO, (thread_info_t)&th_info, &th_info_count);
- } while (ret == KERN_ABORTED);
-
- if (ret == KERN_SUCCESS) {
- thread_user_time = th_info.user_time.seconds + th_info.user_time.microseconds / 1e6;
- thread_system_time = th_info.system_time.seconds + th_info.system_time.microseconds / 1e6;
- //thread_percent = (double)th_info.cpu_usage / TH_USAGE_SCALE;
-
- process_user_time += thread_user_time;
- process_system_time += thread_system_time;
- //process_percent += th_percent;
- }
- }
-
- for (i = 0; i < th_count; i++)
- mach_port_deallocate(task, th_array[i]);
-
- if (pid != getpid ())
- mach_port_deallocate (mach_task_self (), task);
-
- process_user_time += t_info.user_time.seconds + t_info.user_time.microseconds / 1e6;
- process_system_time += t_info.system_time.seconds + t_info.system_time.microseconds / 1e6;
-
- if (pos == 10 && sum == TRUE)
- return (gint64)((process_user_time + process_system_time) * 10000000);
- else if (pos == 10)
- return (gint64)(process_user_time * 10000000);
- else if (pos == 11)
- return (gint64)(process_system_time * 10000000);
-
- return 0;
-#else
- char buf [512];
- char *s, *end;
- FILE *f;
- size_t len;
- int i;
- gint64 value;
-
- g_snprintf (buf, sizeof (buf), "/proc/%d/stat", pid);
- f = fopen (buf, "r");
- if (!f)
- RET_ERROR (MONO_PROCESS_ERROR_NOT_FOUND);
- len = fread (buf, 1, sizeof (buf), f);
- fclose (f);
- if (len <= 0)
- RET_ERROR (MONO_PROCESS_ERROR_OTHER);
- s = strchr (buf, ')');
- if (!s)
- RET_ERROR (MONO_PROCESS_ERROR_OTHER);
- s++;
- while (g_ascii_isspace (*s)) s++;
- if (!*s)
- RET_ERROR (MONO_PROCESS_ERROR_OTHER);
- /* skip the status char */
- while (*s && !g_ascii_isspace (*s)) s++;
- if (!*s)
- RET_ERROR (MONO_PROCESS_ERROR_OTHER);
- for (i = 0; i < pos; ++i) {
- while (g_ascii_isspace (*s)) s++;
- if (!*s)
- RET_ERROR (MONO_PROCESS_ERROR_OTHER);
- while (*s && !g_ascii_isspace (*s)) s++;
- if (!*s)
- RET_ERROR (MONO_PROCESS_ERROR_OTHER);
- }
- /* we are finally at the needed item */
- value = strtoul (s, &end, 0);
- /* add also the following value */
- if (sum) {
- while (g_ascii_isspace (*s)) s++;
- if (!*s)
- RET_ERROR (MONO_PROCESS_ERROR_OTHER);
- value += strtoul (s, &end, 0);
- }
- if (error)
- *error = MONO_PROCESS_ERROR_NONE;
- return value;
-#endif
-}
-
-static int
-get_user_hz (void)
-{
- static int user_hz = 0;
- if (user_hz == 0) {
-#if defined (_SC_CLK_TCK) && defined (HAVE_SYSCONF)
- user_hz = sysconf (_SC_CLK_TCK);
-#endif
- if (user_hz == 0)
- user_hz = 100;
- }
- return user_hz;
-}
-
-static gint64
-get_process_stat_time (int pid, int pos, int sum, MonoProcessError *error)
-{
- gint64 val = get_process_stat_item (pid, pos, sum, error);
-#if defined(__APPLE__)
- return val;
-#else
- /* return 100ns ticks */
- return (val * 10000000) / get_user_hz ();
-#endif
-}
-
-static gint64
-get_pid_status_item (int pid, const char *item, MonoProcessError *error, int multiplier)
-{
-#if defined(__APPLE__)
- // ignore the multiplier
-
- gint64 ret;
- task_t task;
- task_vm_info_data_t t_info;
- mach_msg_type_number_t info_count = TASK_VM_INFO_COUNT;
- kern_return_t mach_ret;
-
- if (pid == getpid ()) {
- /* task_for_pid () doesn't work on ios, even for the current process */
- task = mach_task_self ();
- } else {
- do {
- mach_ret = task_for_pid (mach_task_self (), pid, &task);
- } while (mach_ret == KERN_ABORTED);
-
- if (mach_ret != KERN_SUCCESS)
- RET_ERROR (MONO_PROCESS_ERROR_NOT_FOUND);
- }
-
- do {
- mach_ret = task_info (task, TASK_VM_INFO, (task_info_t)&t_info, &info_count);
- } while (mach_ret == KERN_ABORTED);
-
- if (mach_ret != KERN_SUCCESS) {
- if (pid != getpid ())
- mach_port_deallocate (mach_task_self (), task);
- RET_ERROR (MONO_PROCESS_ERROR_OTHER);
- }
-
- if(strcmp (item, "VmData") == 0)
- ret = t_info.internal + t_info.compressed;
- else if (strcmp (item, "VmRSS") == 0)
- ret = t_info.resident_size;
- else if(strcmp (item, "VmHWM") == 0)
- ret = t_info.resident_size_peak;
- else if (strcmp (item, "VmSize") == 0 || strcmp (item, "VmPeak") == 0)
- ret = t_info.virtual_size;
- else if (strcmp (item, "Threads") == 0) {
- struct task_basic_info t_info;
- mach_msg_type_number_t th_count = TASK_BASIC_INFO_COUNT;
- do {
- mach_ret = task_info (task, TASK_BASIC_INFO, (task_info_t)&t_info, &th_count);
- } while (mach_ret == KERN_ABORTED);
-
- if (mach_ret != KERN_SUCCESS) {
- if (pid != getpid ())
- mach_port_deallocate (mach_task_self (), task);
- RET_ERROR (MONO_PROCESS_ERROR_OTHER);
- }
- ret = th_count;
- } else if (strcmp (item, "VmSwap") == 0)
- ret = t_info.compressed;
- else
- ret = 0;
-
- if (pid != getpid ())
- mach_port_deallocate (mach_task_self (), task);
-
- return ret;
-#else
- char buf [64];
- char *s;
-
- s = get_pid_status_item_buf (pid, item, buf, sizeof (buf), error);
- if (s)
- return ((gint64) atol (s)) * multiplier;
- return 0;
-#endif
-}
-
-/**
- * mono_process_get_data:
- * \param pid pid of the process
- * \param data description of data to return
- * \returns a data item of a process like user time, memory use etc,
- * according to the \p data argumet.
- */
-gint64
-mono_process_get_data_with_error (gpointer pid, MonoProcessData data, MonoProcessError *error)
-{
- gint64 val;
- int rpid = GPOINTER_TO_INT (pid);
-
- if (error)
- *error = MONO_PROCESS_ERROR_OTHER;
-
- switch (data) {
- case MONO_PROCESS_NUM_THREADS:
- return get_pid_status_item (rpid, "Threads", error, 1);
- case MONO_PROCESS_USER_TIME:
- return get_process_stat_time (rpid, 10, FALSE, error);
- case MONO_PROCESS_SYSTEM_TIME:
- return get_process_stat_time (rpid, 11, FALSE, error);
- case MONO_PROCESS_TOTAL_TIME:
- return get_process_stat_time (rpid, 10, TRUE, error);
- case MONO_PROCESS_WORKING_SET:
- return get_pid_status_item (rpid, "VmRSS", error, 1024);
- case MONO_PROCESS_WORKING_SET_PEAK:
- val = get_pid_status_item (rpid, "VmHWM", error, 1024);
- if (val == 0)
- val = get_pid_status_item (rpid, "VmRSS", error, 1024);
- return val;
- case MONO_PROCESS_PRIVATE_BYTES:
- return get_pid_status_item (rpid, "VmData", error, 1024);
- case MONO_PROCESS_VIRTUAL_BYTES:
- return get_pid_status_item (rpid, "VmSize", error, 1024);
- case MONO_PROCESS_VIRTUAL_BYTES_PEAK:
- val = get_pid_status_item (rpid, "VmPeak", error, 1024);
- if (val == 0)
- val = get_pid_status_item (rpid, "VmSize", error, 1024);
- return val;
- case MONO_PROCESS_FAULTS:
- return get_process_stat_item (rpid, 6, TRUE, error);
- case MONO_PROCESS_ELAPSED:
- return get_process_stat_time (rpid, 18, FALSE, error);
- case MONO_PROCESS_PPID:
- return get_process_stat_time (rpid, 0, FALSE, error);
- case MONO_PROCESS_PAGED_BYTES:
- return get_pid_status_item (rpid, "VmSwap", error, 1024);
-
- /* Nothing yet */
- case MONO_PROCESS_END:
- return 0;
- }
- return 0;
-}
-
-gint64
-mono_process_get_data (gpointer pid, MonoProcessData data)
-{
- MonoProcessError error;
- return mono_process_get_data_with_error (pid, data, &error);
-}
-
-#ifndef HOST_WIN32
-int
-mono_process_current_pid ()
-{
-#if defined(HAVE_GETPID)
- return (int) getpid ();
-#elif defined(HOST_WASI)
- return 0;
-#else
-#error getpid
-#endif
-}
-#endif /* !HOST_WIN32 */
-
-/**
* mono_cpu_count:
* \returns the number of processors on the system.
*/
-#ifndef HOST_WIN32
int
mono_cpu_count (void)
{
+#ifdef HOST_WIN32
+ SYSTEM_INFO info;
+ GetSystemInfo (&info);
+ return info.dwNumberOfProcessors;
+#else
#ifdef HOST_ANDROID
/* Android tries really hard to save power by powering off CPUs on SMP phones which
* means the normal way to query cpu count returns a wrong value with userspace API.
/*
* Recap from Alexander Köplinger <alex.koeplinger@outlook.com>:
*
- * When we merged the change from PR #2722, we started seeing random failures on ARM in
+ * When we merged the change from mono/mono PR #2722, we started seeing random failures on ARM in
* the MonoTests.System.Threading.ThreadPoolTests.SetAndGetMaxThreads and
* MonoTests.System.Threading.ManualResetEventSlimTests.Constructor_Defaults tests. Both
* of those tests are dealing with Environment.ProcessorCount to verify some implementation
#endif /* defined(HOST_ARM) || defined (HOST_ARM64) */
-#ifdef USE_SYSCTL
+#ifdef HAVE_SYS_SYSCTL_H
{
int count;
int mib [2];
#endif
/* FIXME: warn */
return 1;
-}
-#endif /* !HOST_WIN32 */
-
-static void
-get_cpu_times (int cpu_id, gint64 *user, gint64 *systemt, gint64 *irq, gint64 *sirq, gint64 *idle)
-{
- char buf [256];
- char *s;
- int uhz = get_user_hz ();
- guint64 user_ticks = 0, nice_ticks = 0, system_ticks = 0, idle_ticks = 0, irq_ticks = 0, sirq_ticks = 0;
- FILE *f = fopen ("/proc/stat", "r");
- if (!f)
- return;
- if (cpu_id < 0)
- uhz *= mono_cpu_count ();
- while ((s = fgets (buf, sizeof (buf), f))) {
- char *data = NULL;
- if (cpu_id < 0 && strncmp (s, "cpu", 3) == 0 && g_ascii_isspace (s [3])) {
- data = s + 4;
- } else if (cpu_id >= 0 && strncmp (s, "cpu", 3) == 0 && strtol (s + 3, &data, 10) == cpu_id) {
- if (data == s + 3)
- continue;
- data++;
- } else {
- continue;
- }
-
- user_ticks = strtoull (data, &data, 10);
- nice_ticks = strtoull (data, &data, 10);
- system_ticks = strtoull (data, &data, 10);
- idle_ticks = strtoull (data, &data, 10);
- /* iowait_ticks = strtoull (data, &data, 10); */
- irq_ticks = strtoull (data, &data, 10);
- sirq_ticks = strtoull (data, &data, 10);
- break;
- }
- fclose (f);
-
- if (user)
- *user = (user_ticks + nice_ticks) * 10000000 / uhz;
- if (systemt)
- *systemt = (system_ticks) * 10000000 / uhz;
- if (irq)
- *irq = (irq_ticks) * 10000000 / uhz;
- if (sirq)
- *sirq = (sirq_ticks) * 10000000 / uhz;
- if (idle)
- *idle = (idle_ticks) * 10000000 / uhz;
-}
-
-/**
- * mono_cpu_get_data:
- * \param cpu_id processor number or -1 to get a summary of all the processors
- * \param data type of data to retrieve
- * Get data about a processor on the system, like time spent in user space or idle time.
- */
-gint64
-mono_cpu_get_data (int cpu_id, MonoCpuData data, MonoProcessError *error)
-{
- gint64 value = 0;
-
- if (error)
- *error = MONO_PROCESS_ERROR_NONE;
- switch (data) {
- case MONO_CPU_USER_TIME:
- get_cpu_times (cpu_id, &value, NULL, NULL, NULL, NULL);
- break;
- case MONO_CPU_PRIV_TIME:
- get_cpu_times (cpu_id, NULL, &value, NULL, NULL, NULL);
- break;
- case MONO_CPU_INTR_TIME:
- get_cpu_times (cpu_id, NULL, NULL, &value, NULL, NULL);
- break;
- case MONO_CPU_DCP_TIME:
- get_cpu_times (cpu_id, NULL, NULL, NULL, &value, NULL);
- break;
- case MONO_CPU_IDLE_TIME:
- get_cpu_times (cpu_id, NULL, NULL, NULL, NULL, &value);
- break;
-
- case MONO_CPU_END:
- /* Nothing yet */
- return 0;
- }
- return value;
-}
-
-int
-mono_atexit (void (*func)(void))
-{
-#if defined(HOST_ANDROID) || !defined(HAVE_ATEXIT)
- /* Some versions of android libc doesn't define atexit () */
- return 0;
-#else
- return atexit (func);
-#endif
-}
-
-/*
- * This function returns the cpu usage in percentage,
- * normalized on the number of cores.
- *
- * Warning : the percentage returned can be > 100%. This
- * might happens on systems like Android which, for
- * battery and performance reasons, shut down cores and
- * lie about the number of active cores.
- */
-#ifndef HOST_WIN32
-gint32
-mono_cpu_usage (MonoCpuUsageState *prev)
-{
- gint32 cpu_usage = 0;
-#ifdef HAVE_GETRUSAGE
- gint64 cpu_total_time;
- gint64 cpu_busy_time;
- struct rusage resource_usage;
- gint64 current_time;
- gint64 kernel_time;
- gint64 user_time;
-
- if (getrusage (RUSAGE_SELF, &resource_usage) == -1) {
- g_error ("getrusage() failed, errno is %d (%s)\n", errno, strerror (errno));
- return -1;
- }
-
- current_time = mono_100ns_ticks ();
- kernel_time = resource_usage.ru_stime.tv_sec * 1000 * 1000 * 10 + resource_usage.ru_stime.tv_usec * 10;
- user_time = resource_usage.ru_utime.tv_sec * 1000 * 1000 * 10 + resource_usage.ru_utime.tv_usec * 10;
-
- cpu_busy_time = (user_time - (prev ? prev->user_time : 0)) + (kernel_time - (prev ? prev->kernel_time : 0));
- cpu_total_time = (current_time - (prev ? prev->current_time : 0)) * mono_cpu_count ();
-
- if (prev) {
- prev->kernel_time = kernel_time;
- prev->user_time = user_time;
- prev->current_time = current_time;
- }
-
- if (cpu_total_time > 0 && cpu_busy_time > 0)
- cpu_usage = (gint32)(cpu_busy_time * 100 / cpu_total_time);
#endif
- return cpu_usage;
}
-#endif /* !HOST_WIN32 */
#include <glib.h>
#include <mono/utils/mono-compiler.h>
-#include <mono/utils/mono-publib.h>
-/* never remove or reorder these enums values: they are used in corlib/System */
+MONO_COMPONENT_API
+int
+mono_process_current_pid (void);
-typedef enum {
- MONO_PROCESS_NUM_THREADS,
- MONO_PROCESS_USER_TIME, /* milliseconds */
- MONO_PROCESS_SYSTEM_TIME, /* milliseconds */
- MONO_PROCESS_TOTAL_TIME, /* milliseconds */
- MONO_PROCESS_WORKING_SET,
- MONO_PROCESS_WORKING_SET_PEAK, /* 5 */
- MONO_PROCESS_PRIVATE_BYTES,
- MONO_PROCESS_VIRTUAL_BYTES,
- MONO_PROCESS_VIRTUAL_BYTES_PEAK,
- MONO_PROCESS_FAULTS,
- MONO_PROCESS_ELAPSED, /* 10 */
- MONO_PROCESS_PPID,
- MONO_PROCESS_PAGED_BYTES,
- MONO_PROCESS_END
-} MonoProcessData;
-
-typedef enum {
- MONO_CPU_USER_TIME,
- MONO_CPU_PRIV_TIME,
- MONO_CPU_INTR_TIME,
- MONO_CPU_DCP_TIME,
- MONO_CPU_IDLE_TIME,
- MONO_CPU_END
-} MonoCpuData;
-
-typedef enum {
- MONO_PROCESS_ERROR_NONE, /* no error happened */
- MONO_PROCESS_ERROR_NOT_FOUND, /* process not found */
- MONO_PROCESS_ERROR_OTHER
-} MonoProcessError;
-
-typedef struct _MonoCpuUsageState MonoCpuUsageState;
-#ifndef HOST_WIN32
-struct _MonoCpuUsageState {
- gint64 kernel_time;
- gint64 user_time;
- gint64 current_time;
-};
-#else
-struct _MonoCpuUsageState {
- guint64 kernel_time;
- guint64 user_time;
- guint64 idle_time;
-};
-#endif
-
-gpointer* mono_process_list (int *size);
-
-void mono_process_get_times (gpointer pid, gint64 *start_time, gint64 *user_time, gint64 *kernel_time);
-
-char* mono_process_get_name (gpointer pid, char *buf, int len);
-
-gint64 mono_process_get_data (gpointer pid, MonoProcessData data);
-gint64 mono_process_get_data_with_error (gpointer pid, MonoProcessData data, MonoProcessError *error);
-
-MONO_COMPONENT_API int mono_process_current_pid (void);
-
-MONO_API int mono_cpu_count (void);
-gint64 mono_cpu_get_data (int cpu_id, MonoCpuData data, MonoProcessError *error);
-gint32 mono_cpu_usage (MonoCpuUsageState *prev);
-
-int mono_atexit (void (*func)(void));
-
-#ifndef HOST_WIN32
-
-#include <sys/stat.h>
-#include <unistd.h>
-
-#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
-
-#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
-#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
-#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
-
-#define IMAGE_SIZEOF_SHORT_NAME 8
-
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
-#define IMAGE_DOS_SIGNATURE 0x4d5a
-#define IMAGE_NT_SIGNATURE 0x50450000
-#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0xb10
-#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0xb20
-#else
-#define IMAGE_DOS_SIGNATURE 0x5a4d
-#define IMAGE_NT_SIGNATURE 0x00004550
-#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
-#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
-#endif
-
-typedef struct {
- guint16 e_magic;
- guint16 e_cblp;
- guint16 e_cp;
- guint16 e_crlc;
- guint16 e_cparhdr;
- guint16 e_minalloc;
- guint16 e_maxalloc;
- guint16 e_ss;
- guint16 e_sp;
- guint16 e_csum;
- guint16 e_ip;
- guint16 e_cs;
- guint16 e_lfarlc;
- guint16 e_ovno;
- guint16 e_res[4];
- guint16 e_oemid;
- guint16 e_oeminfo;
- guint16 e_res2[10];
- guint32 e_lfanew;
-} IMAGE_DOS_HEADER;
-
-typedef struct {
- guint16 Machine;
- guint16 NumberOfSections;
- guint32 TimeDateStamp;
- guint32 PointerToSymbolTable;
- guint32 NumberOfSymbols;
- guint16 SizeOfOptionalHeader;
- guint16 Characteristics;
-} IMAGE_FILE_HEADER;
-
-typedef struct {
- guint32 VirtualAddress;
- guint32 Size;
-} IMAGE_DATA_DIRECTORY;
-
-typedef struct {
- guint16 Magic;
- guint8 MajorLinkerVersion;
- guint8 MinorLinkerVersion;
- guint32 SizeOfCode;
- guint32 SizeOfInitializedData;
- guint32 SizeOfUninitializedData;
- guint32 AddressOfEntryPoint;
- guint32 BaseOfCode;
- guint32 BaseOfData;
- guint32 ImageBase;
- guint32 SectionAlignment;
- guint32 FileAlignment;
- guint16 MajorOperatingSystemVersion;
- guint16 MinorOperatingSystemVersion;
- guint16 MajorImageVersion;
- guint16 MinorImageVersion;
- guint16 MajorSubsystemVersion;
- guint16 MinorSubsystemVersion;
- guint32 Win32VersionValue;
- guint32 SizeOfImage;
- guint32 SizeOfHeaders;
- guint32 CheckSum;
- guint16 Subsystem;
- guint16 DllCharacteristics;
- guint32 SizeOfStackReserve;
- guint32 SizeOfStackCommit;
- guint32 SizeOfHeapReserve;
- guint32 SizeOfHeapCommit;
- guint32 LoaderFlags;
- guint32 NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
-} IMAGE_OPTIONAL_HEADER32;
-
-typedef struct {
- guint16 Magic;
- guint8 MajorLinkerVersion;
- guint8 MinorLinkerVersion;
- guint32 SizeOfCode;
- guint32 SizeOfInitializedData;
- guint32 SizeOfUninitializedData;
- guint32 AddressOfEntryPoint;
- guint32 BaseOfCode;
- guint64 ImageBase;
- guint32 SectionAlignment;
- guint32 FileAlignment;
- guint16 MajorOperatingSystemVersion;
- guint16 MinorOperatingSystemVersion;
- guint16 MajorImageVersion;
- guint16 MinorImageVersion;
- guint16 MajorSubsystemVersion;
- guint16 MinorSubsystemVersion;
- guint32 Win32VersionValue;
- guint32 SizeOfImage;
- guint32 SizeOfHeaders;
- guint32 CheckSum;
- guint16 Subsystem;
- guint16 DllCharacteristics;
- guint64 SizeOfStackReserve;
- guint64 SizeOfStackCommit;
- guint64 SizeOfHeapReserve;
- guint64 SizeOfHeapCommit;
- guint32 LoaderFlags;
- guint32 NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
-} IMAGE_OPTIONAL_HEADER64;
-
-#if SIZEOF_VOID_P == 8
-typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER;
-#else
-typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER;
-#endif
-
-typedef struct {
- guint32 Signature;
- IMAGE_FILE_HEADER FileHeader;
- IMAGE_OPTIONAL_HEADER32 OptionalHeader;
-} IMAGE_NT_HEADERS32;
-
-typedef struct {
- guint32 Signature;
- IMAGE_FILE_HEADER FileHeader;
- IMAGE_OPTIONAL_HEADER64 OptionalHeader;
-} IMAGE_NT_HEADERS64;
-
-#if SIZEOF_VOID_P == 8
-typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS;
-#else
-typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS;
-#endif
-
-typedef struct {
- guint8 Name[IMAGE_SIZEOF_SHORT_NAME];
- union {
- guint32 PhysicalAddress;
- guint32 VirtualSize;
- } Misc;
- guint32 VirtualAddress;
- guint32 SizeOfRawData;
- guint32 PointerToRawData;
- guint32 PointerToRelocations;
- guint32 PointerToLinenumbers;
- guint16 NumberOfRelocations;
- guint16 NumberOfLinenumbers;
- guint32 Characteristics;
-} IMAGE_SECTION_HEADER;
-
-#define IMAGE_FIRST_SECTION32(header) ((IMAGE_SECTION_HEADER *)((gsize)(header) + G_STRUCT_OFFSET (IMAGE_NT_HEADERS32, OptionalHeader) + GUINT16_FROM_LE (((IMAGE_NT_HEADERS32 *)(header))->FileHeader.SizeOfOptionalHeader)))
-
-#define RT_CURSOR 0x01
-#define RT_BITMAP 0x02
-#define RT_ICON 0x03
-#define RT_MENU 0x04
-#define RT_DIALOG 0x05
-#define RT_STRING 0x06
-#define RT_FONTDIR 0x07
-#define RT_FONT 0x08
-#define RT_ACCELERATOR 0x09
-#define RT_RCDATA 0x0a
-#define RT_MESSAGETABLE 0x0b
-#define RT_GROUP_CURSOR 0x0c
-#define RT_GROUP_ICON 0x0e
-#define RT_VERSION 0x10
-#define RT_DLGINCLUDE 0x11
-#define RT_PLUGPLAY 0x13
-#define RT_VXD 0x14
-#define RT_ANICURSOR 0x15
-#define RT_ANIICON 0x16
-#define RT_HTML 0x17
-#define RT_MANIFEST 0x18
-
-typedef struct {
- guint32 Characteristics;
- guint32 TimeDateStamp;
- guint16 MajorVersion;
- guint16 MinorVersion;
- guint16 NumberOfNamedEntries;
- guint16 NumberOfIdEntries;
-} IMAGE_RESOURCE_DIRECTORY;
-
-typedef struct {
- union {
- struct {
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- guint32 NameIsString:1;
- guint32 NameOffset:31;
-#else
- guint32 NameOffset:31;
- guint32 NameIsString:1;
-#endif
- };
- guint32 Name;
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- struct {
- guint16 __wapi_big_endian_padding;
- guint16 Id;
- };
-#else
- guint16 Id;
-#endif
- };
- union {
- guint32 OffsetToData;
- struct {
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- guint32 DataIsDirectory:1;
- guint32 OffsetToDirectory:31;
-#else
- guint32 OffsetToDirectory:31;
- guint32 DataIsDirectory:1;
-#endif
- };
- };
-} IMAGE_RESOURCE_DIRECTORY_ENTRY;
-
-typedef struct {
- guint32 OffsetToData;
- guint32 Size;
- guint32 CodePage;
- guint32 Reserved;
-} IMAGE_RESOURCE_DATA_ENTRY;
-
-#endif /* HOST_WIN32 */
+MONO_API
+int
+mono_cpu_count (void);
#endif /* __MONO_PROC_LIB_H__ */
} while (0)
#endif
-#elif defined(__mips__)
-
-# if HAVE_UCONTEXT_H
-# include <ucontext.h>
-# endif
-
-/* No ucontext.h */
-#if defined(TARGET_ANDROID)
-
-#define NGREG 32
-#define NFPREG 32
-
-typedef unsigned long gregset_t[NGREG];
-
-typedef struct fpregset {
- union {
- double fp_dregs[NFPREG];
- struct {
- float _fp_fregs;
- unsigned int _fp_pad;
- } fp_fregs[NFPREG];
- } fp_r;
-} fpregset_t;
-
-typedef struct
- {
- unsigned int regmask;
- unsigned int status;
- unsigned long pc;
- gregset_t gregs;
- fpregset_t fpregs;
- /* missing fields follow */
-} mcontext_t;
-
-typedef struct ucontext
- {
- unsigned long int uc_flags;
- struct ucontext *uc_link;
- stack_t uc_stack;
- mcontext_t uc_mcontext;
- /* missing fields follow */
- } ucontext_t;
-
-#endif
-
-# define UCONTEXT_GREGS(ctx) (((ucontext_t *)(ctx))->uc_mcontext.gregs)
-# define UCONTEXT_FPREGS(ctx) (((ucontext_t *)(ctx))->uc_mcontext.fpregs.fp_r.fp_dregs)
-# define UCONTEXT_REG_PC(ctx) (((ucontext_t *)(ctx))->uc_mcontext.pc)
-
#elif defined(__s390x__)
# if HAVE_UCONTEXT_H
#if defined (HAVE_SYS_PARAM_H)
#include <sys/param.h>
#endif
-#if defined(HAVE_SYS_SYSCTL_H)
-#include <sys/sysctl.h>
-#endif
#if defined(HOST_DARWIN)
#include <mach/mach.h>
Console.WriteLine ();
if (sse1Methods != 92)
- throw new Exception ("New changes in Sse (don't forget to update simd-intrinsics-netcore.c if necessary)");
+ throw new Exception ("New changes in Sse (don't forget to update simd-intrinsics.c if necessary)");
if (sse2Methods != 302)
- throw new Exception ("New changes in Sse2 (don't forget to update simd-intrinsics-netcore.c if necessary)");
+ throw new Exception ("New changes in Sse2 (don't forget to update simd-intrinsics.c if necessary)");
if (sse3Methods != 23)
- throw new Exception ("New changes in Sse3 (don't forget to update simd-intrinsics-netcore.c if necessary)");
+ throw new Exception ("New changes in Sse3 (don't forget to update simd-intrinsics.c if necessary)");
if (ssse3Methods != 29)
- throw new Exception ("New changes in Ssse3 (don't forget to update simd-intrinsics-netcore.c if necessary)");
+ throw new Exception ("New changes in Ssse3 (don't forget to update simd-intrinsics.c if necessary)");
if (sse41Methods != 144)
- throw new Exception ("New changes in Sse41 (don't forget to update simd-intrinsics-netcore.c if necessary)");
+ throw new Exception ("New changes in Sse41 (don't forget to update simd-intrinsics.c if necessary)");
if (sse42Methods != 9)
- throw new Exception ("New changes in Sse42 (don't forget to update simd-intrinsics-netcore.c if necessary)");
+ throw new Exception ("New changes in Sse42 (don't forget to update simd-intrinsics.c if necessary)");
int skipped = 0;
var tests = new SseTests ();