// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use crate::tests::common::run_test;
use iced_x86::code_asm::*;
use x86defs::RFlags;
use x86emu::Cpu;
use x86emu::Gp;

const ROTATE_MASK: RFlags = RFlags::new().with_carry(true);

fn rotate_memory_by_regvalue(
    variations: &[(u64, u64, bool, u64, u64)],
    shift_op: impl Fn(&mut CodeAssembler, AsmMemoryOperand, AsmRegister8) -> Result<(), IcedError>,
    ptr_op: impl Fn(AsmMemoryOperand) -> AsmMemoryOperand,
    operand_bit_size: u32,
    with_carry: bool,
) {
    for &(left, right, initial_carry, result, rflags) in variations {
        let count_mask = if operand_bit_size == 64 { 0x3f } else { 0x1f };

        let masked_count = (right & count_mask) as u32;
        let mut count = masked_count;
        if with_carry {
            if operand_bit_size == 8 {
                count %= 9;
            } else if operand_bit_size == 16 {
                count %= 17;
            }
        } else {
            count %= operand_bit_size;
        }

        let flags = if masked_count == 1 {
            let mut mask = ROTATE_MASK;
            mask.set_overflow(true);
            mask
        } else if count == 0 {
            if !with_carry & (masked_count != 0) {
                ROTATE_MASK
            } else {
                RFlags::new()
            }
        } else {
            ROTATE_MASK
        };

        let mut cpu = run_test(
            flags,
            |asm| shift_op(asm, ptr_op(rcx + 0x10), cl),
            |cpu| {
                let mut rflags = cpu.rflags();
                rflags.set_carry(initial_carry);
                cpu.set_rflags(rflags);
                cpu.set_gp(Gp::RCX.into(), right);
                cpu.valid_gva = cpu.gp(Gp::RCX.into()).wrapping_add(0x10);
                cpu.mem_val = left;
            },
        );

        assert_eq!(cpu.mem_val, result);
        assert_eq!(cpu.rflags() & flags, rflags.into());
    }
}

#[test]
fn rcl_byte_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0x43, 0x0),
        (0x64, 0x64, true, 0x4b, 0x0),
        (0x64, 0x1, false, 0xc8, 0x800),
        (0x64, 0x1, true, 0xc9, 0x800),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x1, 0x0),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0xfffffffffffffffe, 0x1),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xffffffffffffffdf, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xfffffffffffffff7, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0xfe, 0x800),
        (0x7f, 0x1, true, 0xff, 0x800),
        (0x7f, 0x2, false, 0xfc, 0x1),
        (0x7f, 0x2, true, 0xfe, 0x1),
        (0xaaaaaaaa, 0x3, false, 0xaaaaaa52, 0x1),
        (0xaaaaaaaa, 0x3, true, 0xaaaaaa56, 0x1),
        (0x55555555, 0x3, false, 0x555555a9, 0x0),
        (0x55555555, 0x3, true, 0x555555ad, 0x0),
        (0x80000000, 0x7f, false, 0x80000000, 0x0),
        (0x80000000, 0x7f, true, 0x80000008, 0x0),
        (0x80000000, 0xf, false, 0x80000000, 0x0),
        (0x80000000, 0xf, true, 0x80000020, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0x7f, true, 0x8000000000000008, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0x7ffffffffffffff7, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0x7fffffffffffffff, 0x1),
        (0x8000000000000000, 0xff, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0xff, true, 0x8000000000000008, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::rcl, byte_ptr, 8, true);
}

#[test]
fn rcl_word_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0x640, 0x0),
        (0x64, 0x64, true, 0x648, 0x0),
        (0x64, 0x1, false, 0xc8, 0x0),
        (0x64, 0x1, true, 0xc9, 0x0),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x1, 0x0),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0xfffffffffffffffe, 0x1),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xffffffffffffbfff, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xffffffffffffdfff, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0xfe, 0x0),
        (0x7f, 0x1, true, 0xff, 0x0),
        (0x7f, 0x2, false, 0x1fc, 0x0),
        (0x7f, 0x2, true, 0x1fe, 0x0),
        (0xaaaaaaaa, 0x3, false, 0xaaaa5552, 0x1),
        (0xaaaaaaaa, 0x3, true, 0xaaaa5556, 0x1),
        (0x55555555, 0x3, false, 0x5555aaa9, 0x0),
        (0x55555555, 0x3, true, 0x5555aaad, 0x0),
        (0x80000000, 0x7f, false, 0x80000000, 0x0),
        (0x80000000, 0x7f, true, 0x80002000, 0x0),
        (0x80000000, 0xf, false, 0x80000000, 0x0),
        (0x80000000, 0xf, true, 0x80004000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0x7f, true, 0x8000000000002000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0x7fffffffffffdfff, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0x7fffffffffffffff, 0x1),
        (0x8000000000000000, 0xff, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0xff, true, 0x8000000000002000, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::rcl, word_ptr, 16, true);
}

#[test]
fn rcl_qword_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0x64000000000, 0x0),
        (0x64, 0x64, true, 0x64800000000, 0x0),
        (0x64, 0x1, false, 0xc8, 0x0),
        (0x64, 0x1, true, 0xc9, 0x0),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x1, 0x0),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0xfffffffffffffffe, 0x1),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xffffffffffffbfff, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xbfffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0xfe, 0x0),
        (0x7f, 0x1, true, 0xff, 0x0),
        (0x7f, 0x2, false, 0x1fc, 0x0),
        (0x7f, 0x2, true, 0x1fe, 0x0),
        (0xaaaaaaaa, 0x3, false, 0x555555550, 0x0),
        (0xaaaaaaaa, 0x3, true, 0x555555554, 0x0),
        (0x55555555, 0x3, false, 0x2aaaaaaa8, 0x0),
        (0x55555555, 0x3, true, 0x2aaaaaaac, 0x0),
        (0x80000000, 0x7f, false, 0x20000000, 0x0),
        (0x80000000, 0x7f, true, 0x4000000020000000, 0x0),
        (0x80000000, 0xf, false, 0x400000000000, 0x0),
        (0x80000000, 0xf, true, 0x400000004000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x2000000000000000, 0x0),
        (0x8000000000000000, 0x7f, true, 0x6000000000000000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0x9fffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0xdfffffffffffffff, 0x1),
        (0x8000000000000000, 0xff, false, 0x2000000000000000, 0x0),
        (0x8000000000000000, 0xff, true, 0x6000000000000000, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::rcl, qword_ptr, 64, true);
}

#[test]
fn rcr_byte_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0x86, 0x0),
        (0x64, 0x64, true, 0x96, 0x0),
        (0x64, 0x1, false, 0x32, 0x0),
        (0x64, 0x1, true, 0xb2, 0x800),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x80, 0x800),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0xffffffffffffff7f, 0x801),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xfffffffffffffffb, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xffffffffffffffef, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0x3f, 0x1),
        (0x7f, 0x1, true, 0xbf, 0x801),
        (0x7f, 0x2, false, 0x9f, 0x1),
        (0x7f, 0x2, true, 0xdf, 0x1),
        (0xaaaaaaaa, 0x3, false, 0xaaaaaa95, 0x0),
        (0xaaaaaaaa, 0x3, true, 0xaaaaaab5, 0x0),
        (0x55555555, 0x3, false, 0x5555554a, 0x1),
        (0x55555555, 0x3, true, 0x5555556a, 0x1),
        (0x80000000, 0x7f, false, 0x80000000, 0x0),
        (0x80000000, 0x7f, true, 0x80000010, 0x0),
        (0x80000000, 0xf, false, 0x80000000, 0x0),
        (0x80000000, 0xf, true, 0x80000004, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0x7f, true, 0x8000000000000010, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0x7fffffffffffffef, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0x7fffffffffffffff, 0x1),
        (0x8000000000000000, 0xff, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0xff, true, 0x8000000000000010, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::rcr, byte_ptr, 8, true);
}

#[test]
fn rcr_word_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0x8006, 0x0),
        (0x64, 0x64, true, 0x9006, 0x0),
        (0x64, 0x1, false, 0x32, 0x0),
        (0x64, 0x1, true, 0x8032, 0x800),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x8000, 0x800),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0xffffffffffff7fff, 0x801),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xfffffffffffffffd, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xfffffffffffffffb, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0x3f, 0x1),
        (0x7f, 0x1, true, 0x803f, 0x801),
        (0x7f, 0x2, false, 0x801f, 0x1),
        (0x7f, 0x2, true, 0xc01f, 0x1),
        (0xaaaaaaaa, 0x3, false, 0xaaaa9555, 0x0),
        (0xaaaaaaaa, 0x3, true, 0xaaaab555, 0x0),
        (0x55555555, 0x3, false, 0x55554aaa, 0x1),
        (0x55555555, 0x3, true, 0x55556aaa, 0x1),
        (0x80000000, 0x7f, false, 0x80000000, 0x0),
        (0x80000000, 0x7f, true, 0x80000004, 0x0),
        (0x80000000, 0xf, false, 0x80000000, 0x0),
        (0x80000000, 0xf, true, 0x80000002, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0x7f, true, 0x8000000000000004, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0x7ffffffffffffffb, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0x7fffffffffffffff, 0x1),
        (0x8000000000000000, 0xff, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0xff, true, 0x8000000000000004, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::rcr, word_ptr, 16, true);
}

#[test]
fn rcr_qword_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0xc80000000, 0x0),
        (0x64, 0x64, true, 0xc90000000, 0x0),
        (0x64, 0x1, false, 0x32, 0x0),
        (0x64, 0x1, true, 0x8000000000000032, 0x800),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x8000000000000000, 0x800),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0x7fffffffffffffff, 0x801),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xfffdffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xfffffffffffffffd, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0x3f, 0x1),
        (0x7f, 0x1, true, 0x800000000000003f, 0x801),
        (0x7f, 0x2, false, 0x800000000000001f, 0x1),
        (0x7f, 0x2, true, 0xc00000000000001f, 0x1),
        (0xaaaaaaaa, 0x3, false, 0x8000000015555555, 0x0),
        (0xaaaaaaaa, 0x3, true, 0xa000000015555555, 0x0),
        (0x55555555, 0x3, false, 0x400000000aaaaaaa, 0x1),
        (0x55555555, 0x3, true, 0x600000000aaaaaaa, 0x1),
        (0x80000000, 0x7f, false, 0x200000000, 0x0),
        (0x80000000, 0x7f, true, 0x200000002, 0x0),
        (0x80000000, 0xf, false, 0x10000, 0x0),
        (0x80000000, 0xf, true, 0x2000000010000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x1, 0x0),
        (0x8000000000000000, 0x7f, true, 0x3, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0xfffffffffffffffc, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0xfffffffffffffffe, 0x1),
        (0x8000000000000000, 0xff, false, 0x1, 0x0),
        (0x8000000000000000, 0xff, true, 0x3, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::rcr, qword_ptr, 64, true);
}

#[test]
fn rol_byte_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0x46, 0x0),
        (0x64, 0x64, true, 0x46, 0x0),
        (0x64, 0x1, false, 0xc8, 0x800),
        (0x64, 0x1, true, 0xc8, 0x800),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x0, 0x0),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0xfe, 0x800),
        (0x7f, 0x1, true, 0xfe, 0x800),
        (0x7f, 0x2, false, 0xfd, 0x1),
        (0x7f, 0x2, true, 0xfd, 0x1),
        (0xaaaaaaaa, 0x3, false, 0xaaaaaa55, 0x1),
        (0xaaaaaaaa, 0x3, true, 0xaaaaaa55, 0x1),
        (0xaaaaaaaa, 0x8, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x8, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x10, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x10, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x20, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x20, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x40, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x40, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0xa0, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0xa0, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x9, false, 0xaaaaaa55, 0x1),
        (0xaaaaaaaa, 0x9, true, 0xaaaaaa55, 0x1),
        (0xaaaaaaaa, 0x11, false, 0xaaaaaa55, 0x1),
        (0xaaaaaaaa, 0x11, true, 0xaaaaaa55, 0x1),
        (0xaaaaaaaa, 0x21, false, 0xaaaaaa55, 0x801),
        (0xaaaaaaaa, 0x21, true, 0xaaaaaa55, 0x801),
        (0x55555555, 0x3, false, 0x555555aa, 0x0),
        (0x55555555, 0x3, true, 0x555555aa, 0x0),
        (0x55555555, 0x10, false, 0x55555555, 0x1),
        (0x55555555, 0x10, true, 0x55555555, 0x1),
        (0x55555555, 0x20, false, 0x55555555, 0x0),
        (0x55555555, 0x20, true, 0x55555555, 0x0),
        (0x55555555, 0x40, false, 0x55555555, 0x0),
        (0x55555555, 0x40, true, 0x55555555, 0x0),
        (0x55555555, 0xa0, false, 0x55555555, 0x0),
        (0x55555555, 0xa0, true, 0x55555555, 0x0),
        (0x55555555, 0x9, false, 0x555555aa, 0x0),
        (0x55555555, 0x9, true, 0x555555aa, 0x0),
        (0x55555555, 0x11, false, 0x555555aa, 0x0),
        (0x55555555, 0x11, true, 0x555555aa, 0x0),
        (0x55555555, 0x21, false, 0x555555aa, 0x800),
        (0x55555555, 0x21, true, 0x555555aa, 0x800),
        (0x12345678, 0x3, false, 0x123456c3, 0x1),
        (0x12345678, 0x3, true, 0x123456c3, 0x1),
        (0x12345678, 0x4, false, 0x12345687, 0x1),
        (0x12345678, 0x4, true, 0x12345687, 0x1),
        (0x80000000, 0x7f, false, 0x80000000, 0x0),
        (0x80000000, 0x7f, true, 0x80000000, 0x0),
        (0x80000000, 0xf, false, 0x80000000, 0x0),
        (0x80000000, 0xf, true, 0x80000000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0x7f, true, 0x8000000000000000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0x7fffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0x7fffffffffffffff, 0x1),
        (0x8000000000000000, 0xff, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0xff, true, 0x8000000000000000, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::rol, byte_ptr, 8, false);
}

// weird comment in legacy emulator about carry flag, investigate
#[test]
fn rol_word_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0x640, 0x0),
        (0x64, 0x64, true, 0x640, 0x0),
        (0x64, 0x1, false, 0xc8, 0x0),
        (0x64, 0x1, true, 0xc8, 0x0),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x0, 0x0),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0xfe, 0x0),
        (0x7f, 0x1, true, 0xfe, 0x0),
        (0x7f, 0x2, false, 0x1fc, 0x0),
        (0x7f, 0x2, true, 0x1fc, 0x0),
        (0xaaaaaaaa, 0x3, false, 0xaaaa5555, 0x1),
        (0xaaaaaaaa, 0x3, true, 0xaaaa5555, 0x1),
        (0xaaaaaaaa, 0x8, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x8, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x10, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x10, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x20, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x20, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x40, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x40, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0xa0, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0xa0, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x9, false, 0xaaaa5555, 0x1),
        (0xaaaaaaaa, 0x9, true, 0xaaaa5555, 0x1),
        (0xaaaaaaaa, 0x11, false, 0xaaaa5555, 0x1),
        (0xaaaaaaaa, 0x11, true, 0xaaaa5555, 0x1),
        (0xaaaaaaaa, 0x21, false, 0xaaaa5555, 0x801),
        (0xaaaaaaaa, 0x21, true, 0xaaaa5555, 0x801),
        (0x55555555, 0x3, false, 0x5555aaaa, 0x0),
        (0x55555555, 0x3, true, 0x5555aaaa, 0x0),
        (0x55555555, 0x10, false, 0x55555555, 0x1),
        (0x55555555, 0x10, true, 0x55555555, 0x1),
        (0x55555555, 0x20, false, 0x55555555, 0x0),
        (0x55555555, 0x20, true, 0x55555555, 0x0),
        (0x55555555, 0x40, false, 0x55555555, 0x0),
        (0x55555555, 0x40, true, 0x55555555, 0x0),
        (0x55555555, 0xa0, false, 0x55555555, 0x0),
        (0x55555555, 0xa0, true, 0x55555555, 0x0),
        (0x55555555, 0x9, false, 0x5555aaaa, 0x0),
        (0x55555555, 0x9, true, 0x5555aaaa, 0x0),
        (0x55555555, 0x11, false, 0x5555aaaa, 0x0),
        (0x55555555, 0x11, true, 0x5555aaaa, 0x0),
        (0x55555555, 0x21, false, 0x5555aaaa, 0x800),
        (0x55555555, 0x21, true, 0x5555aaaa, 0x800),
        (0x12345678, 0x3, false, 0x1234b3c2, 0x0),
        (0x12345678, 0x3, true, 0x1234b3c2, 0x0),
        (0x12345678, 0x4, false, 0x12346785, 0x1),
        (0x12345678, 0x4, true, 0x12346785, 0x1),
        (0x80000000, 0x7f, false, 0x80000000, 0x0),
        (0x80000000, 0x7f, true, 0x80000000, 0x0),
        (0x80000000, 0xf, false, 0x80000000, 0x0),
        (0x80000000, 0xf, true, 0x80000000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0x7f, true, 0x8000000000000000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0x7fffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0x7fffffffffffffff, 0x1),
        (0x8000000000000000, 0xff, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0xff, true, 0x8000000000000000, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::rol, word_ptr, 16, false);
}

#[test]
fn rol_qword_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0x64000000000, 0x0),
        (0x64, 0x64, true, 0x64000000000, 0x0),
        (0x64, 0x1, false, 0xc8, 0x0),
        (0x64, 0x1, true, 0xc8, 0x0),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x0, 0x0),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0xfe, 0x0),
        (0x7f, 0x1, true, 0xfe, 0x0),
        (0x7f, 0x2, false, 0x1fc, 0x0),
        (0x7f, 0x2, true, 0x1fc, 0x0),
        (0xaaaaaaaa, 0x3, false, 0x555555550, 0x0),
        (0xaaaaaaaa, 0x3, true, 0x555555550, 0x0),
        (0xaaaaaaaa, 0x8, false, 0xaaaaaaaa00, 0x0),
        (0xaaaaaaaa, 0x8, true, 0xaaaaaaaa00, 0x0),
        (0xaaaaaaaa, 0x10, false, 0xaaaaaaaa0000, 0x0),
        (0xaaaaaaaa, 0x10, true, 0xaaaaaaaa0000, 0x0),
        (0xaaaaaaaa, 0x20, false, 0xaaaaaaaa00000000, 0x0),
        (0xaaaaaaaa, 0x20, true, 0xaaaaaaaa00000000, 0x0),
        (0xaaaaaaaa, 0x40, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x40, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0xa0, false, 0xaaaaaaaa00000000, 0x0),
        (0xaaaaaaaa, 0xa0, true, 0xaaaaaaaa00000000, 0x0),
        (0xaaaaaaaa, 0x9, false, 0x15555555400, 0x0),
        (0xaaaaaaaa, 0x9, true, 0x15555555400, 0x0),
        (0xaaaaaaaa, 0x11, false, 0x1555555540000, 0x0),
        (0xaaaaaaaa, 0x11, true, 0x1555555540000, 0x0),
        (0xaaaaaaaa, 0x21, false, 0x5555555400000001, 0x1),
        (0xaaaaaaaa, 0x21, true, 0x5555555400000001, 0x1),
        (0x55555555, 0x3, false, 0x2aaaaaaa8, 0x0),
        (0x55555555, 0x3, true, 0x2aaaaaaa8, 0x0),
        (0x55555555, 0x10, false, 0x555555550000, 0x0),
        (0x55555555, 0x10, true, 0x555555550000, 0x0),
        (0x55555555, 0x20, false, 0x5555555500000000, 0x0),
        (0x55555555, 0x20, true, 0x5555555500000000, 0x0),
        (0x55555555, 0x40, false, 0x55555555, 0x0),
        (0x55555555, 0x40, true, 0x55555555, 0x0),
        (0x55555555, 0xa0, false, 0x5555555500000000, 0x0),
        (0x55555555, 0xa0, true, 0x5555555500000000, 0x0),
        (0x55555555, 0x9, false, 0xaaaaaaaa00, 0x0),
        (0x55555555, 0x9, true, 0xaaaaaaaa00, 0x0),
        (0x55555555, 0x11, false, 0xaaaaaaaa0000, 0x0),
        (0x55555555, 0x11, true, 0xaaaaaaaa0000, 0x0),
        (0x55555555, 0x21, false, 0xaaaaaaaa00000000, 0x0),
        (0x55555555, 0x21, true, 0xaaaaaaaa00000000, 0x0),
        (0x12345678, 0x3, false, 0x91a2b3c0, 0x0),
        (0x12345678, 0x3, true, 0x91a2b3c0, 0x0),
        (0x12345678, 0x4, false, 0x123456780, 0x0),
        (0x12345678, 0x4, true, 0x123456780, 0x0),
        (0x80000000, 0x7f, false, 0x40000000, 0x0),
        (0x80000000, 0x7f, true, 0x40000000, 0x0),
        (0x80000000, 0xf, false, 0x400000000000, 0x0),
        (0x80000000, 0xf, true, 0x400000000000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x4000000000000000, 0x0),
        (0x8000000000000000, 0x7f, true, 0x4000000000000000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0xbfffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0xbfffffffffffffff, 0x1),
        (0x8000000000000000, 0xff, false, 0x4000000000000000, 0x0),
        (0x8000000000000000, 0xff, true, 0x4000000000000000, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::rol, qword_ptr, 64, false);
}

#[test]
fn ror_byte_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0x46, 0x0),
        (0x64, 0x64, true, 0x46, 0x0),
        (0x64, 0x1, false, 0x32, 0x0),
        (0x64, 0x1, true, 0x32, 0x0),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x0, 0x0),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0xbf, 0x801),
        (0x7f, 0x1, true, 0xbf, 0x801),
        (0x7f, 0x2, false, 0xdf, 0x1),
        (0x7f, 0x2, true, 0xdf, 0x1),
        (0xaaaaaaaa, 0x3, false, 0xaaaaaa55, 0x0),
        (0xaaaaaaaa, 0x3, true, 0xaaaaaa55, 0x0),
        (0xaaaaaaaa, 0x8, false, 0xaaaaaaaa, 0x1),
        (0xaaaaaaaa, 0x8, true, 0xaaaaaaaa, 0x1),
        (0xaaaaaaaa, 0x10, false, 0xaaaaaaaa, 0x1),
        (0xaaaaaaaa, 0x10, true, 0xaaaaaaaa, 0x1),
        (0xaaaaaaaa, 0x20, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x20, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x40, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x40, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0xa0, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0xa0, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x9, false, 0xaaaaaa55, 0x0),
        (0xaaaaaaaa, 0x9, true, 0xaaaaaa55, 0x0),
        (0xaaaaaaaa, 0x11, false, 0xaaaaaa55, 0x0),
        (0xaaaaaaaa, 0x11, true, 0xaaaaaa55, 0x0),
        (0xaaaaaaaa, 0x21, false, 0xaaaaaa55, 0x800),
        (0xaaaaaaaa, 0x21, true, 0xaaaaaa55, 0x800),
        (0x55555555, 0x3, false, 0x555555aa, 0x1),
        (0x55555555, 0x3, true, 0x555555aa, 0x1),
        (0x55555555, 0x10, false, 0x55555555, 0x0),
        (0x55555555, 0x10, true, 0x55555555, 0x0),
        (0x55555555, 0x20, false, 0x55555555, 0x0),
        (0x55555555, 0x20, true, 0x55555555, 0x0),
        (0x55555555, 0x40, false, 0x55555555, 0x0),
        (0x55555555, 0x40, true, 0x55555555, 0x0),
        (0x55555555, 0xa0, false, 0x55555555, 0x0),
        (0x55555555, 0xa0, true, 0x55555555, 0x0),
        (0x55555555, 0x9, false, 0x555555aa, 0x1),
        (0x55555555, 0x9, true, 0x555555aa, 0x1),
        (0x55555555, 0x11, false, 0x555555aa, 0x1),
        (0x55555555, 0x11, true, 0x555555aa, 0x1),
        (0x55555555, 0x21, false, 0x555555aa, 0x801),
        (0x55555555, 0x21, true, 0x555555aa, 0x801),
        (0x12345678, 0x3, false, 0x1234560f, 0x0),
        (0x12345678, 0x3, true, 0x1234560f, 0x0),
        (0x12345678, 0x4, false, 0x12345687, 0x1),
        (0x12345678, 0x4, true, 0x12345687, 0x1),
        (0x80000000, 0x7f, false, 0x80000000, 0x0),
        (0x80000000, 0x7f, true, 0x80000000, 0x0),
        (0x80000000, 0xf, false, 0x80000000, 0x0),
        (0x80000000, 0xf, true, 0x80000000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0x7f, true, 0x8000000000000000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0x7fffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0x7fffffffffffffff, 0x1),
        (0x8000000000000000, 0xff, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0xff, true, 0x8000000000000000, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::ror, byte_ptr, 8, false);
}

// weird comment in legacy emulator about carry flag, investigate
#[test]
fn ror_word_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0x4006, 0x0),
        (0x64, 0x64, true, 0x4006, 0x0),
        (0x64, 0x1, false, 0x32, 0x0),
        (0x64, 0x1, true, 0x32, 0x0),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x0, 0x0),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0x803f, 0x801),
        (0x7f, 0x1, true, 0x803f, 0x801),
        (0x7f, 0x2, false, 0xc01f, 0x1),
        (0x7f, 0x2, true, 0xc01f, 0x1),
        (0xaaaaaaaa, 0x3, false, 0xaaaa5555, 0x0),
        (0xaaaaaaaa, 0x3, true, 0xaaaa5555, 0x0),
        (0xaaaaaaaa, 0x8, false, 0xaaaaaaaa, 0x1),
        (0xaaaaaaaa, 0x8, true, 0xaaaaaaaa, 0x1),
        (0xaaaaaaaa, 0x10, false, 0xaaaaaaaa, 0x1),
        (0xaaaaaaaa, 0x10, true, 0xaaaaaaaa, 0x1),
        (0xaaaaaaaa, 0x20, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x20, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x40, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x40, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0xa0, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0xa0, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x9, false, 0xaaaa5555, 0x0),
        (0xaaaaaaaa, 0x9, true, 0xaaaa5555, 0x0),
        (0xaaaaaaaa, 0x11, false, 0xaaaa5555, 0x0),
        (0xaaaaaaaa, 0x11, true, 0xaaaa5555, 0x0),
        (0xaaaaaaaa, 0x21, false, 0xaaaa5555, 0x800),
        (0xaaaaaaaa, 0x21, true, 0xaaaa5555, 0x800),
        (0x55555555, 0x3, false, 0x5555aaaa, 0x1),
        (0x55555555, 0x3, true, 0x5555aaaa, 0x1),
        (0x55555555, 0x10, false, 0x55555555, 0x0),
        (0x55555555, 0x10, true, 0x55555555, 0x0),
        (0x55555555, 0x20, false, 0x55555555, 0x0),
        (0x55555555, 0x20, true, 0x55555555, 0x0),
        (0x55555555, 0x40, false, 0x55555555, 0x0),
        (0x55555555, 0x40, true, 0x55555555, 0x0),
        (0x55555555, 0xa0, false, 0x55555555, 0x0),
        (0x55555555, 0xa0, true, 0x55555555, 0x0),
        (0x55555555, 0x9, false, 0x5555aaaa, 0x1),
        (0x55555555, 0x9, true, 0x5555aaaa, 0x1),
        (0x55555555, 0x11, false, 0x5555aaaa, 0x1),
        (0x55555555, 0x11, true, 0x5555aaaa, 0x1),
        (0x55555555, 0x21, false, 0x5555aaaa, 0x801),
        (0x55555555, 0x21, true, 0x5555aaaa, 0x801),
        (0x12345678, 0x3, false, 0x12340acf, 0x0),
        (0x12345678, 0x3, true, 0x12340acf, 0x0),
        (0x12345678, 0x4, false, 0x12348567, 0x1),
        (0x12345678, 0x4, true, 0x12348567, 0x1),
        (0x80000000, 0x7f, false, 0x80000000, 0x0),
        (0x80000000, 0x7f, true, 0x80000000, 0x0),
        (0x80000000, 0xf, false, 0x80000000, 0x0),
        (0x80000000, 0xf, true, 0x80000000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0x7f, true, 0x8000000000000000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0x7fffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0x7fffffffffffffff, 0x1),
        (0x8000000000000000, 0xff, false, 0x8000000000000000, 0x0),
        (0x8000000000000000, 0xff, true, 0x8000000000000000, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::ror, word_ptr, 16, false);
}

#[test]
fn ror_qword_memory_by_regvalue() {
    let variations = [
        (0x0, 0x0, false, 0x0, 0x0),
        (0x0, 0x0, true, 0x0, 0x0),
        (0x64, 0x64, false, 0x640000000, 0x0),
        (0x64, 0x64, true, 0x640000000, 0x0),
        (0x64, 0x1, false, 0x32, 0x0),
        (0x64, 0x1, true, 0x32, 0x0),
        (0x0, 0x1, false, 0x0, 0x0),
        (0x0, 0x1, true, 0x0, 0x0),
        (0x1, 0x0, false, 0x1, 0x0),
        (0x1, 0x0, true, 0x1, 0x0),
        (0xffffffffffffffff, 0x0, false, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x0, true, 0xffffffffffffffff, 0x0),
        (0xffffffffffffffff, 0x1, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0x1, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xf, true, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, false, 0xffffffffffffffff, 0x1),
        (0xffffffffffffffff, 0xff, true, 0xffffffffffffffff, 0x1),
        (0x7fffffffffffffff, 0x0, false, 0x7fffffffffffffff, 0x0),
        (0x7fffffffffffffff, 0x0, true, 0x7fffffffffffffff, 0x0),
        (0x7f, 0x0, false, 0x7f, 0x0),
        (0x7f, 0x0, true, 0x7f, 0x0),
        (0x7f, 0x1, false, 0x800000000000003f, 0x801),
        (0x7f, 0x1, true, 0x800000000000003f, 0x801),
        (0x7f, 0x2, false, 0xc00000000000001f, 0x1),
        (0x7f, 0x2, true, 0xc00000000000001f, 0x1),
        (0xaaaaaaaa, 0x3, false, 0x4000000015555555, 0x0),
        (0xaaaaaaaa, 0x3, true, 0x4000000015555555, 0x0),
        (0xaaaaaaaa, 0x8, false, 0xaa00000000aaaaaa, 0x1),
        (0xaaaaaaaa, 0x8, true, 0xaa00000000aaaaaa, 0x1),
        (0xaaaaaaaa, 0x10, false, 0xaaaa00000000aaaa, 0x1),
        (0xaaaaaaaa, 0x10, true, 0xaaaa00000000aaaa, 0x1),
        (0xaaaaaaaa, 0x20, false, 0xaaaaaaaa00000000, 0x1),
        (0xaaaaaaaa, 0x20, true, 0xaaaaaaaa00000000, 0x1),
        (0xaaaaaaaa, 0x40, false, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0x40, true, 0xaaaaaaaa, 0x0),
        (0xaaaaaaaa, 0xa0, false, 0xaaaaaaaa00000000, 0x1),
        (0xaaaaaaaa, 0xa0, true, 0xaaaaaaaa00000000, 0x1),
        (0xaaaaaaaa, 0x9, false, 0x5500000000555555, 0x0),
        (0xaaaaaaaa, 0x9, true, 0x5500000000555555, 0x0),
        (0xaaaaaaaa, 0x11, false, 0x5555000000005555, 0x0),
        (0xaaaaaaaa, 0x11, true, 0x5555000000005555, 0x0),
        (0xaaaaaaaa, 0x21, false, 0x5555555500000000, 0x0),
        (0xaaaaaaaa, 0x21, true, 0x5555555500000000, 0x0),
        (0x55555555, 0x3, false, 0xa00000000aaaaaaa, 0x1),
        (0x55555555, 0x3, true, 0xa00000000aaaaaaa, 0x1),
        (0x55555555, 0x10, false, 0x5555000000005555, 0x0),
        (0x55555555, 0x10, true, 0x5555000000005555, 0x0),
        (0x55555555, 0x20, false, 0x5555555500000000, 0x0),
        (0x55555555, 0x20, true, 0x5555555500000000, 0x0),
        (0x55555555, 0x40, false, 0x55555555, 0x0),
        (0x55555555, 0x40, true, 0x55555555, 0x0),
        (0x55555555, 0xa0, false, 0x5555555500000000, 0x0),
        (0x55555555, 0xa0, true, 0x5555555500000000, 0x0),
        (0x55555555, 0x9, false, 0xaa800000002aaaaa, 0x1),
        (0x55555555, 0x9, true, 0xaa800000002aaaaa, 0x1),
        (0x55555555, 0x11, false, 0xaaaa800000002aaa, 0x1),
        (0x55555555, 0x11, true, 0xaaaa800000002aaa, 0x1),
        (0x55555555, 0x21, false, 0x2aaaaaaa80000000, 0x0),
        (0x55555555, 0x21, true, 0x2aaaaaaa80000000, 0x0),
        (0x12345678, 0x3, false, 0x2468acf, 0x0),
        (0x12345678, 0x3, true, 0x2468acf, 0x0),
        (0x12345678, 0x4, false, 0x8000000001234567, 0x1),
        (0x12345678, 0x4, true, 0x8000000001234567, 0x1),
        (0x80000000, 0x7f, false, 0x100000000, 0x0),
        (0x80000000, 0x7f, true, 0x100000000, 0x0),
        (0x80000000, 0xf, false, 0x10000, 0x0),
        (0x80000000, 0xf, true, 0x10000, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x8000000000000000, 0x7f, false, 0x1, 0x0),
        (0x8000000000000000, 0x7f, true, 0x1, 0x0),
        (0x7fffffff, 0x80, false, 0x7fffffff, 0x0),
        (0x7fffffff, 0x80, true, 0x7fffffff, 0x0),
        (0x7fffffffffffffff, 0xff, false, 0xfffffffffffffffe, 0x1),
        (0x7fffffffffffffff, 0xff, true, 0xfffffffffffffffe, 0x1),
        (0x8000000000000000, 0xff, false, 0x1, 0x0),
        (0x8000000000000000, 0xff, true, 0x1, 0x0),
    ];

    rotate_memory_by_regvalue(&variations, CodeAssembler::ror, qword_ptr, 64, false);
}
