#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 */

/* Variables and functions */
int VPB_get_speed();
void SPI_init(int channel_mask, int bits, int bps) {
  (void)bits;
  int dummy, i;
  int div_calc;
  if (channel_mask & 1) {
    (*((volatile unsigned long *)0xE002C000)) &=
        ~((3UL << 8) | (3UL << 10) | (3UL << 12) | (3UL << 14));
    (*((volatile unsigned long *)0xE002C000)) |=
        (1UL << 8) | (1UL << 10) | (1UL << 12);
    (*((volatile unsigned short *)0xE0020000)) = (1 << 5) | (0 << 4);
    div_calc = ((VPB_get_speed() / bps) + 1) & 0xFFFFFFFE;
    if (div_calc < 8)
      div_calc = 8;
    (*((volatile unsigned char *)0xE002000C)) = div_calc;
  }
  if (channel_mask & 2) {
    (*((volatile unsigned char *)0xE0068004)) &= ~(1 << 1);
    (*((volatile unsigned short *)0xE0068000)) =
        ((8 - 1) << 0) | (0 << 6) | (0x2 << 8);
    (*((volatile unsigned long *)0xE002C004)) =
        ((*((volatile unsigned long *)0xE002C004)) & (~(3 << 2))) | (2 << 2);
    (*((volatile unsigned long *)0xE002C004)) =
        ((*((volatile unsigned long *)0xE002C004)) & (~(3 << 4))) | (2 << 4);
    (*((volatile unsigned long *)0xE002C004)) =
        ((*((volatile unsigned long *)0xE002C004)) & (~(3 << 6))) | (2 << 6);
    div_calc = (VPB_get_speed() / bps);
    if (div_calc < 2)
      div_calc = 2;
    (*((volatile unsigned char *)0xE0068010)) = div_calc;
    (*((volatile unsigned char *)0xE0068004)) = (1 << 1);
    for (i = 0; i < 8; i++) {
      dummy = (*((volatile unsigned short *)0xE0068008));
    }
  }
}


x86 assembly (clang, -O0):
<SPI_init>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    %edx,-0xc(%rbp)
mov    -0x4(%rbp),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     1199 <SPI_init+0x89>
mov    $0xe002c000,%eax
mov    (%rax),%rcx
and    $0xffffffffffff00ff,%rcx
mov    $0xe002c000,%eax
mov    %rcx,(%rax)
mov    $0xe002c000,%eax
mov    (%rax),%rcx
or     $0x1500,%rcx
mov    $0xe002c000,%eax
mov    %rcx,(%rax)
mov    $0xe0020000,%eax
movw   $0x20,(%rax)
mov    $0x0,%al
call   1030 <VPB_get_speed@plt>
cltd
idivl  -0xc(%rbp)
add    $0x1,%eax
and    $0xfffffffe,%eax
mov    %eax,-0x18(%rbp)
cmpl   $0x8,-0x18(%rbp)
jge    118d <SPI_init+0x7d>
movl   $0x8,-0x18(%rbp)
mov    -0x18(%rbp),%eax
mov    %al,%cl
mov    $0xe002000c,%eax
mov    %cl,(%rax)
mov    -0x4(%rbp),%eax
and    $0x2,%eax
cmp    $0x0,%eax
je     127b <SPI_init+0x16b>
mov    $0xe0068004,%eax
mov    (%rax),%al
movzbl %al,%eax
and    $0xfffffffd,%eax
mov    %al,%cl
mov    $0xe0068004,%eax
mov    %cl,(%rax)
mov    $0xe0068000,%eax
movw   $0x207,(%rax)
mov    $0xe002c004,%eax
mov    (%rax),%rcx
and    $0xfffffffffffffff3,%rcx
or     $0x8,%rcx
mov    $0xe002c004,%eax
mov    %rcx,(%rax)
mov    $0xe002c004,%eax
mov    (%rax),%rcx
and    $0xffffffffffffffcf,%rcx
or     $0x20,%rcx
mov    $0xe002c004,%eax
mov    %rcx,(%rax)
mov    $0xe002c004,%eax
mov    (%rax),%rcx
and    $0xffffffffffffff3f,%rcx
or     $0x80,%rcx
mov    $0xe002c004,%eax
mov    %rcx,(%rax)
mov    $0x0,%al
call   1030 <VPB_get_speed@plt>
cltd
idivl  -0xc(%rbp)
mov    %eax,-0x18(%rbp)
cmpl   $0x2,-0x18(%rbp)
jge    1235 <SPI_init+0x125>
movl   $0x2,-0x18(%rbp)
mov    -0x18(%rbp),%eax
mov    %al,%cl
mov    $0xe0068010,%eax
mov    %cl,(%rax)
mov    $0xe0068004,%eax
movb   $0x2,(%rax)
movl   $0x0,-0x14(%rbp)
cmpl   $0x8,-0x14(%rbp)
jge    1276 <SPI_init+0x166>
mov    $0xe0068008,%eax
mov    (%rax),%ax
movzwl %ax,%eax
mov    %eax,-0x10(%rbp)
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x14(%rbp)
jmp    1250 <SPI_init+0x140>
jmp    127b <SPI_init+0x16b>
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<SPI_init>:
push   %rbp
push   %r14
push   %rbx
mov    %edx,%r14d
mov    %edi,%ebp
mov    $0xe0068008,%ebx
test   $0x1,%bpl
je     1165 <SPI_init+0x55>
andq   $0xffffffffffff00ff,-0x3c008(%rbx)
orq    $0x1500,-0x3c008(%rbx)
movw   $0x20,-0x48008(%rbx)
xor    %eax,%eax
call   1030 <VPB_get_speed@plt>
cltd
idiv   %r14d
add    $0x1,%eax
and    $0xfffffffe,%eax
cmp    $0x9,%eax
mov    $0x8,%ecx
cmovge %eax,%ecx
mov    %cl,-0x47ffc(%rbx)
test   $0x2,%bpl
je     11f5 <SPI_init+0xe5>
andb   $0xfd,-0x4(%rbx)
movw   $0x207,-0x8(%rbx)
mov    -0x3c004(%rbx),%rax
and    $0xfffffffffffffff3,%rax
or     $0x8,%rax
mov    %rax,-0x3c004(%rbx)
mov    -0x3c004(%rbx),%rax
and    $0xffffffffffffffcf,%rax
or     $0x20,%rax
mov    %rax,-0x3c004(%rbx)
mov    $0xffffffffffffff3f,%rax
and    -0x3c004(%rbx),%rax
or     $0x80,%rax
mov    %rax,-0x3c004(%rbx)
xor    %eax,%eax
call   1030 <VPB_get_speed@plt>
cltd
idiv   %r14d
cmp    $0x3,%eax
mov    $0x2,%ecx
cmovge %eax,%ecx
mov    %cl,0x8(%rbx)
movb   $0x2,-0x4(%rbx)
movzwl (%rbx),%eax
movzwl (%rbx),%eax
movzwl (%rbx),%eax
movzwl (%rbx),%eax
movzwl (%rbx),%eax
movzwl (%rbx),%eax
movzwl (%rbx),%eax
movzwl (%rbx),%eax
pop    %rbx
pop    %r14
pop    %rbp
ret

LLVM IR (-O0):
define void @SPI_init(i32 %0, i32 %1, i32 %2) {
%4 = alloca i32
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
store i32 %0, i32* %4
store i32 %1, i32* %5
store i32 %2, i32* %6
%10 = load i32, i32* %5
%11 = load i32, i32* %4
%12 = and i32 %11, 1
%13 = icmp ne i32 %12, 0
br i1 %13, label %14, label %30
14: ; preds = %3
%15 = load volatile i64, i64* inttoptr (i64 3758276608 to i64*)
%16 = and i64 %15, -65281
store volatile i64 %16, i64* inttoptr (i64 3758276608 to i64*)
%17 = load volatile i64, i64* inttoptr (i64 3758276608 to i64*)
%18 = or i64 %17, 5376
store volatile i64 %18, i64* inttoptr (i64 3758276608 to i64*)
store volatile i16 32, i16* inttoptr (i64 3758227456 to i16*)
%19 = call i32 (...) @VPB_get_speed()
%20 = load i32, i32* %6
%21 = sdiv i32 %19, %20
%22 = add nsw i32 %21, 1
%23 = and i32 %22, -2
store i32 %23, i32* %9
%24 = load i32, i32* %9
%25 = icmp slt i32 %24, 8
br i1 %25, label %26, label %27
26: ; preds = %14
store i32 8, i32* %9
br label %27
27: ; preds = %26, %14
%28 = load i32, i32* %9
%29 = trunc i32 %28 to i8
store volatile i8 %29, i8* inttoptr (i64 3758227468 to i8*)
br label %30
30: ; preds = %27, %3
%31 = load i32, i32* %4
%32 = and i32 %31, 2
%33 = icmp ne i32 %32, 0
br i1 %33, label %34, label %67
34: ; preds = %30
%35 = load volatile i8, i8* inttoptr (i64 3758522372 to i8*)
%36 = zext i8 %35 to i32
%37 = and i32 %36, -3
%38 = trunc i32 %37 to i8
store volatile i8 %38, i8* inttoptr (i64 3758522372 to i8*)
store volatile i16 519, i16* inttoptr (i64 3758522368 to i16*)
%39 = load volatile i64, i64* inttoptr (i64 3758276612 to i64*)
%40 = and i64 %39, -13
%41 = or i64 %40, 8
store volatile i64 %41, i64* inttoptr (i64 3758276612 to i64*)
%42 = load volatile i64, i64* inttoptr (i64 3758276612 to i64*)
%43 = and i64 %42, -49
%44 = or i64 %43, 32
store volatile i64 %44, i64* inttoptr (i64 3758276612 to i64*)
%45 = load volatile i64, i64* inttoptr (i64 3758276612 to i64*)
%46 = and i64 %45, -193
%47 = or i64 %46, 128
store volatile i64 %47, i64* inttoptr (i64 3758276612 to i64*)
%48 = call i32 (...) @VPB_get_speed()
%49 = load i32, i32* %6
%50 = sdiv i32 %48, %49
store i32 %50, i32* %9
%51 = load i32, i32* %9
%52 = icmp slt i32 %51, 2
br i1 %52, label %53, label %54
53: ; preds = %34
store i32 2, i32* %9
br label %54
54: ; preds = %53, %34
%55 = load i32, i32* %9
%56 = trunc i32 %55 to i8
store volatile i8 %56, i8* inttoptr (i64 3758522384 to i8*)
store volatile i8 2, i8* inttoptr (i64 3758522372 to i8*)
store i32 0, i32* %8
br label %57
57: ; preds = %63, %54
%58 = load i32, i32* %8
%59 = icmp slt i32 %58, 8
br i1 %59, label %60, label %66
60: ; preds = %57
%61 = load volatile i16, i16* inttoptr (i64 3758522376 to i16*)
%62 = zext i16 %61 to i32
store i32 %62, i32* %7
br label %63
63: ; preds = %60
%64 = load i32, i32* %8
%65 = add nsw i32 %64, 1
store i32 %65, i32* %8
br label %57
66: ; preds = %57
br label %67
67: ; preds = %66, %30
ret void
}

LLVM IR (-O2):
define void @SPI_init(i32 %0, i32 %1, i32 %2) {
%4 = and i32 %0, 1
%5 = icmp eq i32 %4, 0
br i1 %5, label %18, label %6
6: ; preds = %3
%7 = load volatile i64, i64* inttoptr (i64 3758276608 to i64*)
%8 = and i64 %7, -65281
store volatile i64 %8, i64* inttoptr (i64 3758276608 to i64*)
%9 = load volatile i64, i64* inttoptr (i64 3758276608 to i64*)
%10 = or i64 %9, 5376
store volatile i64 %10, i64* inttoptr (i64 3758276608 to i64*)
store volatile i16 32, i16* inttoptr (i64 3758227456 to i16*)
%11 = tail call i32 (...) @VPB_get_speed()
%12 = sdiv i32 %11, %2
%13 = add nsw i32 %12, 1
%14 = and i32 %13, -2
%15 = icmp sgt i32 %14, 8
%16 = select i1 %15, i32 %14, i32 8
%17 = trunc i32 %16 to i8
store volatile i8 %17, i8* inttoptr (i64 3758227468 to i8*)
br label %18
18: ; preds = %6, %3
%19 = and i32 %0, 2
%20 = icmp eq i32 %19, 0
br i1 %20, label %46, label %21
21: ; preds = %18
%22 = load volatile i8, i8* inttoptr (i64 3758522372 to i8*)
%23 = and i8 %22, -3
store volatile i8 %23, i8* inttoptr (i64 3758522372 to i8*)
store volatile i16 519, i16* inttoptr (i64 3758522368 to i16*)
%24 = load volatile i64, i64* inttoptr (i64 3758276612 to i64*)
%25 = and i64 %24, -13
%26 = or i64 %25, 8
store volatile i64 %26, i64* inttoptr (i64 3758276612 to i64*)
%27 = load volatile i64, i64* inttoptr (i64 3758276612 to i64*)
%28 = and i64 %27, -49
%29 = or i64 %28, 32
store volatile i64 %29, i64* inttoptr (i64 3758276612 to i64*)
%30 = load volatile i64, i64* inttoptr (i64 3758276612 to i64*)
%31 = and i64 %30, -193
%32 = or i64 %31, 128
store volatile i64 %32, i64* inttoptr (i64 3758276612 to i64*)
%33 = tail call i32 (...) @VPB_get_speed()
%34 = sdiv i32 %33, %2
%35 = icmp sgt i32 %34, 2
%36 = select i1 %35, i32 %34, i32 2
%37 = trunc i32 %36 to i8
store volatile i8 %37, i8* inttoptr (i64 3758522384 to i8*)
store volatile i8 2, i8* inttoptr (i64 3758522372 to i8*)
%38 = load volatile i16, i16* inttoptr (i64 3758522376 to i16*)
%39 = load volatile i16, i16* inttoptr (i64 3758522376 to i16*)
%40 = load volatile i16, i16* inttoptr (i64 3758522376 to i16*)
%41 = load volatile i16, i16* inttoptr (i64 3758522376 to i16*)
%42 = load volatile i16, i16* inttoptr (i64 3758522376 to i16*)
%43 = load volatile i16, i16* inttoptr (i64 3758522376 to i16*)
%44 = load volatile i16, i16* inttoptr (i64 3758522376 to i16*)
%45 = load volatile i16, i16* inttoptr (i64 3758522376 to i16*)
br label %46
46: ; preds = %21, %18
ret void
}