void delay(int time) {
  unsigned int val = (50000000 >> 3) / 1000 - 1;
  (*(volatile unsigned long *)0x51000000) &= ~(0xff << 8);
  (*(volatile unsigned long *)0x51000000) |= 3 << 8;
  (*(volatile unsigned long *)0x51000004) &= ~(0xf << 12);
  (*(volatile unsigned long *)0x51000004) |= 0 << 12;
  (*(volatile unsigned long *)0x51000030) = val;
  (*(volatile unsigned long *)0x51000034) = val >> 1;
  (*(volatile unsigned long *)0x51000008) &= ~(0xf << 16);
  (*(volatile unsigned long *)0x51000008) |= (0xb << 16);
  (*(volatile unsigned long *)0x51000008) &= ~(2 << 16);
  while (time--) {
    while ((*(volatile unsigned long *)0x51000038) >= val >> 1)
      ;
    while ((*(volatile unsigned long *)0x51000038) < val >> 1)
      ;
  };
}


x86 assembly (clang, -O0):
<delay>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
movl   $0x1869,-0x8(%rbp)
mov    $0x51000000,%eax
mov    (%rax),%rcx
and    $0xffffffffffff00ff,%rcx
mov    $0x51000000,%eax
mov    %rcx,(%rax)
mov    $0x51000000,%eax
mov    (%rax),%rcx
or     $0x300,%rcx
mov    $0x51000000,%eax
mov    %rcx,(%rax)
mov    $0x51000004,%eax
mov    (%rax),%rcx
and    $0xffffffffffff0fff,%rcx
mov    $0x51000004,%eax
mov    %rcx,(%rax)
mov    $0x51000004,%eax
mov    (%rax),%rcx
or     $0x0,%rcx
mov    $0x51000004,%eax
mov    %rcx,(%rax)
mov    -0x8(%rbp),%eax
mov    %eax,%ecx
mov    $0x51000030,%eax
mov    %rcx,(%rax)
mov    -0x8(%rbp),%eax
shr    $0x1,%eax
mov    %eax,%eax
mov    %eax,%ecx
mov    $0x51000034,%eax
mov    %rcx,(%rax)
mov    $0x51000008,%eax
mov    (%rax),%rcx
and    $0xfffffffffff0ffff,%rcx
mov    $0x51000008,%eax
mov    %rcx,(%rax)
mov    $0x51000008,%eax
mov    (%rax),%rcx
or     $0xb0000,%rcx
mov    $0x51000008,%eax
mov    %rcx,(%rax)
mov    $0x51000008,%eax
mov    (%rax),%rcx
and    $0xfffffffffffdffff,%rcx
mov    $0x51000008,%eax
mov    %rcx,(%rax)
mov    -0x4(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x4(%rbp)
cmp    $0x0,%eax
je     122a <delay+0x12a>
jmp    11e4 <delay+0xe4>
mov    $0x51000038,%eax
mov    (%rax),%rax
mov    -0x8(%rbp),%ecx
shr    $0x1,%ecx
mov    %ecx,%ecx
cmp    %rcx,%rax
jb     1202 <delay+0x102>
jmp    11e4 <delay+0xe4>
jmp    1207 <delay+0x107>
mov    $0x51000038,%eax
mov    (%rax),%rax
mov    -0x8(%rbp),%ecx
shr    $0x1,%ecx
mov    %ecx,%ecx
cmp    %rcx,%rax
jae    1225 <delay+0x125>
jmp    1207 <delay+0x107>
jmp    11cb <delay+0xcb>
pop    %rbp
ret

x86 assembly (clang, -O2):
<delay>:
andq   $0xffffffffffff00ff,0x51000000
orq    $0x300,0x51000000
andq   $0xffffffffffff0fff,0x51000004
51 ff 0f ff ff
mov    0x51000004,%rax
51
mov    %rax,0x51000004
51
movq   $0x1869,0x51000030
movq   $0xc34,0x51000034
andq   $0xfffffffffff0ffff,0x51000008
51 ff ff f0 ff
orq    $0xb0000,0x51000008
andq   $0xfffffffffffdffff,0x51000008
51 ff ff fd ff
test   %edi,%edi
je     1226 <delay+0x126>
mov    %edi,%eax
test   $0x1,%dil
je     11a3 <delay+0xa3>
mov    0x51000038,%rax
51
cmp    $0xc33,%rax
ja     1180 <delay+0x80>
mov    0x51000038,%rax
51
cmp    $0xc34,%rax
jb     1190 <delay+0x90>
lea    -0x1(%rdi),%eax
cmp    $0x1,%edi
je     1226 <delay+0x126>
nopl   0x0(%rax,%rax,1)
mov    0x51000038,%rcx
51
cmp    $0xc33,%rcx
ja     11b0 <delay+0xb0>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
mov    0x51000038,%rcx
51
cmp    $0xc34,%rcx
jb     11d0 <delay+0xd0>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
mov    0x51000038,%rcx
51
cmp    $0xc33,%rcx
ja     11f0 <delay+0xf0>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
mov    0x51000038,%rcx
51
cmp    $0xc34,%rcx
jb     1210 <delay+0x110>
add    $0xfffffffe,%eax
jne    11b0 <delay+0xb0>
ret

LLVM IR (-O0):
define void @delay(i32 %0) {
%2 = alloca i32
%3 = alloca i32
store i32 %0, i32* %2
store i32 6249, i32* %3
%4 = load volatile i64, i64* inttoptr (i64 1358954496 to i64*)
%5 = and i64 %4, -65281
store volatile i64 %5, i64* inttoptr (i64 1358954496 to i64*)
%6 = load volatile i64, i64* inttoptr (i64 1358954496 to i64*)
%7 = or i64 %6, 768
store volatile i64 %7, i64* inttoptr (i64 1358954496 to i64*)
%8 = load volatile i64, i64* inttoptr (i64 1358954500 to i64*)
%9 = and i64 %8, -61441
store volatile i64 %9, i64* inttoptr (i64 1358954500 to i64*)
%10 = load volatile i64, i64* inttoptr (i64 1358954500 to i64*)
%11 = or i64 %10, 0
store volatile i64 %11, i64* inttoptr (i64 1358954500 to i64*)
%12 = load i32, i32* %3
%13 = zext i32 %12 to i64
store volatile i64 %13, i64* inttoptr (i64 1358954544 to i64*)
%14 = load i32, i32* %3
%15 = lshr i32 %14, 1
%16 = zext i32 %15 to i64
store volatile i64 %16, i64* inttoptr (i64 1358954548 to i64*)
%17 = load volatile i64, i64* inttoptr (i64 1358954504 to i64*)
%18 = and i64 %17, -983041
store volatile i64 %18, i64* inttoptr (i64 1358954504 to i64*)
%19 = load volatile i64, i64* inttoptr (i64 1358954504 to i64*)
%20 = or i64 %19, 720896
store volatile i64 %20, i64* inttoptr (i64 1358954504 to i64*)
%21 = load volatile i64, i64* inttoptr (i64 1358954504 to i64*)
%22 = and i64 %21, -131073
store volatile i64 %22, i64* inttoptr (i64 1358954504 to i64*)
br label %23
23: ; preds = %43, %1
%24 = load i32, i32* %2
%25 = add nsw i32 %24, -1
store i32 %25, i32* %2
%26 = icmp ne i32 %24, 0
br i1 %26, label %27, label %44
27: ; preds = %23
br label %28
28: ; preds = %34, %27
%29 = load volatile i64, i64* inttoptr (i64 1358954552 to i64*)
%30 = load i32, i32* %3
%31 = lshr i32 %30, 1
%32 = zext i32 %31 to i64
%33 = icmp uge i64 %29, %32
br i1 %33, label %34, label %35
34: ; preds = %28
br label %28
35: ; preds = %28
br label %36
36: ; preds = %42, %35
%37 = load volatile i64, i64* inttoptr (i64 1358954552 to i64*)
%38 = load i32, i32* %3
%39 = lshr i32 %38, 1
%40 = zext i32 %39 to i64
%41 = icmp ult i64 %37, %40
br i1 %41, label %42, label %43
42: ; preds = %36
br label %36
43: ; preds = %36
br label %23
44: ; preds = %23
ret void
}

LLVM IR (-O2):
define void @delay(i32 %0) {
%2 = load volatile i64, i64* inttoptr (i64 1358954496 to i64*)
%3 = and i64 %2, -65281
store volatile i64 %3, i64* inttoptr (i64 1358954496 to i64*)
%4 = load volatile i64, i64* inttoptr (i64 1358954496 to i64*)
%5 = or i64 %4, 768
store volatile i64 %5, i64* inttoptr (i64 1358954496 to i64*)
%6 = load volatile i64, i64* inttoptr (i64 1358954500 to i64*)
%7 = and i64 %6, -61441
store volatile i64 %7, i64* inttoptr (i64 1358954500 to i64*)
%8 = load volatile i64, i64* inttoptr (i64 1358954500 to i64*)
store volatile i64 %8, i64* inttoptr (i64 1358954500 to i64*)
store volatile i64 6249, i64* inttoptr (i64 1358954544 to i64*)
store volatile i64 3124, i64* inttoptr (i64 1358954548 to i64*)
%9 = load volatile i64, i64* inttoptr (i64 1358954504 to i64*)
%10 = and i64 %9, -983041
store volatile i64 %10, i64* inttoptr (i64 1358954504 to i64*)
%11 = load volatile i64, i64* inttoptr (i64 1358954504 to i64*)
%12 = or i64 %11, 720896
store volatile i64 %12, i64* inttoptr (i64 1358954504 to i64*)
%13 = load volatile i64, i64* inttoptr (i64 1358954504 to i64*)
%14 = and i64 %13, -131073
store volatile i64 %14, i64* inttoptr (i64 1358954504 to i64*)
%15 = icmp eq i32 %0, 0
br i1 %15, label %47, label %16
16: ; preds = %1
%17 = and i32 %0, 1
%18 = icmp eq i32 %17, 0
br i1 %18, label %27, label %19
19: ; preds = %16, %19
%20 = load volatile i64, i64* inttoptr (i64 1358954552 to i64*)
%21 = icmp ugt i64 %20, 3123
br i1 %21, label %19, label %22
22: ; preds = %19, %22
%23 = load volatile i64, i64* inttoptr (i64 1358954552 to i64*)
%24 = icmp ult i64 %23, 3124
br i1 %24, label %22, label %25
25: ; preds = %22
%26 = add nsw i32 %0, -1
br label %27
27: ; preds = %25, %16
%28 = phi i32 [ %0, %16 ], [ %26, %25 ]
%29 = icmp eq i32 %0, 1
br i1 %29, label %47, label %39
30: ; preds = %44, %30
%31 = load volatile i64, i64* inttoptr (i64 1358954552 to i64*)
%32 = icmp ugt i64 %31, 3123
br i1 %32, label %30, label %33
33: ; preds = %30, %33
%34 = load volatile i64, i64* inttoptr (i64 1358954552 to i64*)
%35 = icmp ult i64 %34, 3124
br i1 %35, label %33, label %36
36: ; preds = %33
%37 = add nsw i32 %40, -2
%38 = icmp eq i32 %37, 0
br i1 %38, label %47, label %39
39: ; preds = %27, %36
%40 = phi i32 [ %37, %36 ], [ %28, %27 ]
br label %41
41: ; preds = %39, %41
%42 = load volatile i64, i64* inttoptr (i64 1358954552 to i64*)
%43 = icmp ugt i64 %42, 3123
br i1 %43, label %41, label %44
44: ; preds = %41, %44
%45 = load volatile i64, i64* inttoptr (i64 1358954552 to i64*)
%46 = icmp ult i64 %45, 3124
br i1 %46, label %44, label %30
47: ; preds = %27, %36, %1
ret void
}