void nand_erase_block(unsigned int start) {
  (*(volatile unsigned int *)(0x70200004)) &= ~2;
  (*(volatile unsigned int *)(0x70200008)) = 0x60;
  int page = start / 4096;
  (*(volatile unsigned int *)(0x7020000C)) = page & 0xFF;
  (*(volatile unsigned int *)(0x7020000C)) = (page >> 8) & 0xFF;
  (*(volatile unsigned int *)(0x7020000C)) = (page >> 16) & 0xFF;
  (*(volatile unsigned int *)(0x70200008)) = 0xD0;
  while (1) {
    if ((*(volatile unsigned int *)(0x70200028)) & 1)
      break;
  }
  (*(volatile unsigned int *)(0x70200004)) |= 2;
  return;
}


x86 assembly (clang, -O0):
<nand_erase_block>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    $0x70200004,%eax
mov    (%rax),%ecx
and    $0xfffffffd,%ecx
mov    $0x70200004,%eax
mov    %ecx,(%rax)
mov    $0x70200008,%eax
movl   $0x60,(%rax)
mov    -0x4(%rbp),%eax
shr    $0xc,%eax
mov    %eax,-0x8(%rbp)
mov    -0x8(%rbp),%ecx
and    $0xff,%ecx
mov    $0x7020000c,%eax
mov    %ecx,(%rax)
mov    -0x8(%rbp),%ecx
sar    $0x8,%ecx
and    $0xff,%ecx
mov    $0x7020000c,%eax
mov    %ecx,(%rax)
mov    -0x8(%rbp),%ecx
sar    $0x10,%ecx
and    $0xff,%ecx
mov    $0x7020000c,%eax
mov    %ecx,(%rax)
mov    $0x70200008,%eax
movl   $0xd0,(%rax)
mov    $0x70200028,%eax
mov    (%rax),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     1185 <nand_erase_block+0x85>
jmp    118a <nand_erase_block+0x8a>
jmp    116d <nand_erase_block+0x6d>
mov    $0x70200004,%eax
mov    (%rax),%ecx
or     $0x2,%ecx
mov    $0x70200004,%eax
mov    %ecx,(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<nand_erase_block>:
andl   $0xfffffffd,0x70200004
fd
movl   $0x60,0x70200008
mov    %edi,%eax
shr    $0xc,%eax
movzbl %al,%eax
mov    %eax,0x7020000c
mov    %edi,%eax
shr    $0x14,%eax
movzbl %al,%eax
mov    %eax,0x7020000c
shr    $0x1c,%edi
mov    %edi,0x7020000c
movl   $0xd0,0x70200008
cs nopw 0x0(%rax,%rax,1)
testl  $0x1,0x70200028
je     1150 <nand_erase_block+0x50>
orl    $0x2,0x70200004
02
ret

LLVM IR (-O0):
define void @nand_erase_block(i32 %0) {
%2 = alloca i32
%3 = alloca i32
store i32 %0, i32* %2
%4 = load volatile i32, i32* inttoptr (i64 1881145348 to i32*)
%5 = and i32 %4, -3
store volatile i32 %5, i32* inttoptr (i64 1881145348 to i32*)
store volatile i32 96, i32* inttoptr (i64 1881145352 to i32*)
%6 = load i32, i32* %2
%7 = udiv i32 %6, 4096
store i32 %7, i32* %3
%8 = load i32, i32* %3
%9 = and i32 %8, 255
store volatile i32 %9, i32* inttoptr (i64 1881145356 to i32*)
%10 = load i32, i32* %3
%11 = ashr i32 %10, 8
%12 = and i32 %11, 255
store volatile i32 %12, i32* inttoptr (i64 1881145356 to i32*)
%13 = load i32, i32* %3
%14 = ashr i32 %13, 16
%15 = and i32 %14, 255
store volatile i32 %15, i32* inttoptr (i64 1881145356 to i32*)
store volatile i32 208, i32* inttoptr (i64 1881145352 to i32*)
br label %16
16: ; preds = %1, %21
%17 = load volatile i32, i32* inttoptr (i64 1881145384 to i32*)
%18 = and i32 %17, 1
%19 = icmp ne i32 %18, 0
br i1 %19, label %20, label %21
20: ; preds = %16
br label %22
21: ; preds = %16
br label %16
22: ; preds = %20
%23 = load volatile i32, i32* inttoptr (i64 1881145348 to i32*)
%24 = or i32 %23, 2
store volatile i32 %24, i32* inttoptr (i64 1881145348 to i32*)
ret void
}

LLVM IR (-O2):
define void @nand_erase_block(i32 %0) {
%2 = load volatile i32, i32* inttoptr (i64 1881145348 to i32*)
%3 = and i32 %2, -3
store volatile i32 %3, i32* inttoptr (i64 1881145348 to i32*)
store volatile i32 96, i32* inttoptr (i64 1881145352 to i32*)
%4 = lshr i32 %0, 12
%5 = and i32 %4, 255
store volatile i32 %5, i32* inttoptr (i64 1881145356 to i32*)
%6 = lshr i32 %0, 20
%7 = and i32 %6, 255
store volatile i32 %7, i32* inttoptr (i64 1881145356 to i32*)
%8 = lshr i32 %0, 28
store volatile i32 %8, i32* inttoptr (i64 1881145356 to i32*)
store volatile i32 208, i32* inttoptr (i64 1881145352 to i32*)
br label %9
9: ; preds = %9, %1
%10 = load volatile i32, i32* inttoptr (i64 1881145384 to i32*)
%11 = and i32 %10, 1
%12 = icmp eq i32 %11, 0
br i1 %12, label %9, label %13
13: ; preds = %9
%14 = load volatile i32, i32* inttoptr (i64 1881145348 to i32*)
%15 = or i32 %14, 2
store volatile i32 %15, i32* inttoptr (i64 1881145348 to i32*)
ret void
}