Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / assembler / TestMain.cpp
1
2 // A short test program with which to experiment with the assembler.
3
4 //satisfies  CPU(X86_64)
5 //#define WTF_CPU_X86_64
6
7 // satisfies  ENABLE(ASSEMBLER)
8 #define ENABLE_ASSEMBLER 1
9
10 // satisfies  ENABLE(JIT)
11 #define ENABLE_JIT 1
12
13 #define USE_SYSTEM_MALLOC 1
14 // leads to FORCE_SYSTEM_MALLOC in wtf/FastMalloc.cpp
15
16 #include <jit/ExecutableAllocator.h>
17 #include <assembler/LinkBuffer.h>
18 #include <assembler/CodeLocation.h>
19 #include <assembler/RepatchBuffer.h>
20
21 #include <assembler/MacroAssembler.h>
22
23 #include <stdio.h>
24
25 /////////////////////////////////////////////////////////////////
26 // Temporary scaffolding for selecting the arch
27 #undef ARCH_x86
28 #undef ARCH_amd64
29 #undef ARCH_arm
30
31 #if defined(__APPLE__) && defined(__i386__)
32 #  define ARCH_x86 1
33 #elif defined(__APPLE__) && defined(__x86_64__)
34 #  define ARCH_amd64 1
35 #elif defined(__linux__) && defined(__i386__)
36 #  define ARCH_x86 1
37 #elif defined(__linux__) && defined(__x86_64__)
38 #  define ARCH_amd64 1
39 #elif defined(__linux__) && defined(__arm__)
40 #  define ARCH_arm 1
41 #elif defined(_MSC_VER) && defined(_M_IX86)
42 #  define ARCH_x86 1
43 #endif
44 /////////////////////////////////////////////////////////////////
45
46 // just somewhere convenient to put a breakpoint, before
47 // running gdb
48 #if WTF_COMPILER_GCC
49 __attribute__((noinline))
50 #endif
51 void pre_run ( void ) { }
52
53 /////////////////////////////////////////////////////////////////
54 //// test1 (simple straight line code) 
55 #if WTF_COMPILER_GCC
56
57 void test1 ( void )
58 {
59   printf("\n------------ Test 1 (straight line code) ------------\n\n" );
60
61   // Create new assembler
62   JSC::MacroAssembler* am = new JSC::MacroAssembler();
63
64 #if defined(ARCH_amd64)
65   JSC::X86Registers::RegisterID areg = JSC::X86Registers::r15;
66   // dump some instructions into it
67   //    xor    %r15,%r15
68   //    add    $0x7b,%r15
69   //    add    $0x141,%r15
70   //    retq
71   am->xorPtr(areg,areg);
72   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
73   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
74   am->ret();
75 #endif
76
77 #if defined(ARCH_x86)
78   JSC::X86Registers::RegisterID areg = JSC::X86Registers::edi;
79   // dump some instructions into it
80   //    xor    %edi,%edi
81   //    add    $0x7b,%edi
82   //    add    $0x141,%edi
83   //    ret
84   am->xorPtr(areg,areg);
85   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
86   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
87   am->ret();
88 #endif
89
90 #if defined(ARCH_arm)
91   JSC::ARMRegisters::RegisterID areg = JSC::ARMRegisters::r8;
92   //    eors    r8, r8, r8
93   //    adds    r8, r8, #123    ; 0x7b
94   //    mov     r3, #256        ; 0x100
95   //    orr     r3, r3, #65     ; 0x41
96   //    adds    r8, r8, r3
97   //    mov     pc, lr
98   am->xorPtr(areg,areg);
99   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
100   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
101   am->ret();
102 #endif
103
104   // prepare a link buffer, into which we can copy the completed insns
105   JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
106
107   // intermediate step .. get the pool suited for the size of code in 'am'
108   //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
109   JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
110
111   // constructor for LinkBuffer asks ep to allocate r-x memory,
112   // then copies it there.
113   JSC::LinkBuffer patchBuffer(am, ep);
114
115   // finalize
116   JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
117
118   // cr now holds a pointer to the final runnable code.
119   void* entry = cr.m_code.executableAddress();
120
121   printf("disas %p %p\n",
122          entry, (char*)entry + cr.m_size);
123   pre_run();
124
125   unsigned long result = 0x55555555;
126
127 #if defined(ARCH_amd64)
128   // call the generated piece of code.  It puts its result in r15.
129   __asm__ __volatile__(
130      "callq *%1"           "\n\t"
131      "movq  %%r15, %0"     "\n"
132      :/*out*/   "=r"(result)
133      :/*in*/    "r"(entry)
134      :/*trash*/ "r15","cc"
135   );
136 #endif
137 #if defined(ARCH_x86)
138   // call the generated piece of code.  It puts its result in edi.
139   __asm__ __volatile__(
140      "calll *%1"           "\n\t"
141      "movl  %%edi, %0"     "\n"
142      :/*out*/   "=r"(result)
143      :/*in*/    "r"(entry)
144      :/*trash*/ "edi","cc"
145   );
146 #endif
147 #if defined(ARCH_arm)
148   // call the generated piece of code.  It puts its result in r8.
149   __asm__ __volatile__(
150      "blx   %1"            "\n\t"
151      "mov   %0, %%r8"      "\n"
152      :/*out*/   "=r"(result)
153      :/*in*/    "r"(entry)
154      :/*trash*/ "r8","cc"
155   );
156 #endif
157
158   printf("\n");
159   printf("value computed is %lu (expected 444)\n", result);
160   printf("\n");
161
162   delete eal;
163   delete am;
164 }
165
166 #endif /* WTF_COMPILER_GCC */
167
168 /////////////////////////////////////////////////////////////////
169 //// test2 (a simple counting-down loop) 
170 #if WTF_COMPILER_GCC
171
172 void test2 ( void )
173 {
174   printf("\n------------ Test 2 (mini loop) ------------\n\n" );
175
176   // Create new assembler
177   JSC::MacroAssembler* am = new JSC::MacroAssembler();
178
179 #if defined(ARCH_amd64)
180   JSC::X86Registers::RegisterID areg = JSC::X86Registers::r15;
181   //    xor    %r15,%r15
182   //    add    $0x7b,%r15
183   //    add    $0x141,%r15
184   //    sub    $0x1,%r15
185   //    mov    $0x0,%r11
186   //    cmp    %r11,%r15
187   //    jne    0x7ff6d3e6a00e
188   //    retq
189   // so r15 always winds up being zero
190   am->xorPtr(areg,areg);
191   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
192   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
193
194   JSC::MacroAssembler::Label loopHeadLabel(am);
195   am->subPtr(JSC::MacroAssembler::Imm32(1), areg);
196
197   JSC::MacroAssembler::Jump j
198      = am->branchPtr(JSC::MacroAssembler::NotEqual,
199                      areg, JSC::MacroAssembler::ImmPtr(0));
200   j.linkTo(loopHeadLabel, am);
201
202   am->ret();
203 #endif
204
205 #if defined(ARCH_x86)
206   JSC::X86Registers::RegisterID areg = JSC::X86Registers::edi;
207   //    xor    %edi,%edi
208   //    add    $0x7b,%edi
209   //    add    $0x141,%edi
210   //    sub    $0x1,%edi
211   //    test   %edi,%edi
212   //    jne    0xf7f9700b
213   //    ret
214   // so edi always winds up being zero
215   am->xorPtr(areg,areg);
216   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
217   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
218
219   JSC::MacroAssembler::Label loopHeadLabel(am);
220   am->subPtr(JSC::MacroAssembler::Imm32(1), areg);
221
222   JSC::MacroAssembler::Jump j
223      = am->branchPtr(JSC::MacroAssembler::NotEqual,
224                      areg, JSC::MacroAssembler::ImmPtr(0));
225   j.linkTo(loopHeadLabel, am);
226
227   am->ret();
228 #endif
229
230 #if defined(ARCH_arm)
231   JSC::ARMRegisters::RegisterID areg = JSC::ARMRegisters::r8;
232   //    eors    r8, r8, r8
233   //    adds    r8, r8, #123    ; 0x7b
234   //    mov     r3, #256        ; 0x100
235   //    orr     r3, r3, #65     ; 0x41
236   //    adds    r8, r8, r3
237   //    subs    r8, r8, #1      ; 0x1
238   //    ldr     r3, [pc, #8]    ; 0x40026028
239   //    cmp     r8, r3
240   //    bne     0x40026014
241   //    mov     pc, lr
242   //    andeq   r0, r0, r0         // DATA (0)
243   //    andeq   r0, r0, r4, lsl r0 // DATA (?? what's this for?)
244   // so r8 always winds up being zero
245   am->xorPtr(areg,areg);
246   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
247   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
248
249   JSC::MacroAssembler::Label loopHeadLabel(am);
250   am->subPtr(JSC::MacroAssembler::Imm32(1), areg);
251
252   JSC::MacroAssembler::Jump j
253      = am->branchPtr(JSC::MacroAssembler::NotEqual,
254                      areg, JSC::MacroAssembler::ImmPtr(0));
255   j.linkTo(loopHeadLabel, am);
256
257   am->ret();
258 #endif
259
260   // prepare a link buffer, into which we can copy the completed insns
261   JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
262
263   // intermediate step .. get the pool suited for the size of code in 'am'
264   //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
265   JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
266
267   // constructor for LinkBuffer asks ep to allocate r-x memory,
268   // then copies it there.
269   JSC::LinkBuffer patchBuffer(am, ep);
270
271   // finalize
272   JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
273
274   // cr now holds a pointer to the final runnable code.
275   void* entry = cr.m_code.executableAddress();
276
277   printf("disas %p %p\n",
278          entry, (char*)entry + cr.m_size);
279   pre_run();
280
281   unsigned long result = 0x55555555;
282
283 #if defined(ARCH_amd64)
284   // call the generated piece of code.  It puts its result in r15.
285   __asm__ __volatile__(
286      "callq *%1"           "\n\t"
287      "movq  %%r15, %0"     "\n"
288      :/*out*/   "=r"(result)
289      :/*in*/    "r"(entry)
290      :/*trash*/ "r15","cc"
291   );
292 #endif
293 #if defined(ARCH_x86)
294   // call the generated piece of code.  It puts its result in edi.
295   __asm__ __volatile__(
296      "calll *%1"           "\n\t"
297      "movl  %%edi, %0"     "\n"
298      :/*out*/   "=r"(result)
299      :/*in*/    "r"(entry)
300      :/*trash*/ "edi","cc"
301   );
302 #endif
303 #if defined(ARCH_arm)
304   // call the generated piece of code.  It puts its result in r8.
305   __asm__ __volatile__(
306      "blx   %1"            "\n\t"
307      "mov   %0, %%r8"      "\n"
308      :/*out*/   "=r"(result)
309      :/*in*/    "r"(entry)
310      :/*trash*/ "r8","cc"
311   );
312 #endif
313
314   printf("\n");
315   printf("value computed is %lu (expected 0)\n", result);
316   printf("\n");
317
318   delete eal;
319   delete am;
320 }
321
322 #endif /* WTF_COMPILER_GCC */
323
324 /////////////////////////////////////////////////////////////////
325 //// test3 (if-then-else) 
326 #if WTF_COMPILER_GCC
327
328 void test3 ( void )
329 {
330   printf("\n------------ Test 3 (if-then-else) ------------\n\n" );
331
332   // Create new assembler
333   JSC::MacroAssembler* am = new JSC::MacroAssembler();
334
335 #if defined(ARCH_amd64)
336   JSC::X86Registers::RegisterID areg = JSC::X86Registers::r15;
337   //    mov    $0x64,%r15d
338   //    mov    $0x0,%r11
339   //    cmp    %r11,%r15
340   //    jne    0x7ff6d3e6a024
341   //    mov    $0x40,%r15d
342   //    jmpq   0x7ff6d3e6a02a
343   //    mov    $0x4,%r15d
344   //    retq
345   // so r15 ends up being 4
346
347   // put a value in reg
348   am->move(JSC::MacroAssembler::Imm32(100), areg);
349
350   // test, and conditionally jump to 'else' branch
351   JSC::MacroAssembler::Jump jToElse
352     = am->branchPtr(JSC::MacroAssembler::NotEqual,
353                     areg, JSC::MacroAssembler::ImmPtr(0));
354
355   // 'then' branch
356   am->move(JSC::MacroAssembler::Imm32(64), areg);
357   JSC::MacroAssembler::Jump jToAfter
358     = am->jump();
359
360   // 'else' branch
361   JSC::MacroAssembler::Label elseLbl(am);
362   am->move(JSC::MacroAssembler::Imm32(4), areg);
363
364   // after
365   JSC::MacroAssembler::Label afterLbl(am);
366
367   am->ret();
368 #endif
369
370 #if defined(ARCH_x86)
371   JSC::X86Registers::RegisterID areg = JSC::X86Registers::edi;
372   //    mov    $0x64,%edi
373   //    test   %edi,%edi
374   //    jne    0xf7f22017
375   //    mov    $0x40,%edi
376   //    jmp    0xf7f2201c
377   //    mov    $0x4,%edi
378   //    ret
379   // so edi ends up being 4
380
381   // put a value in reg
382   am->move(JSC::MacroAssembler::Imm32(100), areg);
383
384   // test, and conditionally jump to 'else' branch
385   JSC::MacroAssembler::Jump jToElse
386     = am->branchPtr(JSC::MacroAssembler::NotEqual,
387                     areg, JSC::MacroAssembler::ImmPtr(0));
388
389   // 'then' branch
390   am->move(JSC::MacroAssembler::Imm32(64), areg);
391   JSC::MacroAssembler::Jump jToAfter
392     = am->jump();
393
394   // 'else' branch
395   JSC::MacroAssembler::Label elseLbl(am);
396   am->move(JSC::MacroAssembler::Imm32(4), areg);
397
398   // after
399   JSC::MacroAssembler::Label afterLbl(am);
400
401   am->ret();
402 #endif
403
404 #if defined(ARCH_arm)
405   JSC::ARMRegisters::RegisterID areg = JSC::ARMRegisters::r8;
406   //    mov     r8, #100        ; 0x64
407   //    ldr     r3, [pc, #20]   ; 0x40026020
408   //    cmp     r8, r3
409   //    bne     0x40026018
410   //    mov     r8, #64 ; 0x40
411   //    b       0x4002601c
412   //    mov     r8, #4  ; 0x4
413   //    mov     pc, lr
414   //    andeq   r0, r0, r0           // DATA
415   //    andeq   r0, r0, r8, lsl r0   // DATA
416   //    andeq   r0, r0, r12, lsl r0  // DATA
417   //    ldr     r3, [r3, -r3]        // DATA
418   // so r8 ends up being 4
419
420   // put a value in reg
421   am->move(JSC::MacroAssembler::Imm32(100), areg);
422
423   // test, and conditionally jump to 'else' branch
424   JSC::MacroAssembler::Jump jToElse
425     = am->branchPtr(JSC::MacroAssembler::NotEqual,
426                     areg, JSC::MacroAssembler::ImmPtr(0));
427
428   // 'then' branch
429   am->move(JSC::MacroAssembler::Imm32(64), areg);
430   JSC::MacroAssembler::Jump jToAfter
431     = am->jump();
432
433   // 'else' branch
434   JSC::MacroAssembler::Label elseLbl(am);
435   am->move(JSC::MacroAssembler::Imm32(4), areg);
436
437   // after
438   JSC::MacroAssembler::Label afterLbl(am);
439
440   am->ret();
441 #endif
442
443   // set branch targets appropriately
444   jToElse.linkTo(elseLbl, am);
445   jToAfter.linkTo(afterLbl, am);
446
447   // prepare a link buffer, into which we can copy the completed insns
448   JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
449
450   // intermediate step .. get the pool suited for the size of code in 'am'
451   //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
452   JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
453
454   // constructor for LinkBuffer asks ep to allocate r-x memory,
455   // then copies it there.
456   JSC::LinkBuffer patchBuffer(am, ep);
457
458   // finalize
459   JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
460
461   // cr now holds a pointer to the final runnable code.
462   void* entry = cr.m_code.executableAddress();
463
464   printf("disas %p %p\n",
465          entry, (char*)entry + cr.m_size);
466   pre_run();
467
468   unsigned long result = 0x55555555;
469
470 #if defined(ARCH_amd64)
471   // call the generated piece of code.  It puts its result in r15.
472   __asm__ __volatile__(
473      "callq *%1"           "\n\t"
474      "movq  %%r15, %0"     "\n"
475      :/*out*/   "=r"(result)
476      :/*in*/    "r"(entry)
477      :/*trash*/ "r15","cc"
478   );
479 #endif
480 #if defined(ARCH_x86)
481   // call the generated piece of code.  It puts its result in edi.
482   __asm__ __volatile__(
483      "calll *%1"           "\n\t"
484      "movl  %%edi, %0"     "\n"
485      :/*out*/   "=r"(result)
486      :/*in*/    "r"(entry)
487      :/*trash*/ "edi","cc"
488   );
489 #endif
490 #if defined(ARCH_arm)
491   // call the generated piece of code.  It puts its result in r8.
492   __asm__ __volatile__(
493      "blx   %1"            "\n\t"
494      "mov   %0, %%r8"      "\n"
495      :/*out*/   "=r"(result)
496      :/*in*/    "r"(entry)
497      :/*trash*/ "r8","cc"
498   );
499 #endif
500
501   printf("\n");
502   printf("value computed is %lu (expected 4)\n", result);
503   printf("\n");
504
505   delete eal;
506   delete am;
507 }
508
509 #endif /* WTF_COMPILER_GCC */
510
511 /////////////////////////////////////////////////////////////////
512 //// test4 (callable function) 
513
514 void test4 ( void )
515 {
516   printf("\n------------ Test 4 (callable fn) ------------\n\n" );
517
518   // Create new assembler
519   JSC::MacroAssembler* am = new JSC::MacroAssembler();
520
521 #if defined(ARCH_amd64)
522   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
523   //    push   %rbp
524   //    mov    %rsp,%rbp
525   //    push   %rbx
526   //    push   %r12
527   //    push   %r13
528   //    push   %r14
529   //    push   %r15
530   //    xor    %rax,%rax
531   //    add    $0x7b,%rax
532   //    add    $0x141,%rax
533   //    pop    %r15
534   //    pop    %r14
535   //    pop    %r13
536   //    pop    %r12
537   //    pop    %rbx
538   //    mov    %rbp,%rsp
539   //    pop    %rbp
540   //    retq
541   // callable as a normal function, returns 444
542
543   JSC::X86Registers::RegisterID rreg = JSC::X86Registers::eax;
544   am->push(JSC::X86Registers::ebp);
545   am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
546   am->push(JSC::X86Registers::ebx);
547   am->push(JSC::X86Registers::r12);
548   am->push(JSC::X86Registers::r13);
549   am->push(JSC::X86Registers::r14);
550   am->push(JSC::X86Registers::r15);
551
552   am->xorPtr(rreg,rreg);
553   am->addPtr(JSC::MacroAssembler::Imm32(123), rreg);
554   am->addPtr(JSC::MacroAssembler::Imm32(321), rreg);
555
556   am->pop(JSC::X86Registers::r15);
557   am->pop(JSC::X86Registers::r14);
558   am->pop(JSC::X86Registers::r13);
559   am->pop(JSC::X86Registers::r12);
560   am->pop(JSC::X86Registers::ebx);
561   am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
562   am->pop(JSC::X86Registers::ebp);
563   am->ret();
564 #endif
565
566 #if defined(ARCH_x86)
567   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
568   //    push   %ebp
569   //    mov    %esp,%ebp
570   //    push   %ebx
571   //    push   %esi
572   //    push   %edi
573   //    xor    %eax,%eax
574   //    add    $0x7b,%eax
575   //    add    $0x141,%eax
576   //    pop    %edi
577   //    pop    %esi
578   //    pop    %ebx
579   //    mov    %ebp,%esp
580   //    pop    %ebp
581   //    ret
582   // callable as a normal function, returns 444
583
584   JSC::X86Registers::RegisterID rreg = JSC::X86Registers::eax;
585
586   am->push(JSC::X86Registers::ebp);
587   am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
588   am->push(JSC::X86Registers::ebx);
589   am->push(JSC::X86Registers::esi);
590   am->push(JSC::X86Registers::edi);
591
592   am->xorPtr(rreg,rreg);
593   am->addPtr(JSC::MacroAssembler::Imm32(123), rreg);
594   am->addPtr(JSC::MacroAssembler::Imm32(321), rreg);
595
596   am->pop(JSC::X86Registers::edi);
597   am->pop(JSC::X86Registers::esi);
598   am->pop(JSC::X86Registers::ebx);
599   am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
600   am->pop(JSC::X86Registers::ebp);
601   am->ret();
602 #endif
603
604 #if defined(ARCH_arm)
605   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
606   //    push    {r4}            ; (str r4, [sp, #-4]!)
607   //    push    {r5}            ; (str r5, [sp, #-4]!)
608   //    push    {r6}            ; (str r6, [sp, #-4]!)
609   //    push    {r7}            ; (str r7, [sp, #-4]!)
610   //    push    {r8}            ; (str r8, [sp, #-4]!)
611   //    push    {r9}            ; (str r9, [sp, #-4]!)
612   //    push    {r10}           ; (str r10, [sp, #-4]!)
613   //    push    {r11}           ; (str r11, [sp, #-4]!)
614   //    eors    r0, r0, r0
615   //    adds    r0, r0, #123    ; 0x7b
616   //    mov     r3, #256        ; 0x100
617   //    orr     r3, r3, #65     ; 0x41
618   //    adds    r0, r0, r3
619   //    pop     {r11}           ; (ldr r11, [sp], #4)
620   //    pop     {r10}           ; (ldr r10, [sp], #4)
621   //    pop     {r9}            ; (ldr r9, [sp], #4)
622   //    pop     {r8}            ; (ldr r8, [sp], #4)
623   //    pop     {r7}            ; (ldr r7, [sp], #4)
624   //    pop     {r6}            ; (ldr r6, [sp], #4)
625   //    pop     {r5}            ; (ldr r5, [sp], #4)
626   //    pop     {r4}            ; (ldr r4, [sp], #4)
627   //    mov     pc, lr
628   // callable as a normal function, returns 444
629
630   JSC::ARMRegisters::RegisterID rreg = JSC::ARMRegisters::r0;
631
632   am->push(JSC::ARMRegisters::r4);
633   am->push(JSC::ARMRegisters::r5);
634   am->push(JSC::ARMRegisters::r6);
635   am->push(JSC::ARMRegisters::r7);
636   am->push(JSC::ARMRegisters::r8);
637   am->push(JSC::ARMRegisters::r9);
638   am->push(JSC::ARMRegisters::r10);
639   am->push(JSC::ARMRegisters::r11);
640
641   am->xorPtr(rreg,rreg);
642   am->addPtr(JSC::MacroAssembler::Imm32(123), rreg);
643   am->addPtr(JSC::MacroAssembler::Imm32(321), rreg);
644
645   am->pop(JSC::ARMRegisters::r11);
646   am->pop(JSC::ARMRegisters::r10);
647   am->pop(JSC::ARMRegisters::r9);
648   am->pop(JSC::ARMRegisters::r8);
649   am->pop(JSC::ARMRegisters::r7);
650   am->pop(JSC::ARMRegisters::r6);
651   am->pop(JSC::ARMRegisters::r5);
652   am->pop(JSC::ARMRegisters::r4);
653
654   am->ret();
655 #endif
656
657   // prepare a link buffer, into which we can copy the completed insns
658   JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
659
660   // intermediate step .. get the pool suited for the size of code in 'am'
661   //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
662   JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
663
664   // constructor for LinkBuffer asks ep to allocate r-x memory,
665   // then copies it there.
666   JSC::LinkBuffer patchBuffer(am, ep);
667
668   // now fix up any branches/calls
669   //JSC::FunctionPtr target = JSC::FunctionPtr::FunctionPtr( &cube );
670
671   // finalize
672   JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
673
674   // cr now holds a pointer to the final runnable code.
675   void* entry = cr.m_code.executableAddress();
676
677   printf("disas %p %p\n",
678          entry, (char*)entry + cr.m_size);
679   pre_run();
680
681   // call the function
682   unsigned long (*fn)(void) = (unsigned long (*)())entry;
683   unsigned long result = fn();
684
685   printf("\n");
686   printf("value computed is %lu (expected 444)\n", result);
687   printf("\n");
688
689   delete eal;
690   delete am;
691 }
692
693
694 /////////////////////////////////////////////////////////////////
695 //// test5 (call in, out, repatch) 
696
697 // a function which we will call from the JIT generated code
698 unsigned long cube   ( unsigned long x ) { return x * x * x; }
699 unsigned long square ( unsigned long x ) { return x * x; }
700
701 void test5 ( void )
702 {
703   printf("\n--------- Test 5 (call in, out, repatch) ---------\n\n" );
704
705   // Create new assembler
706   JSC::MacroAssembler* am = new JSC::MacroAssembler();
707   JSC::MacroAssembler::Call cl;
708   ptrdiff_t offset_of_call_insn;
709
710 #if defined(ARCH_amd64)
711   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
712   // and then call a non-JIT-generated helper from within
713   // this code
714   //    push   %rbp
715   //    mov    %rsp,%rbp
716   //    push   %rbx
717   //    push   %r12
718   //    push   %r13
719   //    push   %r14
720   //    push   %r15
721   //    mov    $0x9,%edi
722   //    mov    $0x40187e,%r11
723   //    callq  *%r11
724   //    pop    %r15
725   //    pop    %r14
726   //    pop    %r13
727   //    pop    %r12
728   //    pop    %rbx
729   //    mov    %rbp,%rsp
730   //    pop    %rbp
731   //    retq
732   JSC::MacroAssembler::Label startOfFnLbl(am);
733   am->push(JSC::X86Registers::ebp);
734   am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
735   am->push(JSC::X86Registers::ebx);
736   am->push(JSC::X86Registers::r12);
737   am->push(JSC::X86Registers::r13);
738   am->push(JSC::X86Registers::r14);
739   am->push(JSC::X86Registers::r15);
740
741   // let's compute cube(9).  Move $9 to the first arg reg.
742   am->move(JSC::MacroAssembler::Imm32(9), JSC::X86Registers::edi);
743   cl = am->JSC::MacroAssembler::call();
744
745   // result is now in %rax.  Leave it ther and just return.
746
747   am->pop(JSC::X86Registers::r15);
748   am->pop(JSC::X86Registers::r14);
749   am->pop(JSC::X86Registers::r13);
750   am->pop(JSC::X86Registers::r12);
751   am->pop(JSC::X86Registers::ebx);
752   am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
753   am->pop(JSC::X86Registers::ebp);
754   am->ret();
755
756   offset_of_call_insn
757      = am->JSC::MacroAssembler::differenceBetween(startOfFnLbl, cl);
758   if (0) printf("XXXXXXXX offset = %lu\n", offset_of_call_insn);
759 #endif
760
761 #if defined(ARCH_x86)
762   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
763   // and then call a non-JIT-generated helper from within
764   // this code
765   //    push   %ebp
766   //    mov    %esp,%ebp
767   //    push   %ebx
768   //    push   %esi
769   //    push   %edi
770   //    push   $0x9
771   //    call   0x80490e9 <_Z4cubem>
772   //    add    $0x4,%esp
773   //    pop    %edi
774   //    pop    %esi
775   //    pop    %ebx
776   //    mov    %ebp,%esp
777   //    pop    %ebp
778   //    ret
779   JSC::MacroAssembler::Label startOfFnLbl(am);
780   am->push(JSC::X86Registers::ebp);
781   am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
782   am->push(JSC::X86Registers::ebx);
783   am->push(JSC::X86Registers::esi);
784   am->push(JSC::X86Registers::edi);
785
786   // let's compute cube(9).  Push $9 on the stack.
787   am->push(JSC::MacroAssembler::Imm32(9));
788   cl = am->JSC::MacroAssembler::call();
789   am->addPtr(JSC::MacroAssembler::Imm32(4), JSC::X86Registers::esp);
790   // result is now in %eax.  Leave it there and just return.
791
792   am->pop(JSC::X86Registers::edi);
793   am->pop(JSC::X86Registers::esi);
794   am->pop(JSC::X86Registers::ebx);
795   am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
796   am->pop(JSC::X86Registers::ebp);
797   am->ret();
798
799   offset_of_call_insn
800      = am->JSC::MacroAssembler::differenceBetween(startOfFnLbl, cl);
801   if (0) printf("XXXXXXXX offset = %lu\n",
802                 (unsigned long)offset_of_call_insn);
803 #endif
804
805 #if defined(ARCH_arm)
806   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
807   //    push    {r4}            ; (str r4, [sp, #-4]!)
808   //    push    {r5}            ; (str r5, [sp, #-4]!)
809   //    push    {r6}            ; (str r6, [sp, #-4]!)
810   //    push    {r7}            ; (str r7, [sp, #-4]!)
811   //    push    {r8}            ; (str r8, [sp, #-4]!)
812   //    push    {r9}            ; (str r9, [sp, #-4]!)
813   //    push    {r10}           ; (str r10, [sp, #-4]!)
814   //    push    {r11}           ; (str r11, [sp, #-4]!)
815   //    eors    r0, r0, r0
816   //    adds    r0, r0, #123    ; 0x7b
817   //    mov     r3, #256        ; 0x100
818   //    orr     r3, r3, #65     ; 0x41
819   //    adds    r0, r0, r3
820   //    pop     {r11}           ; (ldr r11, [sp], #4)
821   //    pop     {r10}           ; (ldr r10, [sp], #4)
822   //    pop     {r9}            ; (ldr r9, [sp], #4)
823   //    pop     {r8}            ; (ldr r8, [sp], #4)
824   //    pop     {r7}            ; (ldr r7, [sp], #4)
825   //    pop     {r6}            ; (ldr r6, [sp], #4)
826   //    pop     {r5}            ; (ldr r5, [sp], #4)
827   //    pop     {r4}            ; (ldr r4, [sp], #4)
828   //    mov     pc, lr
829   // callable as a normal function, returns 444
830   JSC::MacroAssembler::Label startOfFnLbl(am);
831   am->push(JSC::ARMRegisters::r4);
832   am->push(JSC::ARMRegisters::r5);
833   am->push(JSC::ARMRegisters::r6);
834   am->push(JSC::ARMRegisters::r7);
835   am->push(JSC::ARMRegisters::r8);
836   am->push(JSC::ARMRegisters::r9);
837   am->push(JSC::ARMRegisters::r10);
838   am->push(JSC::ARMRegisters::r11);
839   am->push(JSC::ARMRegisters::lr);
840
841   // let's compute cube(9).  Get $9 into r0.
842   am->move(JSC::MacroAssembler::Imm32(9), JSC::ARMRegisters::r0);
843   cl = am->JSC::MacroAssembler::call();
844   // result is now in r0.  Leave it there and just return.
845
846   am->pop(JSC::ARMRegisters::lr);
847   am->pop(JSC::ARMRegisters::r11);
848   am->pop(JSC::ARMRegisters::r10);
849   am->pop(JSC::ARMRegisters::r9);
850   am->pop(JSC::ARMRegisters::r8);
851   am->pop(JSC::ARMRegisters::r7);
852   am->pop(JSC::ARMRegisters::r6);
853   am->pop(JSC::ARMRegisters::r5);
854   am->pop(JSC::ARMRegisters::r4);
855   am->ret();
856
857   offset_of_call_insn
858      = am->JSC::MacroAssembler::differenceBetween(startOfFnLbl, cl);
859   if (0) printf("XXXXXXXX offset = %lu\n",
860                 (unsigned long)offset_of_call_insn);
861 #endif
862
863   // prepare a link buffer, into which we can copy the completed insns
864   JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
865
866   // intermediate step .. get the pool suited for the size of code in 'am'
867   //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
868   JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
869
870   // constructor for LinkBuffer asks ep to allocate r-x memory,
871   // then copies it there.
872   JSC::LinkBuffer patchBuffer(am, ep);
873
874   // now fix up any branches/calls
875   JSC::FunctionPtr target = JSC::FunctionPtr::FunctionPtr( &cube );
876   patchBuffer.link(cl, target);
877
878   JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
879
880   // cr now holds a pointer to the final runnable code.
881   void* entry = cr.m_code.executableAddress();
882
883   printf("disas %p %p\n",
884          entry, (char*)entry + cr.m_size);
885
886
887   pre_run();
888
889   printf("\n");
890
891   unsigned long (*fn)() = (unsigned long(*)())entry;
892   unsigned long result = fn();
893
894   printf("value computed is %lu (expected 729)\n", result);
895   printf("\n");
896
897   // now repatch the call in the JITted code to go elsewhere
898   JSC::JITCode jc = JSC::JITCode::JITCode(entry, cr.m_size);
899   JSC::CodeBlock cb = JSC::CodeBlock::CodeBlock(jc);
900
901   // the address of the call insn, that we want to prod
902   JSC::MacroAssemblerCodePtr cp
903      = JSC::MacroAssemblerCodePtr( ((char*)entry) + offset_of_call_insn );
904
905   JSC::RepatchBuffer repatchBuffer(&cb);
906   repatchBuffer.relink( JSC::CodeLocationCall(cp),
907                         JSC::FunctionPtr::FunctionPtr( &square ));
908  
909   result = fn();
910   printf("value computed is %lu (expected 81)\n", result);
911   printf("\n\n");
912
913   delete eal;
914   delete am;
915 }
916
917 /////////////////////////////////////////////////////////////////
918
919 int main ( void )
920 {
921 #if WTF_COMPILER_GCC
922   test1();
923   test2();
924   test3();
925 #endif
926   test4();
927   test5();
928   return 0;
929 }