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 #include "mono/interpreter/interp.h"
28 #include "mono/metadata/appdomain.h"
29 #include "mono/metadata/tabledefs.h"
30 #include "hppa-codegen.h"
32 #if SIZEOF_VOID_P != 8
33 #error "HPPA code only currently supports 64bit pointers"
36 // debugging flag which dumps code generated
37 static int debug_asm = 0;
40 static void flush_cache(void *address, int length)
43 #error "currently only supports the HP C compiler"
45 int cache_line_size = 16;
46 ulong_t end = (ulong_t)address + length;
48 register ulong_t offset = (ulong_t) address;
49 register ulong_t r0 = 0;
51 _asm("LDSID", 0, offset, sid);
53 _asm("FDC", r0, 0, offset);
54 offset = (offset + (cache_line_size - 1)) & ~(cache_line_size - 1);
55 while (offset < end) {
56 (void)_asm("FDC", r0, 0, offset);
57 offset += cache_line_size;
60 offset = (ulong_t) address;
61 _asm("FIC", r0, 0, offset);
62 offset = (offset + (cache_line_size - 1)) & ~(cache_line_size - 1);
63 while (offset < end) {
64 (void)_asm("FIC", r0, 0, offset);
65 offset += cache_line_size;
68 // sync needs at least 7 instructions after it... this is what is used for NOP
79 static void disassemble (guint32 *code, int n_instrs)
81 const char *tmp_file = "/tmp/mono_adb.in";
82 FILE *fp = fopen(tmp_file, "w");
84 for (i = 0; i < n_instrs; i++)
85 fprintf(fp, "0x%08x=i\n", code[i]);
88 system("adb64 </tmp/mono_adb.in");
92 #define ADD_INST(code, pc, gen_exp) \
93 do { if ((code) == NULL) (pc)++; else { gen_exp; pc++; } } while (0)
96 * void func (void (*callme)(), void *retval, void *this_obj, stackval *arguments);
100 mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
105 unsigned int *code = NULL;
106 unsigned int *code_start = NULL;
108 #define FP_ARG_REG(r) (4 + (26 - arg_reg))
112 int parameter_offset;
117 fprintf(stderr, "trampoline: # params %d has this %d exp this %d string %d, ret type %d\n",
118 sig->param_count, sig->hasthis, sig->explicit_this, string_ctor, sig->ret->type);
121 // everything takes 8 bytes unless it is a bigger struct
122 for (param = 0; param < sig->param_count; param++) {
123 if (sig->params[param]->byref)
126 if (sig->params[param]->type != MONO_TYPE_VALUETYPE)
129 if (sig->params [param]->data.klass->enumtype)
132 frame_size += 15; // large structs are 16 byte aligned
134 frame_size += mono_class_native_size (sig->params [param]->data.klass, NULL);
145 if ((frame_size & 15) != 0)
147 // minimum is 64 bytes
152 fprintf(stderr, "outgoing frame size: %d\n", frame_size);
154 frame_size += 16; // for the frame marker (called routines stuff return address etc. here)
155 frame_size += 32; // spill area for r4, r5 and r27 (16 byte aligned)
157 spill_offset = -frame_size;
158 parameter_offset = spill_offset + 32; // spill area size is really 24
161 /* the rest executes twice - once to count instructions so we can
162 allocate memory in one block and once to fill it in... the count
163 should be pretty fast anyway...
170 parameter_slot = parameter_offset;
172 ADD_INST(code, pc, hppa_std(code, 2, -16, 30)); // STD %r2,-16(%r30)
173 ADD_INST(code, pc, hppa_std_ma(code, 3, frame_size, 30));
174 ADD_INST(code, pc, hppa_std(code, 4, spill_offset, 30));
175 ADD_INST(code, pc, hppa_std(code, 5, spill_offset + 8, 30));
176 ADD_INST(code, pc, hppa_copy(code, 29, 3)); // COPY %r29,%r3
177 ADD_INST(code, pc, hppa_std(code, 27, spill_offset + 16, 30));
178 ADD_INST(code, pc, hppa_nop(code)); // NOP
180 ADD_INST(code, pc, hppa_std(code, 26, -64, 29)); // STD %r26,-64(%r29) callme
181 ADD_INST(code, pc, hppa_std(code, 25, -56, 29)); // STD %r25,-56(%r29) retval
182 ADD_INST(code, pc, hppa_std(code, 24, -48, 29)); // STD %r24,-48(%r29) this_obj
183 ADD_INST(code, pc, hppa_std(code, 23, -40, 29)); // STD %r23,-40(%r29) arguments
185 if (sig->param_count > 0)
186 ADD_INST(code, pc, hppa_copy(code, 23, 4)); // r4 is the current pointer to the stackval array of args
189 if (sig->call_convention != MONO_CALL_THISCALL) {
190 ADD_INST(code, pc, hppa_copy(code, 24, arg_reg));
194 fprintf(stderr, "case I didn't handle\n");
198 for (param = 0; param < sig->param_count; param++) {
199 int type = sig->params[param]->type;
200 if (sig->params[param]->byref) {
202 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, 5));
203 ADD_INST(code, pc, hppa_std(code, 5, parameter_slot, 30));
205 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, arg_reg));
208 arg_offset += sizeof(stackval);
215 case MONO_TYPE_BOOLEAN:
223 ADD_INST(code, pc, hppa_ldw(code, arg_offset, 4, 5));
227 ADD_INST(code, pc, hppa_stw(code, 5, parameter_slot + 4, 30));
232 ADD_INST(code, pc, hppa_sth(code, 5, parameter_slot + 6, 30));
234 case MONO_TYPE_BOOLEAN:
237 ADD_INST(code, pc, hppa_stb(code, 5, parameter_slot + 7, 30));
241 ADD_INST(code, pc, hppa_ldw(code, arg_offset, 4, arg_reg));
244 arg_offset += sizeof(stackval);
251 case MONO_TYPE_STRING:
252 case MONO_TYPE_OBJECT:
253 case MONO_TYPE_CLASS:
254 case MONO_TYPE_SZARRAY:
257 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, 5));
258 ADD_INST(code, pc, hppa_std(code, 5, parameter_slot, 30));
260 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, arg_reg));
263 arg_offset += sizeof(stackval);
268 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, 5));
269 ADD_INST(code, pc, hppa_std(code, 5, parameter_slot, 30));
271 ADD_INST(code, pc, hppa_fldd(code, arg_offset, 4, FP_ARG_REG(arg_reg)));
274 arg_offset += sizeof(stackval);
279 ADD_INST(code, pc, hppa_fldd(code, arg_offset, 4, 22));
280 ADD_INST(code, pc, hppa_fcnv_dbl_sng(code, 22, 22));
281 ADD_INST(code, pc, hppa_fstw(code, 22, parameter_slot + 4, 30));
283 ADD_INST(code, pc, hppa_fldd(code, arg_offset, 4, FP_ARG_REG(arg_reg)));
284 ADD_INST(code, pc, hppa_fcnv_dbl_sng(code, FP_ARG_REG(arg_reg), FP_ARG_REG(arg_reg)));
287 arg_offset += sizeof(stackval);
290 case MONO_TYPE_VALUETYPE:
291 if (sig->params [param]->data.klass->enumtype) {
292 type = sig->params [param]->data.klass->enum_basetype->type;
295 int size = mono_class_native_size (sig->params [param]->data.klass, NULL);
296 // assumes struct is 8 byte aligned whatever its size... (as interp.c guarantees at present)
297 // copies multiple of 8 bytes which may include some trailing garbage but should be safe
300 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, 5));
301 ADD_INST(code, pc, hppa_ldd(code, 0, 5, 5));
302 ADD_INST(code, pc, hppa_std(code, 5, parameter_slot, 30));
304 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, arg_reg));
305 ADD_INST(code, pc, hppa_ldd(code, 0, arg_reg, arg_reg));
311 if ((parameter_slot & 15) != 0) {
318 ADD_INST(code, pc, hppa_ldd(code, arg_offset, 4, 5));
319 // might generate a lot of code for very large structs... should
320 // use a loop or routine call them
323 ADD_INST(code, pc, hppa_ldd(code, soffset, 5, 31));
324 ADD_INST(code, pc, hppa_std(code, 31, parameter_slot, 30));
326 ADD_INST(code, pc, hppa_ldd(code, soffset, 5, arg_reg));
336 arg_offset += sizeof(stackval);
341 g_error ("mono_create_trampoline: unhandled arg type %d", type);
350 // for large return structs just pass on the buffer given to us.
351 if (sig->ret->type == MONO_TYPE_VALUETYPE && sig->ret->data.klass->enumtype == 0) {
352 int size = mono_class_native_size (sig->ret->data.klass, NULL);
354 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 28));
355 ADD_INST(code, pc, hppa_ldd(code, 0, 28, 28));
359 ADD_INST(code, pc, hppa_nop(code)); // NOP
360 ADD_INST(code, pc, hppa_ldd(code, -64, 29, 5));
361 ADD_INST(code, pc, hppa_ldd(code, 24, 5, 27));
362 ADD_INST(code, pc, hppa_ldd(code, 16, 5, 5));
363 ADD_INST(code, pc, hppa_blve(code, 5));
364 ADD_INST(code, pc, hppa_ldo(code, parameter_offset + 64, 30, 29));
365 ADD_INST(code, pc, hppa_ldd(code, spill_offset + 16, 30, 27));
366 ADD_INST(code, pc, hppa_nop(code)); // NOP
369 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
370 ADD_INST(code, pc, hppa_std(code, 28, 0, 19)); // STD %r28,0(%r19)
372 else if (sig->ret->type != MONO_TYPE_VOID) {
373 int type = sig->ret->type;
377 case MONO_TYPE_BOOLEAN:
380 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
381 ADD_INST(code, pc, hppa_stb(code, 28, 0, 19)); // STB %r28,0(%r19)
385 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
386 ADD_INST(code, pc, hppa_stw(code, 28, 0, 19)); // STW %r28,0(%r19)
391 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
392 ADD_INST(code, pc, hppa_sth(code, 28, 0, 19)); // STH %r28,0(%r19)
398 case MONO_TYPE_STRING:
399 case MONO_TYPE_OBJECT:
400 case MONO_TYPE_CLASS:
401 case MONO_TYPE_SZARRAY:
403 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
404 ADD_INST(code, pc, hppa_std(code, 28, 0, 19)); // STD %r28,0(%r19)
407 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
408 ADD_INST(code, pc, hppa_fstd(code, 4, 0, 19)); // FSTD %fr4,0(%r19)
411 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19)); // LDD -56(%r3),%r19
412 ADD_INST(code, pc, hppa_fstw(code, 4, 0, 19)); // FSTW %fr4r,0(%r19)
414 case MONO_TYPE_VALUETYPE:
415 if (sig->ret->data.klass->enumtype) {
416 type = sig->ret->data.klass->enum_basetype->type;
419 int size = mono_class_native_size (sig->ret->data.klass, NULL);
423 ADD_INST(code, pc, hppa_ldd(code, -56, 3, 19));
424 ADD_INST(code, pc, hppa_ldd(code, 0, 19, 19));
426 ADD_INST(code, pc, hppa_std(code, 28, 0, 19));
431 // get rest of value right aligned in the register
432 ADD_INST(code, pc, hppa_extrdu(code, reg, 8 * size - 1, 8 * size, reg));
433 if ((size & 1) != 0) {
434 ADD_INST(code, pc, hppa_stb(code, reg, off + size - 1, 19));
435 ADD_INST(code, pc, hppa_extrdu(code, reg, 55, 56, reg));
438 if ((size & 2) != 0) {
439 ADD_INST(code, pc, hppa_sth(code, reg, off + size - 2, 19));
440 ADD_INST(code, pc, hppa_extrdu(code, reg, 47, 48, reg));
444 ADD_INST(code, pc, hppa_stw(code, reg, off + size - 4, 19));
449 g_error ("mono_create_trampoline: unhandled ret type %d", type);
454 ADD_INST(code, pc, hppa_ldd(code, -frame_size-16, 30, 2));
455 ADD_INST(code, pc, hppa_ldd(code, spill_offset, 30, 4));
456 ADD_INST(code, pc, hppa_ldd(code, spill_offset + 8, 30, 5));
457 ADD_INST(code, pc, hppa_bve(code, 2, 0));
458 ADD_INST(code, pc, hppa_ldd_mb(code, -frame_size, 30, 3));
461 descriptor = (void **)g_malloc(4 * sizeof(void *) + pc * sizeof(unsigned int));
462 code = (unsigned int *)((char *)descriptor + 4 * sizeof(void *));
467 g_assert(pc == save_pc);
470 fprintf(stderr, "generated: %d bytes\n", pc * 4);
471 disassemble(code_start, pc);
474 // must do this so we can actually execute the code we just put in memory
475 flush_cache(code_start, 4 * pc);
479 descriptor[2] = code_start;
482 return (MonoPIFunc)descriptor;
486 mono_arch_create_method_pointer (MonoMethod *method)
488 MonoMethodSignature *sig = method->signature;
493 void **descriptor = NULL;
495 unsigned int *code = NULL;
496 unsigned int *code_start = NULL;
500 int invoke_rec_offset;
501 int stack_vals_offset;
509 fprintf(stderr, "mono_create_method_pointer %s: flags %d\n", method->name, method->flags);
510 fprintf(stderr, "method: # params %d has this %d exp this %d\n", sig->param_count, sig->hasthis, sig->explicit_this);
511 fprintf(stderr, "ret %d\n", sig->ret->type);
512 for (i = 0; i < sig->param_count; i++)
513 fprintf(stderr, "%d: %d\n", i, sig->params[i]->type);
516 // the extra stackval is for the return val if necessary
517 // the 64 is for outgoing parameters and the 16 is the frame marker.
518 // the other 16 is space for struct return vals < 16 bytes
519 frame_size = sizeof(MonoInvocation) + (sig->param_count + 1) * sizeof(stackval) + 16 + 64 + 16;
522 invoke_rec_offset = -frame_size;
523 vtoffsets = (int *)alloca(sig->param_count * sizeof(int));
525 t = invoke_rec_offset;
527 for (i = 0; i < sig->param_count; ++i)
528 if (sig->params[i]->type == MONO_TYPE_VALUETYPE &&
529 !sig->params[i]->data.klass->enumtype && !sig->params[i]->byref) {
530 int size = mono_class_native_size (sig->params[i]->data.klass, NULL);
538 stack_vals_offset = invoke_rec_offset + sizeof(MonoInvocation);
539 stack_vals_offset += 7;
540 stack_vals_offset &= ~7;
544 spill_offset = -frame_size + 8;
547 stack_val_pos = stack_vals_offset;
551 ADD_INST(code, pc, hppa_std(code, 2, -16, 30));
552 ADD_INST(code, pc, hppa_std_ma(code, 3, frame_size, 30));
553 ADD_INST(code, pc, hppa_std(code, 4, spill_offset, 30));
554 ADD_INST(code, pc, hppa_copy(code, 29, 3));
555 ADD_INST(code, pc, hppa_std(code, 27, spill_offset + 8, 30));
556 ADD_INST(code, pc, hppa_std(code, 28, spill_offset + 16, 30));
557 ADD_INST(code, pc, hppa_nop(code));
559 ADD_INST(code, pc, hppa_std(code, 26, -64, 29)); // STD %r26,-64(%r29)
560 ADD_INST(code, pc, hppa_std(code, 25, -56, 29)); // STD %r25,-56(%r29)
561 ADD_INST(code, pc, hppa_std(code, 24, -48, 29)); // STD %r24,-48(%r29)
562 ADD_INST(code, pc, hppa_std(code, 23, -40, 29)); // STD %r23,-40(%r29)
563 ADD_INST(code, pc, hppa_std(code, 22, -32, 29)); // STD %r22,-32(%r29)
564 ADD_INST(code, pc, hppa_std(code, 21, -24, 29)); // STD %r21,-24(%r29)
565 ADD_INST(code, pc, hppa_std(code, 20, -16, 29)); // STD %r20,-16(%r29)
566 ADD_INST(code, pc, hppa_std(code, 19, -8, 29)); // STD %r19,-8(%r29)
568 ADD_INST(code, pc, hppa_std(code, 0, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, parent), 30));
569 ADD_INST(code, pc, hppa_std(code, 0, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, child), 30));
570 ADD_INST(code, pc, hppa_std(code, 0, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, ex), 30));
571 ADD_INST(code, pc, hppa_std(code, 0, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, ex_handler), 30));
572 ADD_INST(code, pc, hppa_std(code, 0, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, ip), 30));
576 ADD_INST(code, pc, hppa_ldd(code, 0, 27, 19));
577 ADD_INST(code, pc, hppa_std(code, 19, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, method), 30));
580 if (sig->call_convention != MONO_CALL_THISCALL) {
581 ADD_INST(code, pc, hppa_std(code, arg_reg, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, obj), 30));
584 fprintf(stderr, "case I didn't handle 2\n");
589 data[2] = (void *)stackval_from_data;
591 for (i = 0; i < sig->param_count; ++i) {
593 data[4 + i] = sig->params[i];
594 ADD_INST(code, pc, hppa_ldd(code, (4 + i) * 8, 27, 26)); // LDD x(%r27),%r26 == type
595 ADD_INST(code, pc, hppa_ldo(code, stack_val_pos, 30, 25)); // LDD x(%r30),%r25 == &stackval
596 if (sig->params[i]->byref) {
597 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos, 3, 24));
599 int type = sig->params[i]->type;
606 case MONO_TYPE_STRING:
607 case MONO_TYPE_OBJECT:
608 case MONO_TYPE_CLASS:
609 case MONO_TYPE_SZARRAY:
612 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos, 3, 24));
616 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos + 4, 3, 24));
621 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos + 6, 3, 24));
625 case MONO_TYPE_BOOLEAN:
626 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos + 7, 3, 24));
628 case MONO_TYPE_VALUETYPE:
629 if (sig->params [i]->data.klass->enumtype) {
630 type = sig->params [i]->data.klass->enum_basetype->type;
633 int size = mono_class_native_size (sig->params[i]->data.klass, NULL);
635 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos, 3, 24));
639 ADD_INST(code, pc, hppa_ldo(code, arg_val_pos, 3, 24));
645 arg_val_pos -=8 ; // as it is incremented later
647 ADD_INST(code, pc, hppa_ldo(code, vtoffsets[i], 30, 19));
648 ADD_INST(code, pc, hppa_std(code, 19, 0, 25));
652 fprintf(stderr, "can not cope in create method pointer %d\n", sig->params[i]->type);
657 ADD_INST(code, pc, hppa_ldo(code, sig->pinvoke, 0, 23)); // LDI sig->pinvoke,%r23
658 ADD_INST(code, pc, hppa_ldd(code, 16, 27, 19)); // LDD x(%r27),%r19 == stackval_from_data
659 ADD_INST(code, pc, hppa_ldd(code, 16, 19, 20)); // LDD 16(%r19),%r20
660 ADD_INST(code, pc, hppa_ldd(code, 24, 19, 27)); // LDD 24(%r19),%r27
661 ADD_INST(code, pc, hppa_blve(code, 20)); // BVE,L (%r20),%r2
662 ADD_INST(code, pc, hppa_ldo(code, -16, 30, 29)); // LDO -16(%r30),%r29
663 ADD_INST(code, pc, hppa_ldd(code, spill_offset + 8, 30, 27));
665 stack_val_pos += sizeof (stackval);
667 g_assert(stack_val_pos < -96);
670 ADD_INST(code, pc, hppa_ldo(code, stack_vals_offset, 30, 19));
671 ADD_INST(code, pc, hppa_std(code, 19, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, stack_args), 30));
672 ADD_INST(code, pc, hppa_ldo(code, stack_val_pos, 30, 19));
673 ADD_INST(code, pc, hppa_std(code, 19, invoke_rec_offset + G_STRUCT_OFFSET (MonoInvocation, retval), 30));
675 if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->data.klass->enumtype) {
676 int size = mono_class_native_size (sig->ret->data.klass, NULL);
677 // for large return structs pass on the pointer given us by our caller.
679 ADD_INST(code, pc, hppa_ldd(code, spill_offset + 16, 30, 28));
680 else // use space left on stack for the return value
681 ADD_INST(code, pc, hppa_ldo(code, stack_val_pos + sizeof(stackval), 30, 28));
682 ADD_INST(code, pc, hppa_std(code, 28, stack_val_pos, 30));
685 ADD_INST(code, pc, hppa_ldo(code, invoke_rec_offset, 30, 26)); // address of invocation
688 data[1] = (void *)ves_exec_method;
689 ADD_INST(code, pc, hppa_ldd(code, 8, 27, 19)); // LDD 8(%r27),%r19
690 ADD_INST(code, pc, hppa_ldd(code, 16, 19, 20)); // LDD 16(%r19),%r20
691 ADD_INST(code, pc, hppa_ldd(code, 24, 19, 27)); // LDD 24(%r19),%r27
692 ADD_INST(code, pc, hppa_blve(code, 20)); // BVE,L (%r20),%r2
693 ADD_INST(code, pc, hppa_ldo(code, -16, 30, 29)); // LDO -16(%r30),%r29
694 ADD_INST(code, pc, hppa_ldd(code, spill_offset + 8, 30, 27));
695 if (sig->ret->byref) {
696 fprintf(stderr, "can'ty cope with ret byref\n");
698 int simpletype = sig->ret->type;
700 switch (simpletype) {
703 case MONO_TYPE_BOOLEAN:
711 ADD_INST(code, pc, hppa_ldw(code, stack_val_pos, 30, 28)); // LDW x(%r30),%r28
717 case MONO_TYPE_STRING:
718 case MONO_TYPE_OBJECT:
719 case MONO_TYPE_CLASS:
720 case MONO_TYPE_SZARRAY:
722 ADD_INST(code, pc, hppa_ldd(code, stack_val_pos, 30, 28)); // LDD x(%r30),%r28
725 ADD_INST(code, pc, hppa_fldd(code, stack_val_pos, 30, 4)); // FLDD x(%r30),%fr4
727 case MONO_TYPE_VALUETYPE:
728 if (sig->ret->data.klass->enumtype) {
729 simpletype = sig->ret->data.klass->enum_basetype->type;
732 int size = mono_class_native_size (sig->ret->data.klass, NULL);
734 ADD_INST(code, pc, hppa_ldd(code, stack_val_pos, 30, 28));
736 ADD_INST(code, pc, hppa_ldd(code, 8, 28, 29));
737 ADD_INST(code, pc, hppa_ldd(code, 0, 28, 28));
742 fprintf(stderr, "can't cope with ret type %d\n", simpletype);
747 ADD_INST(code, pc, hppa_ldd(code, -frame_size-16, 30, 2));
748 ADD_INST(code, pc, hppa_ldd(code, spill_offset, 30, 4));
749 ADD_INST(code, pc, hppa_bve(code, 2, 0));
750 ADD_INST(code, pc, hppa_ldd_mb(code, -frame_size, 30, 3));
752 descriptor = (void **)malloc((8 + sig->param_count) * sizeof(void *) + sizeof(unsigned int) * pc);
753 data = descriptor + 4;
754 code = (unsigned int *)(data + 4 + sig->param_count);
760 fprintf(stderr, "generated: %d bytes\n", pc * 4);
761 disassemble(code_start, pc);
764 flush_cache(code_start, 4 * pc);
768 descriptor[2] = code_start;
769 descriptor[3] = data;
771 ji = g_new0 (MonoJitInfo, 1);
773 ji->code_size = 4; // does this matter?
774 ji->code_start = descriptor;
776 mono_jit_info_table_add (mono_root_domain, ji);
778 return ji->code_start;