testAssemblerCodeGen.cpp (5556B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 */ 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include "jit/Disassemble.h" 9 #include "jit/Linker.h" 10 #include "jit/MacroAssembler.h" 11 #include "js/GCAPI.h" 12 13 #include "jsapi-tests/tests.h" 14 #include "jsapi-tests/testsJit.h" 15 16 #include "jit/MacroAssembler-inl.h" 17 18 using namespace js; 19 using namespace js::jit; 20 21 #if defined(JS_JITSPEW) && defined(JS_CODEGEN_X64) 22 using DisasmCharVector = js::Vector<char, 64, SystemAllocPolicy>; 23 static MOZ_THREAD_LOCAL(DisasmCharVector*) disasmResult; 24 25 static void CaptureDisasmText(const char* text) { 26 // Skip the instruction offset (8 bytes) and two space characters, because the 27 // offsets make it harder to modify the test. 28 MOZ_RELEASE_ASSERT(strlen(text) > 10); 29 text = text + 10; 30 MOZ_RELEASE_ASSERT(disasmResult.get()->append(text, text + strlen(text))); 31 MOZ_RELEASE_ASSERT(disasmResult.get()->append('\n')); 32 } 33 34 BEGIN_TEST(testAssemblerCodeGen_x64_cmp8) { 35 TempAllocator tempAlloc(&cx->tempLifoAlloc()); 36 JitContext jcx(cx); 37 StackMacroAssembler masm(cx, tempAlloc); 38 AutoCreatedBy acb(masm, __func__); 39 40 masm.cmp8(Operand(rax), rbx); 41 masm.cmp8(Operand(rax), rdi); 42 masm.cmp8(Operand(rdi), rax); 43 masm.cmp8(Operand(rdi), rdi); 44 masm.cmp8(Operand(r10), r13); 45 46 masm.cmp8(Operand(Address(rax, 0)), rbx); 47 masm.cmp8(Operand(Address(rax, 1)), rdi); 48 masm.cmp8(Operand(Address(rdi, 0x10)), rax); 49 masm.cmp8(Operand(Address(rdi, 0x20)), rdi); 50 masm.cmp8(Operand(Address(r10, 0x30)), r11); 51 masm.cmp8(Operand(Address(rsp, 0x40)), rdi); 52 53 masm.cmp8(Operand(BaseIndex(rax, rbx, TimesFour, 0)), rcx); 54 masm.cmp8(Operand(BaseIndex(rax, rbx, TimesEight, 1)), rdi); 55 masm.cmp8(Operand(BaseIndex(rdi, rax, TimesOne, 2)), rdi); 56 masm.cmp8(Operand(BaseIndex(rax, rdi, TimesTwo, 3)), rdi); 57 masm.cmp8(Operand(BaseIndex(r10, r11, TimesFour, 4)), r12); 58 masm.cmp8(Operand(BaseIndex(rsp, rax, TimesEight, 5)), rdi); 59 60 void* ptr = (void*)0x1234; 61 masm.cmp8(Operand(AbsoluteAddress(ptr)), rax); 62 masm.cmp8(Operand(AbsoluteAddress(ptr)), rsi); 63 masm.cmp8(Operand(AbsoluteAddress(ptr)), r15); 64 65 // For Imm32(0) we emit a |test| instruction. 66 masm.cmp8(Operand(rax), Imm32(0)); 67 masm.cmp8(Operand(rbx), Imm32(0)); 68 masm.cmp8(Operand(rdi), Imm32(0)); 69 masm.cmp8(Operand(r8), Imm32(0)); 70 masm.cmp8(Operand(rax), Imm32(1)); 71 masm.cmp8(Operand(rbx), Imm32(-1)); 72 masm.cmp8(Operand(rdi), Imm32(2)); 73 masm.cmp8(Operand(r8), Imm32(-2)); 74 75 CHECK(!masm.oom()); 76 77 Linker linker(masm); 78 JitCode* code = linker.newCode(cx, CodeKind::Other); 79 CHECK(code); 80 81 DisasmCharVector disassembled; 82 disasmResult.set(&disassembled); 83 auto onFinish = mozilla::MakeScopeExit([&] { disasmResult.set(nullptr); }); 84 85 { 86 // jit::Disassemble can't GC. 87 JS::AutoSuppressGCAnalysis nogc; 88 jit::Disassemble(code->raw(), code->instructionsSize(), &CaptureDisasmText); 89 } 90 91 static const char* expected = 92 "3a c3 cmp %bl, %al\n" 93 "40 3a c7 cmp %dil, %al\n" 94 "40 3a f8 cmp %al, %dil\n" 95 "40 3a ff cmp %dil, %dil\n" 96 "45 3a d5 cmp %r13b, %r10b\n" 97 98 "38 18 cmpb %bl, (%rax)\n" 99 "40 38 78 01 cmpb %dil, 0x01(%rax)\n" 100 "38 47 10 cmpb %al, 0x10(%rdi)\n" 101 "40 38 7f 20 cmpb %dil, 0x20(%rdi)\n" 102 "45 38 5a 30 cmpb %r11b, 0x30(%r10)\n" 103 "40 38 7c 24 40 cmpb %dil, 0x40(%rsp)\n" 104 105 "38 0c 98 cmpb %cl, (%rax,%rbx,4)\n" 106 "40 38 7c d8 01 cmpb %dil, 0x01(%rax,%rbx,8)\n" 107 "40 38 7c 07 02 cmpb %dil, 0x02(%rdi,%rax,1)\n" 108 "40 38 7c 78 03 cmpb %dil, 0x03(%rax,%rdi,2)\n" 109 "47 38 64 9a 04 cmpb %r12b, 0x04(%r10,%r11,4)\n" 110 "40 38 7c c4 05 cmpb %dil, 0x05(%rsp,%rax,8)\n" 111 112 "38 04 25 34 12 00 00 cmpb %al, 0x0000000000001234\n" 113 "40 38 34 25 34 12 00 00 cmpb %sil, 0x0000000000001234\n" 114 "44 38 3c 25 34 12 00 00 cmpb %r15b, 0x0000000000001234\n" 115 116 "84 c0 test %al, %al\n" 117 "84 db test %bl, %bl\n" 118 "40 84 ff test %dil, %dil\n" 119 "45 84 c0 test %r8b, %r8b\n" 120 "3c 01 cmp $0x01, %al\n" 121 "80 fb ff cmp $-0x01, %bl\n" 122 "40 80 ff 02 cmp $0x02, %dil\n" 123 "41 80 f8 fe cmp $-0x02, %r8b\n" 124 125 "0f 0b ud2\n"; 126 127 bool matched = disassembled.length() == strlen(expected) && 128 memcmp(expected, disassembled.begin(), strlen(expected)) == 0; 129 if (!matched) { 130 CHECK(disassembled.append('\0')); 131 fprintf(stderr, "Generated:\n%s\n", disassembled.begin()); 132 fprintf(stderr, "Expected:\n%s\n", expected); 133 } 134 CHECK(matched); 135 136 return true; 137 } 138 END_TEST(testAssemblerCodeGen_x64_cmp8) 139 140 #endif // defined(JS_JITSPEW) && defined(JS_CODEGEN_X64)