Slight soptimization for utf8/latin1 decoding
[mono-project/dkf.git] / mono / arch / hppa / tramp.c
blobe012436df29064cd145e49e24a2b2698cf473768
1 /*
2 Copyright (c) 2003 Bernie Solomon <bernard@ugsolutions.com>
4 Permission is hereby granted, free of charge, to any person obtaining
5 a copy of this software and associated documentation files (the
6 "Software"), to deal in the Software without restriction, including
7 without limitation the rights to use, copy, modify, merge, publish,
8 distribute, sublicense, and/or sell copies of the Software, and to
9 permit persons to whom the Software is furnished to do so, subject to
10 the following conditions:
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 Trampoline generation for HPPA - currently (Oct 9th 2003) only
25 supports 64 bits - and the HP compiler.
27 #ifndef __linux__
29 #include "mono/interpreter/interp.h"
30 #include "mono/metadata/appdomain.h"
31 #include "mono/metadata/tabledefs.h"
32 #include "hppa-codegen.h"
34 #if SIZEOF_VOID_P != 8
35 #error "HPPA code only currently supports 64bit pointers"
36 #endif
38 // debugging flag which dumps code generated
39 static int debug_asm = 0;
42 static void flush_cache(void *address, int length)
44 #ifdef __GNUC__
45 #error "currently only supports the HP C compiler"
46 #else
47 int cache_line_size = 16;
48 ulong_t end = (ulong_t)address + length;
49 register ulong_t sid;
50 register ulong_t offset = (ulong_t) address;
51 register ulong_t r0 = 0;
53 _asm("LDSID", 0, offset, sid);
54 _asm("MTSP", sid, 0);
55 _asm("FDC", r0, 0, offset);
56 offset = (offset + (cache_line_size - 1)) & ~(cache_line_size - 1);
57 while (offset < end) {
58 (void)_asm("FDC", r0, 0, offset);
59 offset += cache_line_size;
61 _asm("SYNC");
62 offset = (ulong_t) address;
63 _asm("FIC", r0, 0, offset);
64 offset = (offset + (cache_line_size - 1)) & ~(cache_line_size - 1);
65 while (offset < end) {
66 (void)_asm("FIC", r0, 0, offset);
67 offset += cache_line_size;
69 _asm("SYNC");
70 // sync needs at least 7 instructions after it... this is what is used for NOP
71 _asm("OR", 0, 0, 0);
72 _asm("OR", 0, 0, 0);
73 _asm("OR", 0, 0, 0);
74 _asm("OR", 0, 0, 0);
75 _asm("OR", 0, 0, 0);
76 _asm("OR", 0, 0, 0);
77 _asm("OR", 0, 0, 0);
78 #endif
81 static void disassemble (guint32 *code, int n_instrs)
83 const char *tmp_file = "/tmp/mono_adb.in";
84 FILE *fp = fopen(tmp_file, "w");
85 int i;
86 for (i = 0; i < n_instrs; i++)
87 fprintf(fp, "0x%08x=i\n", code[i]);
88 fprintf(fp, "$q\n");
89 fclose(fp);
90 system("adb64 </tmp/mono_adb.in");
91 unlink(tmp_file);
94 #define ADD_INST(code, pc, gen_exp) \
95 do { if ((code) == NULL) (pc)++; else { gen_exp; pc++; } } while (0)
98 * void func (void (*callme)(), void *retval, void *this_obj, stackval *arguments);
101 MonoPIFunc
102 mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
104 int pc, save_pc;
105 int param;
106 void **descriptor;
107 unsigned int *code = NULL;
108 unsigned int *code_start = NULL;
109 int arg_reg;
110 #define FP_ARG_REG(r) (4 + (26 - arg_reg))
111 int arg_offset;
112 int frame_size = 0;
113 int spill_offset;
114 int parameter_offset;
115 int parameter_slot;
116 int args_on_stack;
118 if (debug_asm) {
119 fprintf(stderr, "trampoline: # params %d has this %d exp this %d string %d, ret type %d\n",
120 sig->param_count, sig->hasthis, sig->explicit_this, string_ctor, sig->ret->type);
123 // everything takes 8 bytes unless it is a bigger struct
124 for (param = 0; param < sig->param_count; param++) {
125 if (sig->params[param]->byref)
126 frame_size += 8;
127 else {
128 if (sig->params[param]->type != MONO_TYPE_VALUETYPE)
129 frame_size += 8;
130 else {
131 if (sig->params [param]->data.klass->enumtype)
132 frame_size += 8;
133 else {
134 frame_size += 15; // large structs are 16 byte aligned
135 frame_size &= ~15;
136 frame_size += mono_class_native_size (sig->params [param]->data.klass, NULL);
137 frame_size += 7;
138 frame_size &= ~7;
144 if (sig->hasthis)
145 frame_size += 8;
146 // 16 byte alignment
147 if ((frame_size & 15) != 0)
148 frame_size += 8;
149 // minimum is 64 bytes
150 if (frame_size < 64)
151 frame_size = 64;
153 if (debug_asm)
154 fprintf(stderr, "outgoing frame size: %d\n", frame_size);
156 frame_size += 16; // for the frame marker (called routines stuff return address etc. here)
157 frame_size += 32; // spill area for r4, r5 and r27 (16 byte aligned)
159 spill_offset = -frame_size;
160 parameter_offset = spill_offset + 32; // spill area size is really 24
161 spill_offset += 8;
163 /* the rest executes twice - once to count instructions so we can
164 allocate memory in one block and once to fill it in... the count
165 should be pretty fast anyway...
167 generate:
168 pc = 0;
169 arg_reg = 26;
170 arg_offset = 0;
171 args_on_stack = 0;
172 parameter_slot = parameter_offset;
174 ADD_INST(code, pc, hppa_std(code, 2, -16, 30)); // STD %r2,-16(%r30)
175 ADD_INST(code, pc, hppa_std_ma(code, 3, frame_size, 30));
176 ADD_INST(code, pc, hppa_std(code, 4, spill_offset, 30));
177 ADD_INST(code, pc, hppa_std(code, 5, spill_offset + 8, 30));
178 ADD_INST(code, pc, hppa_copy(code, 29, 3)); // COPY %r29,%r3
179 ADD_INST(code, pc, hppa_std(code, 27, spill_offset + 16, 30));
180 ADD_INST(code, pc, hppa_nop(code)); // NOP
182 ADD_INST(code, pc, hppa_std(code, 26, -64, 29)); // STD %r26,-64(%r29) callme
183 ADD_INST(code, pc, hppa_std(code, 25, -56, 29)); // STD %r25,-56(%r29) retval
184 ADD_INST(code, pc, hppa_std(code, 24, -48, 29)); // STD %r24,-48(%r29) this_obj
185 ADD_INST(code, pc, hppa_std(code, 23, -40, 29)); // STD %r23,-40(%r29) arguments
187 if (sig->param_count > 0)
188 ADD_INST(code, pc, hppa_copy(code, 23, 4)); // r4 is the current pointer to the stackval array of args
190 if (sig->hasthis) {
191 if (sig->call_convention != MONO_CALL_THISCALL) {
192 ADD_INST(code, pc, hppa_copy(code, 24, arg_reg));
193 --arg_reg;
194 parameter_slot += 8;
195 } else {
196 fprintf(stderr, "case I didn't handle\n");
200 for (param = 0; param < sig->param_count; param++) {
201 int type = sig->params[param]->type;
202 if (sig->params[param]->byref) {
203 if (args_on_stack) {
204 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, 5));
205 ADD_INST(code, pc, hppa_std(code, 5, parameter_slot, 30));
206 } else {
207 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, arg_reg));
208 --arg_reg;
210 arg_offset += sizeof(stackval);
211 parameter_slot += 8;
212 continue;
214 typeswitch:
215 switch (type) {
216 case MONO_TYPE_CHAR:
217 case MONO_TYPE_BOOLEAN:
218 case MONO_TYPE_I1:
219 case MONO_TYPE_U1:
220 case MONO_TYPE_I2:
221 case MONO_TYPE_U2:
222 case MONO_TYPE_I4:
223 case MONO_TYPE_U4:
224 if (args_on_stack) {
225 ADD_INST(code, pc, hppa_ldw(code, arg_offset, 4, 5));
226 switch (type) {
227 case MONO_TYPE_I4:
228 case MONO_TYPE_U4:
229 ADD_INST(code, pc, hppa_stw(code, 5, parameter_slot + 4, 30));
230 break;
231 case MONO_TYPE_CHAR:
232 case MONO_TYPE_I2:
233 case MONO_TYPE_U2:
234 ADD_INST(code, pc, hppa_sth(code, 5, parameter_slot + 6, 30));
235 break;
236 case MONO_TYPE_BOOLEAN:
237 case MONO_TYPE_I1:
238 case MONO_TYPE_U1:
239 ADD_INST(code, pc, hppa_stb(code, 5, parameter_slot + 7, 30));
240 break;
242 } else {
243 ADD_INST(code, pc, hppa_ldw(code, arg_offset, 4, arg_reg));
244 --arg_reg;
246 arg_offset += sizeof(stackval);
247 parameter_slot += 8;
248 break;
249 case MONO_TYPE_I8:
250 case MONO_TYPE_U8:
251 case MONO_TYPE_I:
252 case MONO_TYPE_U:
253 case MONO_TYPE_STRING:
254 case MONO_TYPE_OBJECT:
255 case MONO_TYPE_CLASS:
256 case MONO_TYPE_SZARRAY:
257 case MONO_TYPE_PTR:
258 if (args_on_stack) {
259 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, 5));
260 ADD_INST(code, pc, hppa_std(code, 5, parameter_slot, 30));
261 } else {
262 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, arg_reg));
263 --arg_reg;
265 arg_offset += sizeof(stackval);
266 parameter_slot += 8;
267 break;
268 case MONO_TYPE_R8:
269 if (args_on_stack) {
270 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, 5));
271 ADD_INST(code, pc, hppa_std(code, 5, parameter_slot, 30));
272 } else {
273 ADD_INST(code, pc, hppa_fldd(code, arg_offset, 4, FP_ARG_REG(arg_reg)));
274 --arg_reg;
276 arg_offset += sizeof(stackval);
277 parameter_slot += 8;
278 break;
279 case MONO_TYPE_R4:
280 if (args_on_stack) {
281 ADD_INST(code, pc, hppa_fldd(code, arg_offset, 4, 22));
282 ADD_INST(code, pc, hppa_fcnv_dbl_sng(code, 22, 22));
283 ADD_INST(code, pc, hppa_fstw(code, 22, parameter_slot + 4, 30));
284 } else {
285 ADD_INST(code, pc, hppa_fldd(code, arg_offset, 4, FP_ARG_REG(arg_reg)));
286 ADD_INST(code, pc, hppa_fcnv_dbl_sng(code, FP_ARG_REG(arg_reg), FP_ARG_REG(arg_reg)));
287 --arg_reg;
289 arg_offset += sizeof(stackval);
290 parameter_slot += 8;
291 break;
292 case MONO_TYPE_VALUETYPE:
293 if (sig->params [param]->data.klass->enumtype) {
294 type = sig->params [param]->data.klass->enum_basetype->type;
295 goto typeswitch;
296 } else {
297 int size = mono_class_native_size (sig->params [param]->data.klass, NULL);
298 // assumes struct is 8 byte aligned whatever its size... (as interp.c guarantees at present)
299 // copies multiple of 8 bytes which may include some trailing garbage but should be safe
300 if (size <= 8) {
301 if (args_on_stack) {
302 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, 5));
303 ADD_INST(code, pc, hppa_ldd(code, 0, 5, 5));
304 ADD_INST(code, pc, hppa_std(code, 5, parameter_slot, 30));
305 } else {
306 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, arg_reg));
307 ADD_INST(code, pc, hppa_ldd(code, 0, arg_reg, arg_reg));
308 --arg_reg;
310 parameter_slot += 8;
311 } else {
312 int soffset = 0;
313 if ((parameter_slot & 15) != 0) {
314 --arg_reg;
315 if (arg_reg < 19) {
316 args_on_stack = 1;
318 parameter_slot += 8;
320 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, 5));
321 // might generate a lot of code for very large structs... should
322 // use a loop or routine call them
323 while (size > 0) {
324 if (args_on_stack) {
325 ADD_INST(code, pc, hppa_ldd(code, soffset, 5, 31));
326 ADD_INST(code, pc, hppa_std(code, 31, parameter_slot, 30));
327 } else {
328 ADD_INST(code, pc, hppa_ldd(code, soffset, 5, arg_reg));
329 --arg_reg;
330 if (arg_reg < 19)
331 args_on_stack = 1;
333 parameter_slot += 8;
334 soffset += 8;
335 size -= 8;
338 arg_offset += sizeof(stackval);
339 break;
341 break;
342 default:
343 g_error ("mono_create_trampoline: unhandled arg type %d", type);
344 return NULL;
347 if (arg_reg < 19) {
348 args_on_stack = 1;
352 // for large return structs just pass on the buffer given to us.
353 if (sig->ret->type == MONO_TYPE_VALUETYPE && sig->ret->data.klass->enumtype == 0) {
354 int size = mono_class_native_size (sig->ret->data.klass, NULL);
355 if (size > 16) {
356 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 28));
357 ADD_INST(code, pc, hppa_ldd(code, 0, 28, 28));
361 ADD_INST(code, pc, hppa_nop(code)); // NOP
362 ADD_INST(code, pc, hppa_ldd(code, -64, 29, 5));
363 ADD_INST(code, pc, hppa_ldd(code, 24, 5, 27));
364 ADD_INST(code, pc, hppa_ldd(code, 16, 5, 5));
365 ADD_INST(code, pc, hppa_blve(code, 5));
366 ADD_INST(code, pc, hppa_ldo(code, parameter_offset + 64, 30, 29));
367 ADD_INST(code, pc, hppa_ldd(code, spill_offset + 16, 30, 27));
368 ADD_INST(code, pc, hppa_nop(code)); // NOP
370 if (string_ctor) {
371 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
372 ADD_INST(code, pc, hppa_std(code, 28, 0, 19)); // STD %r28,0(%r19)
374 else if (sig->ret->type != MONO_TYPE_VOID) {
375 int type = sig->ret->type;
377 rettypeswitch:
378 switch (type) {
379 case MONO_TYPE_BOOLEAN:
380 case MONO_TYPE_I1:
381 case MONO_TYPE_U1:
382 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
383 ADD_INST(code, pc, hppa_stb(code, 28, 0, 19)); // STB %r28,0(%r19)
384 break;
385 case MONO_TYPE_I4:
386 case MONO_TYPE_U4:
387 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
388 ADD_INST(code, pc, hppa_stw(code, 28, 0, 19)); // STW %r28,0(%r19)
389 break;
390 case MONO_TYPE_CHAR:
391 case MONO_TYPE_I2:
392 case MONO_TYPE_U2:
393 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
394 ADD_INST(code, pc, hppa_sth(code, 28, 0, 19)); // STH %r28,0(%r19)
395 break;
396 case MONO_TYPE_I8:
397 case MONO_TYPE_U8:
398 case MONO_TYPE_I:
399 case MONO_TYPE_U:
400 case MONO_TYPE_STRING:
401 case MONO_TYPE_OBJECT:
402 case MONO_TYPE_CLASS:
403 case MONO_TYPE_SZARRAY:
404 case MONO_TYPE_PTR:
405 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
406 ADD_INST(code, pc, hppa_std(code, 28, 0, 19)); // STD %r28,0(%r19)
407 break;
408 case MONO_TYPE_R8:
409 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
410 ADD_INST(code, pc, hppa_fstd(code, 4, 0, 19)); // FSTD %fr4,0(%r19)
411 break;
412 case MONO_TYPE_R4:
413 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
414 ADD_INST(code, pc, hppa_fstw(code, 4, 0, 19)); // FSTW %fr4r,0(%r19)
415 break;
416 case MONO_TYPE_VALUETYPE:
417 if (sig->ret->data.klass->enumtype) {
418 type = sig->ret->data.klass->enum_basetype->type;
419 goto rettypeswitch;
420 } else {
421 int size = mono_class_native_size (sig->ret->data.klass, NULL);
422 if (size <= 16) {
423 int reg = 28;
424 int off = 0;
425 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19));
426 ADD_INST(code, pc, hppa_ldd(code, 0, 19, 19));
427 if (size > 8) {
428 ADD_INST(code, pc, hppa_std(code, 28, 0, 19));
429 size -= 8;
430 reg = 29;
431 off += 8;
433 // get rest of value right aligned in the register
434 ADD_INST(code, pc, hppa_extrdu(code, reg, 8 * size - 1, 8 * size, reg));
435 if ((size & 1) != 0) {
436 ADD_INST(code, pc, hppa_stb(code, reg, off + size - 1, 19));
437 ADD_INST(code, pc, hppa_extrdu(code, reg, 55, 56, reg));
438 size -= 1;
440 if ((size & 2) != 0) {
441 ADD_INST(code, pc, hppa_sth(code, reg, off + size - 2, 19));
442 ADD_INST(code, pc, hppa_extrdu(code, reg, 47, 48, reg));
443 size -= 2;
445 if ((size & 4) != 0)
446 ADD_INST(code, pc, hppa_stw(code, reg, off + size - 4, 19));
448 break;
450 default:
451 g_error ("mono_create_trampoline: unhandled ret type %d", type);
452 return NULL;
456 ADD_INST(code, pc, hppa_ldd(code, -frame_size-16, 30, 2));
457 ADD_INST(code, pc, hppa_ldd(code, spill_offset, 30, 4));
458 ADD_INST(code, pc, hppa_ldd(code, spill_offset + 8, 30, 5));
459 ADD_INST(code, pc, hppa_bve(code, 2, 0));
460 ADD_INST(code, pc, hppa_ldd_mb(code, -frame_size, 30, 3));
462 if (code == NULL) {
463 descriptor = (void **)g_malloc(4 * sizeof(void *) + pc * sizeof(unsigned int));
464 code = (unsigned int *)((char *)descriptor + 4 * sizeof(void *));
465 code_start = code;
466 save_pc = pc;
467 goto generate;
468 } else
469 g_assert(pc == save_pc);
471 if (debug_asm) {
472 fprintf(stderr, "generated: %d bytes\n", pc * 4);
473 disassemble(code_start, pc);
476 // must do this so we can actually execute the code we just put in memory
477 flush_cache(code_start, 4 * pc);
479 descriptor[0] = 0;
480 descriptor[1] = 0;
481 descriptor[2] = code_start;
482 descriptor[3] = 0;
484 return (MonoPIFunc)descriptor;
487 void *
488 mono_arch_create_method_pointer (MonoMethod *method)
490 MonoMethodSignature *sig = method->signature;
491 MonoJitInfo *ji;
492 int i;
493 int pc;
494 int param;
495 void **descriptor = NULL;
496 void **data = NULL;
497 unsigned int *code = NULL;
498 unsigned int *code_start = NULL;
499 int arg_reg = 26;
500 int arg_offset = 0;
501 int frame_size;
502 int invoke_rec_offset;
503 int stack_vals_offset;
504 int stack_val_pos;
505 int arg_val_pos;
506 int spill_offset;
507 int *vtoffsets;
508 int t;
510 if (debug_asm) {
511 fprintf(stderr, "mono_create_method_pointer %s: flags %d\n", method->name, method->flags);
512 fprintf(stderr, "method: # params %d has this %d exp this %d\n", sig->param_count, sig->hasthis, sig->explicit_this);
513 fprintf(stderr, "ret %d\n", sig->ret->type);
514 for (i = 0; i < sig->param_count; i++)
515 fprintf(stderr, "%d: %d\n", i, sig->params[i]->type);
518 // the extra stackval is for the return val if necessary
519 // the 64 is for outgoing parameters and the 16 is the frame marker.
520 // the other 16 is space for struct return vals < 16 bytes
521 frame_size = sizeof(MonoInvocation) + (sig->param_count + 1) * sizeof(stackval) + 16 + 64 + 16;
522 frame_size += 15;
523 frame_size &= ~15;
524 invoke_rec_offset = -frame_size;
525 vtoffsets = (int *)alloca(sig->param_count * sizeof(int));
527 t = invoke_rec_offset;
529 for (i = 0; i < sig->param_count; ++i)
530 if (sig->params[i]->type == MONO_TYPE_VALUETYPE &&
531 !sig->params[i]->data.klass->enumtype && !sig->params[i]->byref) {
532 int size = mono_class_native_size (sig->params[i]->data.klass, NULL);
533 size += 7;
534 size &= ~7;
535 t -= size;
536 frame_size += size;
537 vtoffsets[i] = t;
540 stack_vals_offset = invoke_rec_offset + sizeof(MonoInvocation);
541 stack_vals_offset += 7;
542 stack_vals_offset &= ~7;
543 frame_size += 32;
544 frame_size += 15;
545 frame_size &= ~15;
546 spill_offset = -frame_size + 8;
548 generate:
549 stack_val_pos = stack_vals_offset;
550 arg_val_pos = -64;
551 pc = 0;
553 ADD_INST(code, pc, hppa_std(code, 2, -16, 30));
554 ADD_INST(code, pc, hppa_std_ma(code, 3, frame_size, 30));
555 ADD_INST(code, pc, hppa_std(code, 4, spill_offset, 30));
556 ADD_INST(code, pc, hppa_copy(code, 29, 3));
557 ADD_INST(code, pc, hppa_std(code, 27, spill_offset + 8, 30));
558 ADD_INST(code, pc, hppa_std(code, 28, spill_offset + 16, 30));
559 ADD_INST(code, pc, hppa_nop(code));
561 ADD_INST(code, pc, hppa_std(code, 26, -64, 29)); // STD %r26,-64(%r29)
562 ADD_INST(code, pc, hppa_std(code, 25, -56, 29)); // STD %r25,-56(%r29)
563 ADD_INST(code, pc, hppa_std(code, 24, -48, 29)); // STD %r24,-48(%r29)
564 ADD_INST(code, pc, hppa_std(code, 23, -40, 29)); // STD %r23,-40(%r29)
565 ADD_INST(code, pc, hppa_std(code, 22, -32, 29)); // STD %r22,-32(%r29)
566 ADD_INST(code, pc, hppa_std(code, 21, -24, 29)); // STD %r21,-24(%r29)
567 ADD_INST(code, pc, hppa_std(code, 20, -16, 29)); // STD %r20,-16(%r29)
568 ADD_INST(code, pc, hppa_std(code, 19, -8, 29)); // STD %r19,-8(%r29)
570 ADD_INST(code, pc, hppa_std(code, 0, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, parent), 30));
571 ADD_INST(code, pc, hppa_std(code, 0, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, ex), 30));
572 ADD_INST(code, pc, hppa_std(code, 0, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, ex_handler), 30));
573 ADD_INST(code, pc, hppa_std(code, 0, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, ip), 30));
575 if (data != NULL)
576 data[0] = method;
577 ADD_INST(code, pc, hppa_ldd(code, 0, 27, 19));
578 ADD_INST(code, pc, hppa_std(code, 19, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, method), 30));
580 if (sig->hasthis) {
581 if (sig->call_convention != MONO_CALL_THISCALL) {
582 ADD_INST(code, pc, hppa_std(code, arg_reg, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, obj), 30));
583 arg_val_pos += 8;
584 } else {
585 fprintf(stderr, "case I didn't handle 2\n");
589 if (data != NULL)
590 data[2] = (void *)stackval_from_data;
592 for (i = 0; i < sig->param_count; ++i) {
593 if (data != NULL)
594 data[4 + i] = sig->params[i];
595 ADD_INST(code, pc, hppa_ldd(code, (4 + i) * 8, 27, 26)); // LDD x(%r27),%r26 == type
596 ADD_INST(code, pc, hppa_ldo(code, stack_val_pos, 30, 25)); // LDD x(%r30),%r25 == &stackval
597 if (sig->params[i]->byref) {
598 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos, 3, 24));
599 } else {
600 int type = sig->params[i]->type;
601 typeswitch:
602 switch (type) {
603 case MONO_TYPE_I8:
604 case MONO_TYPE_U8:
605 case MONO_TYPE_I:
606 case MONO_TYPE_U:
607 case MONO_TYPE_STRING:
608 case MONO_TYPE_OBJECT:
609 case MONO_TYPE_CLASS:
610 case MONO_TYPE_SZARRAY:
611 case MONO_TYPE_PTR:
612 case MONO_TYPE_R8:
613 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos, 3, 24));
614 break;
615 case MONO_TYPE_I4:
616 case MONO_TYPE_U4:
617 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos + 4, 3, 24));
618 break;
619 case MONO_TYPE_CHAR:
620 case MONO_TYPE_I2:
621 case MONO_TYPE_U2:
622 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos + 6, 3, 24));
623 break;
624 case MONO_TYPE_I1:
625 case MONO_TYPE_U1:
626 case MONO_TYPE_BOOLEAN:
627 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos + 7, 3, 24));
628 break;
629 case MONO_TYPE_VALUETYPE:
630 if (sig->params [i]->data.klass->enumtype) {
631 type = sig->params [i]->data.klass->enum_basetype->type;
632 goto typeswitch;
633 } else {
634 int size = mono_class_native_size (sig->params[i]->data.klass, NULL);
635 if (size <= 8)
636 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos, 3, 24));
637 else {
638 arg_val_pos += 15;
639 arg_val_pos &= ~15;
640 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos, 3, 24));
643 arg_val_pos += size;
644 arg_val_pos += 7;
645 arg_val_pos &= ~7;
646 arg_val_pos -=8 ; // as it is incremented later
648 ADD_INST(code, pc, hppa_ldo(code, vtoffsets[i], 30, 19));
649 ADD_INST(code, pc, hppa_std(code, 19, 0, 25));
651 break;
652 default:
653 fprintf(stderr, "can not cope in create method pointer %d\n", sig->params[i]->type);
654 break;
658 ADD_INST(code, pc, hppa_ldo(code, sig->pinvoke, 0, 23)); // LDI sig->pinvoke,%r23
659 ADD_INST(code, pc, hppa_ldd(code, 16, 27, 19)); // LDD x(%r27),%r19 == stackval_from_data
660 ADD_INST(code, pc, hppa_ldd(code, 16, 19, 20)); // LDD 16(%r19),%r20
661 ADD_INST(code, pc, hppa_ldd(code, 24, 19, 27)); // LDD 24(%r19),%r27
662 ADD_INST(code, pc, hppa_blve(code, 20)); // BVE,L (%r20),%r2
663 ADD_INST(code, pc, hppa_ldo(code, -16, 30, 29)); // LDO -16(%r30),%r29
664 ADD_INST(code, pc, hppa_ldd(code, spill_offset + 8, 30, 27));
666 stack_val_pos += sizeof (stackval);
667 arg_val_pos += 8;
668 g_assert(stack_val_pos < -96);
671 ADD_INST(code, pc, hppa_ldo(code, stack_vals_offset, 30, 19));
672 ADD_INST(code, pc, hppa_std(code, 19, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, stack_args), 30));
673 ADD_INST(code, pc, hppa_ldo(code, stack_val_pos, 30, 19));
674 ADD_INST(code, pc, hppa_std(code, 19, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, retval), 30));
676 if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->data.klass->enumtype) {
677 int size = mono_class_native_size (sig->ret->data.klass, NULL);
678 // for large return structs pass on the pointer given us by our caller.
679 if (size > 16)
680 ADD_INST(code, pc, hppa_ldd(code, spill_offset + 16, 30, 28));
681 else // use space left on stack for the return value
682 ADD_INST(code, pc, hppa_ldo(code, stack_val_pos + sizeof(stackval), 30, 28));
683 ADD_INST(code, pc, hppa_std(code, 28, stack_val_pos, 30));
686 ADD_INST(code, pc, hppa_ldo(code, invoke_rec_offset, 30, 26)); // address of invocation
688 if (data != NULL)
689 data[1] = (void *)ves_exec_method;
690 ADD_INST(code, pc, hppa_ldd(code, 8, 27, 19)); // LDD 8(%r27),%r19
691 ADD_INST(code, pc, hppa_ldd(code, 16, 19, 20)); // LDD 16(%r19),%r20
692 ADD_INST(code, pc, hppa_ldd(code, 24, 19, 27)); // LDD 24(%r19),%r27
693 ADD_INST(code, pc, hppa_blve(code, 20)); // BVE,L (%r20),%r2
694 ADD_INST(code, pc, hppa_ldo(code, -16, 30, 29)); // LDO -16(%r30),%r29
695 ADD_INST(code, pc, hppa_ldd(code, spill_offset + 8, 30, 27));
696 if (sig->ret->byref) {
697 fprintf(stderr, "can'ty cope with ret byref\n");
698 } else {
699 int simpletype = sig->ret->type;
700 enum_retvalue:
701 switch (simpletype) {
702 case MONO_TYPE_VOID:
703 break;
704 case MONO_TYPE_BOOLEAN:
705 case MONO_TYPE_I1:
706 case MONO_TYPE_U1:
707 case MONO_TYPE_CHAR:
708 case MONO_TYPE_I2:
709 case MONO_TYPE_U2:
710 case MONO_TYPE_I4:
711 case MONO_TYPE_U4:
712 ADD_INST(code, pc, hppa_ldw(code, stack_val_pos, 30, 28)); // LDW x(%r30),%r28
713 break;
714 case MONO_TYPE_I8:
715 case MONO_TYPE_U8:
716 case MONO_TYPE_I:
717 case MONO_TYPE_U:
718 case MONO_TYPE_STRING:
719 case MONO_TYPE_OBJECT:
720 case MONO_TYPE_CLASS:
721 case MONO_TYPE_SZARRAY:
722 case MONO_TYPE_PTR:
723 ADD_INST(code, pc, hppa_ldd(code, stack_val_pos, 30, 28)); // LDD x(%r30),%r28
724 break;
725 case MONO_TYPE_R8:
726 ADD_INST(code, pc, hppa_fldd(code, stack_val_pos, 30, 4)); // FLDD x(%r30),%fr4
727 break;
728 case MONO_TYPE_VALUETYPE:
729 if (sig->ret->data.klass->enumtype) {
730 simpletype = sig->ret->data.klass->enum_basetype->type;
731 goto enum_retvalue;
732 } else {
733 int size = mono_class_native_size (sig->ret->data.klass, NULL);
734 if (size <= 16) {
735 ADD_INST(code, pc, hppa_ldd(code, stack_val_pos, 30, 28));
736 if (size > 8)
737 ADD_INST(code, pc, hppa_ldd(code, 8, 28, 29));
738 ADD_INST(code, pc, hppa_ldd(code, 0, 28, 28));
741 break;
742 default:
743 fprintf(stderr, "can't cope with ret type %d\n", simpletype);
744 return NULL;
748 ADD_INST(code, pc, hppa_ldd(code, -frame_size-16, 30, 2));
749 ADD_INST(code, pc, hppa_ldd(code, spill_offset, 30, 4));
750 ADD_INST(code, pc, hppa_bve(code, 2, 0));
751 ADD_INST(code, pc, hppa_ldd_mb(code, -frame_size, 30, 3));
752 if (code == NULL) {
753 descriptor = (void **)malloc((8 + sig->param_count) * sizeof(void *) + sizeof(unsigned int) * pc);
754 data = descriptor + 4;
755 code = (unsigned int *)(data + 4 + sig->param_count);
756 code_start = code;
757 goto generate;
760 if (debug_asm) {
761 fprintf(stderr, "generated: %d bytes\n", pc * 4);
762 disassemble(code_start, pc);
765 flush_cache(code_start, 4 * pc);
767 descriptor[0] = 0;
768 descriptor[1] = 0;
769 descriptor[2] = code_start;
770 descriptor[3] = data;
772 ji = g_new0 (MonoJitInfo, 1);
773 ji->method = method;
774 ji->code_size = 4; // does this matter?
775 ji->code_start = descriptor;
777 mono_jit_info_table_add (mono_get_root_domain (), ji);
779 return ji->code_start;
781 #endif