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