/* https://cirosantilli.com/linux-kernel-module-cheat#x86-cqto-and-cltq-instructions */ #include LKMC_PROLOGUE /* Quad to Octo: top bit is zero: extend with zeroes. */ mov $0x7FFFFFFFFFFFFFFF, %rax mov $0x123456789ABCDEF0, %rdx cqto mov %rax, %r12 mov %rdx, %r13 /* rax is unchanged. */ LKMC_ASSERT_EQ(%r12, $0x7FFFFFFFFFFFFFFF) /* rdx is filled with zeros. */ LKMC_ASSERT_EQ(%r13, $0) /* Quad to Octo: top bit is one: extend with ones. */ mov $0x8000000000000000, %rax mov $0x123456789ABCDEF0, %rdx cqto mov %rax, %r12 mov %rdx, %r13 LKMC_ASSERT_EQ(%r12, $0x8000000000000000) LKMC_ASSERT_EQ(%r13, $0xFFFFFFFFFFFFFFFF) /* Intel equivalent syntax also accepte by GNU GAS. */ mov $0x7FFFFFFFFFFFFFFF, %rax mov $0x123456789ABCDEF0, %rdx cqo mov %rax, %r12 mov %rdx, %r13 LKMC_ASSERT_EQ(%r12, $0x7FFFFFFFFFFFFFFF) LKMC_ASSERT_EQ(%r13, $0) /* Smaller size example: Double to Quad. * Also zeroes top 32-bits of RDX like many 32 to 64 operaions. */ mov $0xFFFFFFFF7FFFFFFF, %rax mov $0x123456789ABCDEF0, %rdx cltd mov %rax, %r12 mov %rdx, %r13 LKMC_ASSERT_EQ(%r12, $0xFFFFFFFF7FFFFFFF) LKMC_ASSERT_EQ(%r13, $0) /* Even smaller size example: Word to Doubleword. * Unlike the 32-bit one, does not zero out the top 32-bits of RDX. */ mov $0xFFFFFFFFFFFF7FFF, %rax mov $0x123456789ABCDEF0, %rdx cwtd mov %rax, %r12 mov %rdx, %r13 LKMC_ASSERT_EQ(%r12, $0xFFFFFFFFFFFF7FFF) LKMC_ASSERT_EQ(%r13, $0x123456789ABC0000) LKMC_EPILOGUE