unsigned long USBIndexRead(unsigned long ulBase, unsigned long ulEndpoint,
                           unsigned long ulIndexedReg, unsigned long ulSize) {
  unsigned char ulIndex;
  unsigned char ulValue;
  ;

  ;
  ;
  ulIndex = (*((volatile unsigned char *)(ulBase + 0x0000000E)));
  (*((volatile unsigned char *)(ulBase + 0x0000000E))) = ulEndpoint;
  if (ulSize == 1) {
    ulValue = (*((volatile unsigned char *)(ulBase + ulIndexedReg)));
  } else {
    ulValue = (*((volatile unsigned short *)(ulBase + ulIndexedReg)));
  }
  (*((volatile unsigned char *)(ulBase + 0x0000000E))) = ulIndex;
  return (ulValue);
}


x86 assembly (clang, -O0):
<USBIndexRead>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    -0x8(%rbp),%rax
mov    0xe(%rax),%al
mov    %al,-0x21(%rbp)
mov    -0x10(%rbp),%rax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0xe(%rax)
cmpq   $0x1,-0x20(%rbp)
jne    1148 <USBIndexRead+0x48>
mov    -0x8(%rbp),%rax
add    -0x18(%rbp),%rax
mov    (%rax),%al
mov    %al,-0x22(%rbp)
jmp    1156 <USBIndexRead+0x56>
mov    -0x8(%rbp),%rax
add    -0x18(%rbp),%rax
mov    (%rax),%ax
mov    %al,-0x22(%rbp)
mov    -0x21(%rbp),%cl
mov    -0x8(%rbp),%rax
mov    %cl,0xe(%rax)
movzbl -0x22(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<USBIndexRead>:
mov    0xe(%rdi),%al
mov    %sil,0xe(%rdi)
cmp    $0x1,%rcx
jne    1112 <USBIndexRead+0x12>
mov    (%rdi,%rdx,1),%cl
jmp    1116 <USBIndexRead+0x16>
movzwl (%rdi,%rdx,1),%ecx
mov    %al,0xe(%rdi)
movzbl %cl,%eax
ret

LLVM IR (-O0):
define i64 @USBIndexRead(i64 %0, i64 %1, i64 %2, i64 %3) {
%5 = alloca i64
%6 = alloca i64
%7 = alloca i64
%8 = alloca i64
%9 = alloca i8
%10 = alloca i8
store i64 %0, i64* %5
store i64 %1, i64* %6
store i64 %2, i64* %7
store i64 %3, i64* %8
%11 = load i64, i64* %5
%12 = add i64 %11, 14
%13 = inttoptr i64 %12 to i8*
%14 = load volatile i8, i8* %13
store i8 %14, i8* %9
%15 = load i64, i64* %6
%16 = trunc i64 %15 to i8
%17 = load i64, i64* %5
%18 = add i64 %17, 14
%19 = inttoptr i64 %18 to i8*
store volatile i8 %16, i8* %19
%20 = load i64, i64* %8
%21 = icmp eq i64 %20, 1
br i1 %21, label %22, label %28
22: ; preds = %4
%23 = load i64, i64* %5
%24 = load i64, i64* %7
%25 = add i64 %23, %24
%26 = inttoptr i64 %25 to i8*
%27 = load volatile i8, i8* %26
store i8 %27, i8* %10
br label %35
28: ; preds = %4
%29 = load i64, i64* %5
%30 = load i64, i64* %7
%31 = add i64 %29, %30
%32 = inttoptr i64 %31 to i16*
%33 = load volatile i16, i16* %32
%34 = trunc i16 %33 to i8
store i8 %34, i8* %10
br label %35
35: ; preds = %28, %22
%36 = load i8, i8* %9
%37 = load i64, i64* %5
%38 = add i64 %37, 14
%39 = inttoptr i64 %38 to i8*
store volatile i8 %36, i8* %39
%40 = load i8, i8* %10
%41 = zext i8 %40 to i64
ret i64 %41
}

LLVM IR (-O2):
define i64 @USBIndexRead(i64 %0, i64 %1, i64 %2, i64 %3) {
%5 = add i64 %0, 14
%6 = inttoptr i64 %5 to i8*
%7 = load volatile i8, i8* %6
%8 = trunc i64 %1 to i8
store volatile i8 %8, i8* %6
%9 = icmp eq i64 %3, 1
%10 = add i64 %2, %0
br i1 %9, label %11, label %14
11: ; preds = %4
%12 = inttoptr i64 %10 to i8*
%13 = load volatile i8, i8* %12
br label %18
14: ; preds = %4
%15 = inttoptr i64 %10 to i16*
%16 = load volatile i16, i16* %15
%17 = trunc i16 %16 to i8
br label %18
18: ; preds = %14, %11
%19 = phi i8 [ %13, %11 ], [ %17, %14 ]
store volatile i8 %7, i8* %6
%20 = zext i8 %19 to i64
ret i64 %20
}