#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef scalar_t__ uint8_t;
typedef int uint32_t;

/* Variables and functions */
void read_knobs(uint8_t *k1, uint8_t *k2, uint8_t *k3, uint8_t *b1, uint8_t *b2,
                uint8_t *b3, unsigned char *knobs_mem_base) {
  uint32_t rgb_knobs_value = *(volatile uint32_t *)(knobs_mem_base + 0x024);
  *k1 = (uint8_t)(rgb_knobs_value & 0xFF);
  *k2 = (uint8_t)((rgb_knobs_value >> 8) & 0xFF);
  *k3 = (uint8_t)((rgb_knobs_value >> 16) & 0xFF);
  *b1 = (uint8_t)((rgb_knobs_value >> 24) & 1);
  *b2 = (uint8_t)((rgb_knobs_value >> 25) & 1);
  *b3 = (uint8_t)((rgb_knobs_value >> 26) & 1);
  *(volatile uint32_t *)(knobs_mem_base + 0x004) = rgb_knobs_value;
}


x86 assembly (clang, -O0):
<read_knobs>:
push   %rbp
mov    %rsp,%rbp
mov    0x10(%rbp),%rax
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
mov    %r9,-0x30(%rbp)
mov    0x10(%rbp),%rax
mov    0x24(%rax),%eax
mov    %eax,-0x34(%rbp)
mov    -0x34(%rbp),%eax
and    $0xff,%eax
movslq %eax,%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x34(%rbp),%eax
sar    $0x8,%eax
and    $0xff,%eax
movslq %eax,%rcx
mov    -0x10(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x34(%rbp),%eax
sar    $0x10,%eax
and    $0xff,%eax
movslq %eax,%rcx
mov    -0x18(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x34(%rbp),%eax
sar    $0x18,%eax
and    $0x1,%eax
movslq %eax,%rcx
mov    -0x20(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x34(%rbp),%eax
sar    $0x19,%eax
and    $0x1,%eax
movslq %eax,%rcx
mov    -0x28(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x34(%rbp),%eax
sar    $0x1a,%eax
and    $0x1,%eax
movslq %eax,%rcx
mov    -0x30(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x34(%rbp),%ecx
mov    0x10(%rbp),%rax
mov    %ecx,0x4(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<read_knobs>:
push   %rbx
mov    0x10(%rsp),%r10
mov    0x24(%r10),%ebx
movzbl %bl,%eax
mov    %rax,(%rdi)
movzbl %bh,%eax
mov    %rax,(%rsi)
mov    %ebx,%eax
shr    $0x10,%eax
movzbl %al,%eax
mov    %rax,(%rdx)
mov    %ebx,%eax
shr    $0x18,%eax
and    $0x1,%eax
mov    %rax,(%rcx)
mov    %ebx,%eax
shr    $0x19,%eax
and    $0x1,%eax
mov    %rax,(%r8)
mov    %ebx,%eax
shr    $0x1a,%eax
and    $0x1,%eax
mov    %rax,(%r9)
mov    %ebx,0x4(%r10)
pop    %rbx
ret

LLVM IR (-O0):
define void @read_knobs(i64* %0, i64* %1, i64* %2, i64* %3, i64* %4, i64* %5, i8* %6) {
%8 = alloca i64*
%9 = alloca i64*
%10 = alloca i64*
%11 = alloca i64*
%12 = alloca i64*
%13 = alloca i64*
%14 = alloca i8*
%15 = alloca i32
store i64* %0, i64** %8
store i64* %1, i64** %9
store i64* %2, i64** %10
store i64* %3, i64** %11
store i64* %4, i64** %12
store i64* %5, i64** %13
store i8* %6, i8** %14
%16 = load i8*, i8** %14
%17 = getelementptr inbounds i8, i8* %16, i64 36
%18 = bitcast i8* %17 to i32*
%19 = load volatile i32, i32* %18
store i32 %19, i32* %15
%20 = load i32, i32* %15
%21 = and i32 %20, 255
%22 = sext i32 %21 to i64
%23 = load i64*, i64** %8
store i64 %22, i64* %23
%24 = load i32, i32* %15
%25 = ashr i32 %24, 8
%26 = and i32 %25, 255
%27 = sext i32 %26 to i64
%28 = load i64*, i64** %9
store i64 %27, i64* %28
%29 = load i32, i32* %15
%30 = ashr i32 %29, 16
%31 = and i32 %30, 255
%32 = sext i32 %31 to i64
%33 = load i64*, i64** %10
store i64 %32, i64* %33
%34 = load i32, i32* %15
%35 = ashr i32 %34, 24
%36 = and i32 %35, 1
%37 = sext i32 %36 to i64
%38 = load i64*, i64** %11
store i64 %37, i64* %38
%39 = load i32, i32* %15
%40 = ashr i32 %39, 25
%41 = and i32 %40, 1
%42 = sext i32 %41 to i64
%43 = load i64*, i64** %12
store i64 %42, i64* %43
%44 = load i32, i32* %15
%45 = ashr i32 %44, 26
%46 = and i32 %45, 1
%47 = sext i32 %46 to i64
%48 = load i64*, i64** %13
store i64 %47, i64* %48
%49 = load i32, i32* %15
%50 = load i8*, i8** %14
%51 = getelementptr inbounds i8, i8* %50, i64 4
%52 = bitcast i8* %51 to i32*
store volatile i32 %49, i32* %52
ret void
}

LLVM IR (-O2):
define void @read_knobs(i64* nocapture writeonly %0, i64* nocapture writeonly %1, i64* nocapture writeonly %2, i64* nocapture writeonly %3, i64* nocapture writeonly %4, i64* nocapture writeonly %5, i8* %6) {
%8 = getelementptr inbounds i8, i8* %6, i64 36
%9 = bitcast i8* %8 to i32*
%10 = load volatile i32, i32* %9
%11 = and i32 %10, 255
%12 = zext i32 %11 to i64
store i64 %12, i64* %0
%13 = lshr i32 %10, 8
%14 = and i32 %13, 255
%15 = zext i32 %14 to i64
store i64 %15, i64* %1
%16 = lshr i32 %10, 16
%17 = and i32 %16, 255
%18 = zext i32 %17 to i64
store i64 %18, i64* %2
%19 = lshr i32 %10, 24
%20 = and i32 %19, 1
%21 = zext i32 %20 to i64
store i64 %21, i64* %3
%22 = lshr i32 %10, 25
%23 = and i32 %22, 1
%24 = zext i32 %23 to i64
store i64 %24, i64* %4
%25 = lshr i32 %10, 26
%26 = and i32 %25, 1
%27 = zext i32 %26 to i64
store i64 %27, i64* %5
%28 = getelementptr inbounds i8, i8* %6, i64 4
%29 = bitcast i8* %28 to i32*
store volatile i32 %10, i32* %29
ret void
}