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