0774f4e41193f05c72705550d9a996b7b6a123f9
[cacao.git] / src / vm / jit / m68k / patcher.c
1 /* src/vm/jit/m68k/patcher.c - m68k patcher functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
26
27 */
28
29 #include "config.h"
30
31 #include <assert.h>
32 #include <stdint.h>
33
34 #include "vm/types.h"
35
36 #include "mm/memory.h"
37 #include "native/native.h"
38
39 #include "vm/builtin.h"
40 #include "vm/exceptions.h"
41 #include "vm/initialize.h"
42 #include "vm/resolve.h"
43
44 #include "vm/jit/asmpart.h"
45 #include "vm/jit/patcher.h"
46 #include "vm/jit/md.h"
47 #include "vm/jit/methodheader.h"
48 #include "vm/jit/stacktrace.h"
49
50 #include "vmcore/class.h"
51 #include "vmcore/field.h"
52 #include "vmcore/options.h"
53 #include "vmcore/references.h"
54
55 #include "codegen.h"
56
57 /* patcher_wrapper *************************************************************
58
59    Wrapper for all patchers.  It also creates the stackframe info
60    structure.
61
62    If the return value of the patcher function is false, it gets the
63    exception object, clears the exception pointer and returns the
64    exception.
65
66 *******************************************************************************/
67
68 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
69 {
70         stackframeinfo     sfi;
71         u1                *xpc;
72         java_objectheader *o;
73         functionptr        f;
74         bool               result;
75         java_objectheader *e;
76
77         /* define the patcher function */
78
79         bool (*patcher_function)(u1 *);
80
81         /* get stuff from the stack */
82
83         xpc = (u1 *)                *((ptrint *) (sp + 6 * 4));
84         /* REG_ITMP3                              sp + 5 * 4 */
85         o   = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
86         /*mcode =                                   *((u4*)      (sp + 3 * 4));*/
87         /*xmcode =                                      *((u4*)      (sp + 2 * 4));*/
88         /* unresolved file                        sp + 1 * 4 */
89         f   = (functionptr)         *((ptrint *) (sp + 0 * 4));
90
91
92         /* calculate and set the new return address */
93         xpc = xpc - PATCHER_CALL_SIZE;
94         *((ptrint *) (sp + 6 * 4)) = (ptrint) xpc;
95
96
97         /* cast the passed function to a patcher function */
98         patcher_function = (bool (*)(u1 *)) (ptrint) f;
99
100         /* enter a monitor on the patching position */
101         PATCHER_MONITORENTER;
102
103         /* create the stackframeinfo */
104
105         /* RA is passed as NULL, but the XPC is correct and can be used in
106            stacktrace_create_extern_stackframeinfo for
107            md_codegen_get_pv_from_pc. */
108
109         /*
110         fprintf(stderr, "EXT STACKFRAME: sfi=%x pv=%x, sp=%x, xpc=%x\n", &sfi, pv, sp+7*4, xpc);
111         */
112         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 7 * 4, xpc, xpc);
113
114         /* call the proper patcher function */
115         result = (patcher_function)(sp);
116
117
118         /* remove the stackframeinfo */
119         stacktrace_remove_stackframeinfo(&sfi);
120
121         /* check for return value and exit accordingly */
122         if (result == false) {
123                 e = exceptions_get_and_clear_exception();
124
125                 PATCHER_MONITOREXIT;
126
127                 return e;
128         }
129         PATCHER_MARK_PATCHED_MONITOREXIT;
130
131         return NULL;
132 }
133
134 /*      Helper
135  */
136 static void patcher_patch_back(u1 *sp)  
137 {
138         u1* xpc    = (u1 *)      *((ptrint *) (sp + 6 * 4));
139         u4 mcode  = *((u4*)      (sp + 3 * 4));
140         u4 xmcode = *((u4*)      (sp + 2 * 4));
141
142         *((u4*)(xpc))   = mcode;
143         *((u4*)(xpc+4)) = xmcode;
144         md_icacheflush(xpc, 8);
145 }
146
147 /* patcher_initialize_class ****************************************************
148
149    Initalizes a given classinfo pointer.  This function does not patch
150    any data.
151
152 *******************************************************************************/
153
154 bool patcher_initialize_class(u1 *sp)
155 {
156         classinfo *c;
157         u4                 xpc, mcode, xmcode;
158
159         /* get stuff from the stack */
160         c = (classinfo *) *((ptrint *) (sp + 1 * 4));
161
162         /* check if the class is initialized */
163         if (!(c->state & CLASS_INITIALIZED))
164                 if (!initialize_class(c))
165                         return false;
166
167         /* patch back original code */
168         patcher_patch_back(sp);
169
170         return true;
171 }
172
173 /* patcher_invokevirtual *******************************************************
174
175    Machine code:
176 0x4029bc46:   61ff 0000 00ba    bsrl 0x4029bd02
177 0x4029bc4c:   246f 0000         moveal %sp@(0),%a2
178 0x4029bc50:   266a 0000         moveal %a2@(0),%a3
179 0x4029bc54:   246b 0000         moveal %a3@(0),%a2      <-- patch this (0) offset
180 0x4029bc58:   4e92              jsr %a2@
181
182 *******************************************************************************/
183
184 bool patcher_invokevirtual(u1 *sp)
185 {
186         u1                *ra;
187         unresolved_method *um;
188         methodinfo        *m;
189         s2                 disp;
190
191         /* get stuff from the stack */
192         ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
193         um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
194
195         /* get the fieldinfo */
196         if (!(m = resolve_method_eager(um)))
197                 return false;
198
199         /* patch back original code */
200         patcher_patch_back(sp);
201
202         /* if we show NOPs, we have to skip them */
203         if (opt_shownops) ra += PATCHER_CALL_SIZE;
204
205         assert( *((u2*)(ra+8)) == 0x286b);
206
207         /* patch vftbl index */
208         disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
209         *((s2 *) (ra + 10)) = disp;
210
211         /* synchronize instruction cache */
212         md_icacheflush(ra + 10, 2);
213
214         return true;
215 }
216
217 /* patcher_invokestatic_special ************************************************
218
219    Machine code:
220
221    INVOKESPECIAL
222 0x402902bc:   61ff 0000 0076    bsrl 0x40290334
223 0x402902c2:   247c 0000 0000    moveal #0,%a2           <-- this #0
224 0x402902c8:   4e92              jsr %a2@
225
226 ******************************************************************************/
227
228 bool patcher_invokestatic_special(u1 *sp)
229 {
230         unresolved_method *um;
231         s4                 disp;
232         methodinfo        *m;
233
234         /* get stuff from the stack */
235         disp =                       *((s4 *)     (sp + 6 * 4));
236         um   = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
237
238         /* get the fieldinfo */
239         if (!(m = resolve_method_eager(um)))
240                 return false;
241
242         /* patch back original code */
243         patcher_patch_back(sp);
244
245         /* patch stubroutine */
246         if (opt_shownops) disp += PATCHER_CALL_SIZE;
247
248         *((ptrint *) (disp+2)) = (ptrint) m->stubroutine;
249
250         /* synchronize inst cache */
251
252         md_icacheflush(disp+2, SIZEOF_VOID_P);
253
254         return true;
255 }
256
257
258 /* patcher_resolve_class *******************************************************
259
260    Resolves a given unresolved_class pointer.  This function does not
261    patch any data.
262
263 *******************************************************************************/
264
265 #ifdef ENABLE_VERIFIER
266 bool patcher_resolve_class(u1 *sp)
267 {
268         unresolved_class *uc;
269         classinfo        *c;
270         s4                              disp;
271
272         /* get stuff from the stack */
273         uc = (unresolved_class *) *((ptrint *) (sp + 1 * 4));
274         disp =                    *((s4 *)     (sp + 6 * 4));
275
276         /* resolve the class */
277         if (!resolve_class(uc, resolveEager, false, &c))
278                 return false;
279
280         /* patch back original code */
281         patcher_patch_back(sp);
282
283         return true;
284 }
285 #endif /* ENABLE_VERIFIER */
286
287 /* patcher_resolve_classref_to_classinfo ***************************************
288   ACONST:
289         0x4028f2ca:   2479 0000 0000    moveal 0x00000000,%a2
290 *******************************************************************************/
291 bool patcher_resolve_classref_to_classinfo(u1 *sp)
292 {
293         constant_classref *cr;
294         s4                 disp;
295         u1                *pv;
296         classinfo         *c;
297
298         /* get stuff from the stack */
299         cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
300         disp =                       *((s4 *)     (sp + 6 * 4));
301
302         /* get the classinfo */
303         if (!(c = resolve_classref_eager(cr)))
304                 return false;
305
306         /* patch back original code */
307         patcher_patch_back(sp);
308
309         /* patch the classinfo pointer */
310         if (opt_shownops) disp += PATCHER_CALL_SIZE;
311         *((ptrint *) (disp+2)) = (ptrint) c;
312
313         /* synchronize inst cache */
314         md_icacheflush(disp+2, SIZEOF_VOID_P);
315
316         return true;
317 }
318
319 /* patcher_get_putstatic *******************************************************
320
321    Machine code:
322
323 *******************************************************************************/
324
325 bool patcher_get_putstatic(u1 *sp)
326 {
327         u1               *ra;
328         unresolved_field *uf;
329         s4                disp;
330         u1               *pv;
331         fieldinfo        *fi;
332
333         /* get stuff from the stack */
334         uf    = (unresolved_field *)  *((ptrint *) (sp + 1 * 4));
335         disp  =                       *((s4 *)     (sp + 6 * 4));
336
337         /* get the fieldinfo */
338         if (!(fi = resolve_field_eager(uf)))
339                 return false;
340
341         /* check if the field's class is initialized */
342         if (!(fi->class->state & CLASS_INITIALIZED))
343                 if (!initialize_class(fi->class))
344                         return false;
345
346         /* patch back original code */
347         patcher_patch_back(sp);
348
349         /* patch the field value's address */
350         if (opt_shownops) disp += PATCHER_CALL_SIZE;
351         assert(*((uint16_t*)(disp)) == 0x247c);
352         *((intptr_t *) (disp+2)) = (intptr_t) fi->value;
353
354         /* synchronize inst cache */
355         md_icacheflush(disp+2, SIZEOF_VOID_P);
356
357         return true;
358 }
359
360 /* patcher_get_putfield ********************************************************
361
362    Machine code:
363
364    <patched call position>
365
366 *******************************************************************************/
367
368 bool patcher_get_putfield(u1 *sp)
369 {
370         u1               *ra;
371         unresolved_field *uf;
372         fieldinfo        *fi;
373         s2                disp;
374
375         ra = (u1 *)               *((ptrint *) (sp + 6 * 4));
376         uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
377
378         /* get the fieldinfo */
379         if (!(fi = resolve_field_eager(uf)))
380                 return false;
381
382         /* patch back original code */
383         patcher_patch_back(sp);
384
385         /* if we show NOPs, we have to skip them */
386         if (opt_shownops) ra += PATCHER_CALL_SIZE;
387
388         /* patch the field's offset */
389         if (IS_LNG_TYPE(fi->type)) {
390                 /*
391                  *      0x40d05bb2:     0x25440000      movel %d4,%a2@(0)
392                  *      0x40d05bb6:     0x25430004      movel %d3,%a2@(4)
393                  *                                            ^^^^
394                  *                                            both 0000 and 0004 have to be patched
395                  */
396
397                 assert( (fi->offset & 0x0000ffff) == fi->offset );
398
399                 assert( (*((uint32_t*)ra) & 0xffff0000) == *((uint32_t*)ra) );
400                 assert( (*((uint32_t*)(ra+4)) & 0xffff0004) == *((uint32_t*)(ra+4)) );
401
402                 *((int16_t *) (ra + 2)) = (int16_t) ((fi->offset) & 0x0000ffff);
403                 *((int16_t *) (ra + 6)) = (int16_t) ((fi->offset + 4) & 0x0000ffff);
404
405                 md_icacheflush(ra, 2 * 4);
406         } else  {
407                 /*      Multiple cases here, int, adr, flt and dbl. */
408                 if ( (*((uint32_t*)ra) & 0xfff00000) == 0xf2200000 )    {
409                         /* flt/dbl case 
410                          * 0x40d3ddc2:     0xf22944c0 0x0000xxxx        fsmoves %a1@(0),%fp1
411                          *                                  ^^^^
412                          *                                  patch here 
413                          */
414                         assert( (fi->offset & 0x0000ffff) == fi->offset );
415                         assert( (*((uint32_t*)(ra+4)) & 0x0000ffff) == *((uint32_t*)(ra+4)) );
416                         *((int16_t*)(ra+4)) = (int16_t)fi->offset;
417
418                         md_icacheflush(ra+4, 1 * 4);
419                 } else  {
420                         /*      int/adr case
421                          *      0x40adb3f6:     0x254d0000      movel %a5,%a2@(0)
422                          *                            ^^^^                     ^
423                          *                            to be patched
424                          */
425                         assert( (*((uint32_t*)ra) & 0xffff0000) == *((uint32_t*)ra) );
426                         assert( (fi->offset & 0x0000ffff) == fi->offset );
427                         *((int16_t*)(ra+2)) = (int16_t)fi->offset;
428
429                         /* synchronize instruction cache */
430                         md_icacheflush(ra, 1 * 4);
431                 }
432         }
433
434         return true;
435 }
436 /* patcher_resolve_classref_to_flags *******************************************
437
438    CHECKCAST/INSTANCEOF:
439
440
441 CHECKCAST:
442 0x4029b056:   61ff 0000 013e    bsrl 0x4029b196
443 0x4029b05c:   263c 0000 0000    movel #0,%d3            <-- patch this #0
444 0x4029b062:   0283 0000 0200    andil #512,%d3
445
446 INSTANCEOF:
447 0x402a4aa8:   61ff 0000 05c4    bsrl 0x402a506e
448 0x402a4aae:   283c 0000 0000    movel #0,%d4            <-- same here
449 0x402a4ab4:   0284 0000 0200    andil #512,%d4
450
451
452 *******************************************************************************/
453
454 bool patcher_resolve_classref_to_flags(u1 *sp)
455 {
456         constant_classref *cr;
457         s4                 disp;
458         classinfo         *c;
459
460         /* get stuff from the stack */
461         cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
462         disp =                       *((s4 *)     (sp + 6 * 4));
463
464         /* get the fieldinfo */
465         if (!(c = resolve_classref_eager(cr)))
466                 return false;
467
468         /* patch back original code */
469         patcher_patch_back(sp);
470
471         /* patch class flags */
472         if (opt_shownops) disp += PATCHER_CALL_SIZE;
473         assert( (*((u2*)(disp)) == 0x263c) || (*((u2*)(disp)) == 0x283c) );
474         *((s4 *) (disp + 2)) = (s4) c->flags;
475
476         /* synchronize insn cache */
477         md_icacheflush(disp + 2, SIZEOF_VOID_P);
478
479         return true;
480 }
481
482 /* patcher_resolve_classref_to_vftbl *******************************************
483
484    CHECKCAST (class):
485 0x4029b094:   61ff 0000 00b4    bsrl 0x4029b14a
486 0x4029b09a:   287c 0000 0000    moveal #0,%a4           <-- patch this #0
487 0x4029b0a0:   2668 0000         moveal %a0@(0),%a3
488
489    INSTANCEOF (class):
490 0x402a9300:   61ff 0000 0574    bsrl 0x402a9876
491 0x402a9306:   267c 0000 0000    moveal #0,%a3
492 0x402a930c:   246a 0000         moveal %a2@(0),%a2
493
494
495 *******************************************************************************/
496
497 bool patcher_resolve_classref_to_vftbl(u1 *sp)
498 {
499         constant_classref *cr;
500         s4                 disp;
501         classinfo         *c;
502
503         /* get stuff from the stack */
504         cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
505         disp =                       *((s4 *)     (sp + 6 * 4));
506
507         /* get the fieldinfo */
508         if (!(c = resolve_classref_eager(cr)))
509                 return false;
510
511         /* patch back original code */
512         patcher_patch_back(sp);
513
514         /* patch super class' vftbl */
515         if (opt_shownops) disp += PATCHER_CALL_SIZE;
516         assert( (*((u2*)disp) == 0x287c) || (*((u2*)disp)== 0x267c) );
517
518         *((s4 *) (disp+2)) = (s4) c->vftbl;
519
520         /* synchronize insin cache */
521         md_icacheflush(disp+2, SIZEOF_VOID_P);
522
523         return true;
524 }
525
526 /* patcher_instanceof_interface ************************************************
527
528    Machine code:
529
530 0x402a92da:   61ff 0000 05c0    bsrl 0x402a989c
531 0x402a92e0:   246a 0000         moveal %a2@(0),%a2
532 0x402a92e4:   282a 0010         movel %a2@(16),%d4
533 0x402a92e8:   d8bc 0000 0000    addl #0,%d4             <-- this const
534 0x402a92ee:   4a84              tstl %d4
535 0x402a92f0:   6e0a              bles 0x402a92fc
536 0x402a92f2:   246a 0000         moveal %a2@(0),%a2      <-- this offset
537
538 *******************************************************************************/
539
540 bool patcher_instanceof_interface(u1 *sp)
541 {
542         u1                *ra;
543         constant_classref *cr;
544         classinfo         *c;
545         s4                 disp;
546
547         /* get stuff from the stack */
548
549         ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
550         cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
551
552         /* get the fieldinfo */
553         if (!(c = resolve_classref_eager(cr)))
554                 return false;
555
556         /* patch back original code */
557         patcher_patch_back(sp);
558
559         /* if we show NOPs, we have to skip them */
560         if (opt_shownops) ra += PATCHER_CALL_SIZE;
561                 
562         /* patch super class index */
563         disp = -(c->index);
564         assert( *((u2*)(ra + 8)) == 0xd8bc );
565         *((s4 *) (ra + 10 )) = disp;
566
567         disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
568
569         assert( (s2)disp  == disp);
570         assert ( *((s2*)(ra+18)) == 0x246a );
571
572         *((s2 *) (ra + 20)) = disp;
573
574         /* synchronize instruction cache */
575         md_icacheflush(ra + 10, 12);
576
577         return true;
578 }
579
580 /* patcher_checkcast_interface *************************************************
581
582 0x402a9400:   61ff 0000 03b6    bsrl 0x402a97b8
583 0x402a9406:   266a 0000         moveal %a2@(0),%a3
584 0x402a940a:   282b 0010         movel %a3@(16),%d4
585 0x402a940e:   d8bc 0000 0000    addl #0,%d4             <-- this 0
586 0x402a9414:   4a84              tstl %d4
587 0x402a9416:   6e02              bgts 0x402a941a
588               1234              tstb %d0
589 0x402a9418:   4afc              illegal
590 0x402a941a:   286b 0000         moveal %a3@(0),%a4      <-- and this 0 offset
591
592 *******************************************************************************/
593
594 bool patcher_checkcast_interface(u1 *sp)
595 {
596         u1                *ra;
597         constant_classref *cr;
598         classinfo         *c;
599         s4                 disp;
600
601         /* get stuff from the stack */
602         ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
603         cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
604
605         /* get the fieldinfo */
606         if (!(c = resolve_classref_eager(cr)))
607                 return false;
608
609         /* patch back original code */
610         patcher_patch_back(sp);
611
612         /* if we show NOPs, we have to skip them */
613         if (opt_shownops) ra += PATCHER_CALL_SIZE;
614
615         /* patch super class index */
616         disp = -(c->index);
617         assert ( *((u2 *)(ra + 8)) == 0xd8bc );
618         *((s4 *) (ra + 10)) = disp;
619
620         disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
621         assert( *((u2 *)(ra + 22)) == 0x286b );
622         assert( (s2)disp == disp);
623         *((s2 *) (ra + 24)) = disp;
624         
625         /* synchronize instruction cache */
626         md_icacheflush(ra + 10, 16);
627
628         return true;
629 }
630
631 /* patcher_resolve_native_function *********************************************
632
633    XXX
634
635 *******************************************************************************/
636
637 #if !defined(WITH_STATIC_CLASSPATH)
638 bool patcher_resolve_native_function(u1 *sp)
639 {
640         methodinfo  *m;
641         s4           disp;
642         functionptr  f;
643
644         /* get stuff from the stack */
645         m    = (methodinfo *) *((ptrint *) (sp + 1 * 4));
646         disp =                *((s4 *)     (sp + 6 * 4));
647
648         /* resolve native function */
649         if (!(f = native_resolve_function(m)))
650                 return false;
651
652         /* patch back original code */
653         patcher_patch_back(sp);
654
655         /* patch native function pointer */
656         if (opt_shownops) disp += PATCHER_CALL_SIZE;
657         *((ptrint *) (disp + 2)) = (ptrint) f;
658
659         /* synchronize data cache */
660         md_icacheflush(disp + 2, SIZEOF_VOID_P);
661
662         return true;
663 }
664 #endif /* !defined(WITH_STATIC_CLASSPATH) */
665
666
667 /* patcher_invokeinterface *****************************************************
668
669    Machine code:
670 0x40adb03e:     moveal %a2@(0),%a3              0x266a0000              <-- no patching
671 0x40adb042:     moveal %a3@(0),%a3              0x266b0000              <-- patch this 0000
672 0x40adb046:     moveal %a3@(0),%a4              0xxxxx0000              <-- patch this 0000
673 0x40adb04a:     jsr %a4@                                0xxxxx                  
674
675
676 *******************************************************************************/
677
678 bool patcher_invokeinterface(u1 *sp)
679 {
680         u1                *ra;
681         unresolved_method *um;
682         methodinfo        *m;
683         s4                 disp;
684
685         /* get stuff from the stack */
686         ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
687         um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
688
689
690         /* get the fieldinfo */
691         if (!(m = resolve_method_eager(um)))
692                 return false;
693
694         /* patch back original code */
695         patcher_patch_back(sp);
696
697         /* if we show NOPs, we have to skip them */
698         if (opt_shownops) ra += PATCHER_CALL_SIZE;
699         assert( *((uint32_t*)ra) == 0x246f0000 );
700
701         /* patch interfacetable index (first #0) */
702         disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index;
703         /* XXX this disp is negative, check! 
704          * assert( (disp & 0x0000ffff) == disp);*/
705         *((uint16_t *) (ra + 5 * 2)) = disp;
706
707         /* patch method offset (second #0) */
708         disp = sizeof(methodptr) * (m - m->class->methods);
709         assert( (disp & 0x0000ffff) == disp);
710         *((uint16_t *) (ra + 7 * 2)) = disp;
711
712         /* synchronize instruction cache */
713         md_icacheflush(ra + 5 * 2, 2 * 2);
714
715         return true;
716 }
717 /*
718  * These are local overrides for various environment variables in Emacs.
719  * Please do not remove this and leave it at the end of the file, where
720  * Emacs will automagically detect them.
721  * ---------------------------------------------------------------------
722  * Local variables:
723  * mode: c
724  * indent-tabs-mode: t
725  * c-basic-offset: 4
726  * tab-width: 4
727  * End:
728  * vim:noexpandtab:sw=4:ts=4:
729  */