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