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