1 /**
2  * \file
3  */
4 
5 #ifndef __MONO_MINI_SPARC_H__
6 #define __MONO_MINI_SPARC_H__
7 
8 #include <mono/arch/sparc/sparc-codegen.h>
9 #include <mono/utils/mono-context.h>
10 
11 #include <glib.h>
12 
13 #define MONO_ARCH_CPU_SPEC sparc_desc
14 
15 #define MONO_MAX_IREGS 32
16 #define MONO_MAX_FREGS 32
17 
18 /* Parameters used by the register allocator */
19 
20 /*
21  * Use %o0..%o5 as local registers, plus %l7 since we need an extra register for
22  * holding the sreg1 in call instructions.
23  */
24 #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))
25 
26 #define MONO_ARCH_CALLEE_SAVED_REGS ((~MONO_ARCH_CALLEE_REGS) & ~(1 << sparc_g1))
27 
28 #ifdef SPARCV9
29 /* Use %d34..%d62 as the double precision floating point local registers */
30 /* %d32 has the same encoding as %f1, so %d36%d38 == 0b1010 == 0xa */
31 #define MONO_ARCH_CALLEE_FREGS (0xaaaaaaa8)
32 #else
33 /* Use %f2..%f30 as the double precision floating point local registers */
34 #define MONO_ARCH_CALLEE_FREGS (0x55555554)
35 #endif
36 
37 #define MONO_ARCH_CALLEE_SAVED_FREGS 0
38 
39 #define MONO_ARCH_USE_FPSTACK FALSE
40 #define MONO_ARCH_FPSTACK_SIZE 0
41 #ifdef SPARCV9
42 #define MONO_ARCH_INST_FIXED_REG(desc) ((desc == 'o') ? sparc_o0 : -1)
43 #else
44 #define MONO_ARCH_INST_FIXED_REG(desc) ((desc == 'o') ? sparc_o0 : ((desc == 'l') ? sparc_o1 : -1))
45 #endif
46 #define MONO_ARCH_INST_SREG2_MASK(ins) (0)
47 
48 #ifdef SPARCV9
49 #define MONO_ARCH_INST_IS_REGPAIR(desc) FALSE
50 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (-1)
51 #else
52 #define MONO_ARCH_INST_IS_REGPAIR(desc) ((desc == 'l') || (desc == 'L'))
53 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (((desc == 'l') ? sparc_o0 : (desc == 'L' ? (hreg1 + 1) : -1)))
54 #endif
55 
56 #if SIZEOF_VOID_P == 8
57 #define MONO_ARCH_FRAME_ALIGNMENT 16
58 #else
59 #define MONO_ARCH_FRAME_ALIGNMENT 8
60 #endif
61 
62 #define MONO_ARCH_CODE_ALIGNMENT 32
63 
64 #ifdef SPARCV9
65 #define MONO_SPARC_STACK_BIAS 2047
66 #else
67 #define MONO_SPARC_STACK_BIAS 0
68 #endif
69 
70 struct MonoLMF {
71 	gpointer    previous_lmf;
72 	gpointer    lmf_addr;
73 	MonoMethod *method;
74 	gpointer    ip;
75 	gpointer    sp;
76 	gpointer    ebp;
77 };
78 
79 typedef struct MonoCompileArch {
80 	gint32 lmf_offset;
81 	gint32 localloc_offset;
82 	void *float_spill_slot;
83 } MonoCompileArch;
84 
85 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,start_func) do {	\
86 		mono_arch_flush_register_windows ();	\
87 		MONO_CONTEXT_SET_IP ((ctx), (start_func));	\
88 		MONO_CONTEXT_SET_BP ((ctx), __builtin_frame_address (0));	\
89 		MONO_CONTEXT_SET_SP ((ctx), __builtin_frame_address (0));	\
90 	} while (0)
91 
92 #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf) do { (lmf)->ebp = -1; } while (0)
93 
94 #define MONO_ARCH_USE_SIGACTION 1
95 
96 #ifdef HAVE_WORKING_SIGALTSTACK
97 /*#define MONO_ARCH_SIGSEGV_ON_ALTSTACK*/
98 #endif
99 
100 #define MONO_ARCH_EMULATE_FCONV_TO_I8   1
101 #define MONO_ARCH_EMULATE_LCONV_TO_R8   1
102 #define MONO_ARCH_EMULATE_LCONV_TO_R4   1
103 #define MONO_ARCH_EMULATE_CONV_R8_UN    1
104 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
105 #define MONO_ARCH_EMULATE_FREM 1
106 #define MONO_ARCH_NEED_DIV_CHECK 1
107 #define MONO_ARCH_IMT_REG sparc_g1
108 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
109 #define MONO_ARCH_HAVE_TLS_INIT 1
110 
111 void mono_arch_tls_init (void);
112 
113 #ifdef SPARCV9
114 #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
115 #endif
116 
117 #ifndef __GNUC__
118 /* assume Sun compiler if not GCC */
__builtin_return_address(int depth)119 static void * __builtin_return_address(int depth)
120 {
121 	asm("ta      3");
122 	asm("tst     %i0");
123 	asm("be      retAddr_End");
124 	asm("mov     %fp, %l0");
125 	asm("retAddr_Start:");
126 	asm("sub     %i0, 1, %i0");
127 	asm("tst     %i0");
128 	asm("bne     retAddr_Start");
129 #if SPARCV9
130 	asm("ldx     [%l0+2159], %l0");
131 	asm("retAddr_End:");
132 	asm("ldx     [%l0+2167], %i0");
133 #else
134 	asm("ld      [%l0+56], %l0");
135 	asm("retAddr_End:");
136 	asm("ld      [%l0+60], %i0");
137 #endif
138 }
139 
__builtin_frame_address(int depth)140 static void * __builtin_frame_address(int depth)
141 {
142 	asm("ta      3");
143 	asm("tst     %i0");
144 	asm("be      frameAddr_End");
145 	asm("mov     %fp, %l0");
146 	asm("frameAddr_Start:");
147 	asm("sub     %i0, 1, %i0");
148 	asm("tst     %i0");
149 	asm("bne     frameAddr_Start");
150 #if SPARCV9
151 	asm("ldx     [%l0+2159], %l0");
152 	asm("frameAddr_End:");
153 	asm("ldx     [%l0+2159], %i0");
154 #else
155 	asm("ld      [%l0+56], %l0");
156 	asm("frameAddr_End:");
157 	asm("ld      [%l0+56], %i0");
158 #endif
159 }
160 #endif
161 
162 gboolean mono_sparc_is_virtual_call (guint32 *code);
163 
164 gpointer* mono_sparc_get_vcall_slot_addr (guint32 *code, mgreg_t *regs);
165 
166 void mono_sparc_flushw (void);
167 
168 gboolean mono_sparc_is_v9 (void);
169 
170 gboolean mono_sparc_is_sparc64 (void);
171 
172 struct MonoCompile;
173 
174 guint32* mono_sparc_emit_save_lmf (guint32* code, guint32 lmf_offset);
175 
176 guint32* mono_sparc_emit_restore_lmf (guint32 *code, guint32 lmf_offset);
177 
178 #endif /* __MONO_MINI_SPARC_H__ */
179