// File: ctz[P]openssl-bench/bench.cc
// Function: test_handshake(unsigned int, Context&, Context&)
static void test_handshake(const unsigned n_threads, Context &server_ctx,
                           Context &client_ctx) {
  std::vector<std::thread> threads;
  std::vector<Timings> results(n_threads);
  const size_t handshakes = apply_work_multiplier(512);

  for (unsigned i = 0; i < n_threads; i++) {
    threads.push_back(std::thread(&test_handshake_one, std::ref(results[i]),
                                  handshakes, std::ref(server_ctx),
                                  std::ref(client_ctx)));
  }

  for (unsigned i = 0; i < n_threads; i++) {
    threads[i].join();
  }

  Conn client(client_ctx.open());
  Conn server(server_ctx.open());
  do_handshake(client, server);
  std::string prefix_server = "handshakes\tserver\t";
  std::string prefix_client = "handshakes\tclient\t";
  prefix_server += client.get_cipher_string();
  prefix_client += client.get_cipher_string();

  print_results(prefix_server.c_str(), prefix_client.c_str(), results,
                handshakes, "handshakes/s");
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1e0, %rsp            # imm = 0x1E0
movl %edi, -0x4(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x6250
movl -0x4(%rbp), %eax
movq %rax, -0x1b0(%rbp)
leaq -0x49(%rbp), %rdi
movq %rdi, -0x1a8(%rbp)
callq 0x6270
movq -0x1b0(%rbp), %rsi
movq -0x1a8(%rbp), %rdx
leaq -0x48(%rbp), %rdi
callq 0x6290
jmp 0x3fd2
leaq -0x49(%rbp), %rdi
callq 0x6300
movl $0x200, %edi            # imm = 0x200
callq 0x5340
movq %rax, -0x68(%rbp)
movl $0x0, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
cmpl -0x4(%rbp), %eax
jae 0x40d7
leaq 0x14fd(%rip), %rax      # 0x5500
movq %rax, -0x80(%rbp)
movl -0x6c(%rbp), %eax
movl %eax, %esi
leaq -0x48(%rbp), %rdi
callq 0x6380
movq %rax, %rdi
callq 0x6350
movq %rax, -0x88(%rbp)
movq -0x10(%rbp), %rdi
callq 0x63a0
movq %rax, -0x90(%rbp)
movq -0x18(%rbp), %rdi
callq 0x63a0
movq %rax, -0x98(%rbp)
leaq -0x78(%rbp), %rdi
leaq -0x80(%rbp), %rsi
leaq -0x88(%rbp), %rdx
leaq -0x68(%rbp), %rcx
leaq -0x90(%rbp), %r8
leaq -0x98(%rbp), %r9
callq 0xaf60
jmp 0x406c
leaq -0x30(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x6320
jmp 0x407b
leaq -0x78(%rbp), %rdi
callq 0x64b0
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x3ff0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x49(%rbp), %rdi
callq 0x6300
jmp 0x43db
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x43d2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x78(%rbp), %rdi
callq 0x64b0
jmp 0x43d2
movl $0x0, -0x9c(%rbp)
movl -0x9c(%rbp), %eax
cmpl -0x4(%rbp), %eax
jae 0x411a
movl -0x9c(%rbp), %eax
movl %eax, %esi
leaq -0x30(%rbp), %rdi
callq 0x64e0
movq %rax, %rdi
callq 0x3580
jmp 0x4107
jmp 0x4109
movl -0x9c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x9c(%rbp)
jmp 0x40e1
movq -0x18(%rbp), %rdi
callq 0x6500
movq %rax, -0x1b8(%rbp)
jmp 0x412c
movq -0x1b8(%rbp), %rsi
leaq -0xd8(%rbp), %rdi
callq 0x6520
jmp 0x4141
movq -0x10(%rbp), %rdi
callq 0x6500
movq %rax, -0x1c0(%rbp)
jmp 0x4153
movq -0x1c0(%rbp), %rsi
leaq -0x110(%rbp), %rdi
callq 0x6520
jmp 0x4168
leaq -0xd8(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0x5050
jmp 0x417d
leaq -0x131(%rbp), %rdi
movq %rdi, -0x1c8(%rbp)
callq 0x35a0
movq -0x1c8(%rbp), %rdx
leaq 0xa2e7(%rip), %rsi      # 0xe485
leaq -0x130(%rbp), %rdi
callq 0x65e0
jmp 0x41ac
leaq -0x131(%rbp), %rdi
callq 0x3380
leaq -0x159(%rbp), %rdi
movq %rdi, -0x1d0(%rbp)
callq 0x35a0
movq -0x1d0(%rbp), %rdx
leaq 0xa2bf(%rip), %rsi      # 0xe498
leaq -0x158(%rbp), %rdi
callq 0x65e0
jmp 0x41e7
leaq -0x159(%rbp), %rdi
callq 0x3380
leaq -0x180(%rbp), %rdi
leaq -0xd8(%rbp), %rsi
callq 0x6690
jmp 0x4208
leaq -0x130(%rbp), %rdi
leaq -0x180(%rbp), %rsi
callq 0x3440
jmp 0x421d
leaq -0x180(%rbp), %rdi
callq 0x31f0
leaq -0x1a0(%rbp), %rdi
leaq -0xd8(%rbp), %rsi
callq 0x6690
jmp 0x423e
leaq -0x158(%rbp), %rdi
leaq -0x1a0(%rbp), %rsi
callq 0x3440
jmp 0x4253
leaq -0x1a0(%rbp), %rdi
callq 0x31f0
leaq -0x130(%rbp), %rdi
callq 0x3160
movq %rax, -0x1d8(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x3160
movq -0x1d8(%rbp), %rdi
movq %rax, %rsi
movaps 0x9d81(%rip), %xmm1     # 0xe010
movq -0x68(%rbp), %xmm0
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x9d80(%rip), %xmm1     # 0xe020
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
leaq 0xa1f5(%rip), %rcx      # 0xe4ab
leaq -0x48(%rbp), %rdx
callq 0x5090
jmp 0x42c1
leaq -0x158(%rbp), %rdi
callq 0x31f0
leaq -0x130(%rbp), %rdi
callq 0x31f0
leaq -0x110(%rbp), %rdi
callq 0x6770
leaq -0xd8(%rbp), %rdi
callq 0x6770
leaq -0x48(%rbp), %rdi
callq 0x67c0
leaq -0x30(%rbp), %rdi
callq 0x6820
addq $0x1e0, %rsp            # imm = 0x1E0
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x43c6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x43ba
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x131(%rbp), %rdi
callq 0x3380
jmp 0x43ba
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x159(%rbp), %rdi
callq 0x3380
jmp 0x43ae
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x43a2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x180(%rbp), %rdi
callq 0x31f0
jmp 0x43a2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x31f0
leaq -0x158(%rbp), %rdi
callq 0x31f0
leaq -0x130(%rbp), %rdi
callq 0x31f0
leaq -0x110(%rbp), %rdi
callq 0x6770
leaq -0xd8(%rbp), %rdi
callq 0x6770
leaq -0x48(%rbp), %rdi
callq 0x67c0
leaq -0x30(%rbp), %rdi
callq 0x6820
movq -0x58(%rbp), %rdi
callq 0x3590
nopl (%rax)