long SPITransfer8(unsigned long ulBase, unsigned char *ucDout,
                  unsigned char *ucDin, unsigned long ulCount,
                  unsigned long ulFlags) {
  unsigned long ulReadReg;
  unsigned long ulWriteReg;
  unsigned long ulStatReg;
  unsigned long ulOutIncr;
  unsigned long ulInIncr;
  unsigned long ulTxDummy;
  unsigned long ulRxDummy;
  ulOutIncr = 1;
  ulInIncr = 1;
  if (ucDout == 0) {
    ulOutIncr = 0;
    ulTxDummy = 0xFFFFFFFF;
    ucDout = (unsigned char *)&ulTxDummy;
  }
  if (ucDin == 0) {
    ulInIncr = 0;
    ucDin = (unsigned char *)&ulRxDummy;
  }
  ulReadReg = (ulBase + 0x0000013C);
  ulWriteReg = (ulBase + 0x00000138);
  ulStatReg = (ulBase + 0x00000130);
  if (ulFlags & 0x00000001) {
    (*((volatile unsigned long *)(ulBase + 0x0000012C))) |= 0x00100000;
  }
  while (ulCount) {
    while (!((*((volatile unsigned long *)(ulStatReg))) & 0x00000002)) {
    }
    (*((volatile unsigned long *)(ulWriteReg))) = *ucDout;
    while (!((*((volatile unsigned long *)(ulStatReg))) & 0x00000001)) {
    }
    *ucDin = (*((volatile unsigned long *)(ulReadReg)));
    ucDout = ucDout + ulOutIncr;
    ucDin = ucDin + ulInIncr;
    ulCount--;
  }
  if (ulFlags & 0x00000002) {
    (*((volatile unsigned long *)(ulBase + 0x0000012C))) &= ~0x00100000;
  }
  return 0;
}


x86 assembly (clang, -O0):
<SPITransfer8>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
movq   $0x1,-0x48(%rbp)
movq   $0x1,-0x50(%rbp)
cmpq   $0x0,-0x10(%rbp)
jne    114c <SPITransfer8+0x4c>
movq   $0x0,-0x48(%rbp)
mov    $0xffffffff,%eax
mov    %rax,-0x58(%rbp)
lea    -0x58(%rbp),%rax
mov    %rax,-0x10(%rbp)
cmpq   $0x0,-0x18(%rbp)
jne    1167 <SPITransfer8+0x67>
movq   $0x0,-0x50(%rbp)
lea    -0x60(%rbp),%rax
mov    %rax,-0x18(%rbp)
mov    -0x8(%rbp),%rax
add    $0x13c,%rax
mov    %rax,-0x30(%rbp)
mov    -0x8(%rbp),%rax
add    $0x138,%rax
mov    %rax,-0x38(%rbp)
mov    -0x8(%rbp),%rax
add    $0x130,%rax
mov    %rax,-0x40(%rbp)
mov    -0x28(%rbp),%rax
and    $0x1,%rax
cmp    $0x0,%rax
je     11bc <SPITransfer8+0xbc>
mov    -0x8(%rbp),%rax
mov    0x12c(%rax),%rcx
or     $0x100000,%rcx
mov    %rcx,0x12c(%rax)
jmp    11c1 <SPITransfer8+0xc1>
cmpq   $0x0,-0x20(%rbp)
je     1265 <SPITransfer8+0x165>
jmp    11d1 <SPITransfer8+0xd1>
mov    -0x40(%rbp),%rax
mov    (%rax),%rax
and    $0x2,%rax
cmp    $0x0,%rax
setne  %al
xor    $0xff,%al
test   $0x1,%al
jne    11f2 <SPITransfer8+0xf2>
jmp    11f7 <SPITransfer8+0xf7>
jmp    11d1 <SPITransfer8+0xd1>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
mov    %eax,%ecx
mov    -0x38(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x40(%rbp),%rax
mov    (%rax),%rax
and    $0x1,%rax
cmp    $0x0,%rax
setne  %al
xor    $0xff,%al
test   $0x1,%al
jne    1228 <SPITransfer8+0x128>
jmp    122d <SPITransfer8+0x12d>
jmp    1207 <SPITransfer8+0x107>
mov    -0x30(%rbp),%rax
mov    (%rax),%rax
mov    %al,%cl
mov    -0x18(%rbp),%rax
mov    %cl,(%rax)
mov    -0x10(%rbp),%rax
add    -0x48(%rbp),%rax
mov    %rax,-0x10(%rbp)
mov    -0x18(%rbp),%rax
add    -0x50(%rbp),%rax
mov    %rax,-0x18(%rbp)
mov    -0x20(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x20(%rbp)
jmp    11c1 <SPITransfer8+0xc1>
mov    -0x28(%rbp),%rax
and    $0x2,%rax
cmp    $0x0,%rax
je     1290 <SPITransfer8+0x190>
mov    -0x8(%rbp),%rax
mov    0x12c(%rax),%rcx
and    $0xffffffffffefffff,%rcx
mov    %rcx,0x12c(%rax)
xor    %eax,%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<SPITransfer8>:
mov    $0x1,%r9d
test   %rsi,%rsi
jne    111d <SPITransfer8+0x1d>
lea    -0x10(%rsp),%rsi
mov    $0xffffffff,%eax
mov    %rax,-0x10(%rsp)
xor    %r9d,%r9d
xor    %r10d,%r10d
test   %rdx,%rdx
setne  %r11b
lea    -0x8(%rsp),%rax
cmovne %rdx,%rax
test   $0x1,%r8b
je     1141 <SPITransfer8+0x41>
orq    $0x100000,0x12c(%rdi)
test   %rcx,%rcx
je     1192 <SPITransfer8+0x92>
mov    %r11b,%r10b
nopl   0x0(%rax)
testq  $0x2,0x130(%rdi)
je     1150 <SPITransfer8+0x50>
movzbl (%rsi),%edx
mov    %rdx,0x138(%rdi)
nopw   0x0(%rax,%rax,1)
testq  $0x1,0x130(%rdi)
je     1170 <SPITransfer8+0x70>
mov    0x13c(%rdi),%rdx
mov    %dl,(%rax)
add    %r9,%rsi
add    %r10,%rax
add    $0xffffffffffffffff,%rcx
jne    1150 <SPITransfer8+0x50>
test   $0x2,%r8b
je     11a3 <SPITransfer8+0xa3>
andq   $0xffffffffffefffff,0x12c(%rdi)
ff ff ef ff
xor    %eax,%eax
ret

LLVM IR (-O0):
define i64 @SPITransfer8(i64 %0, i8* %1, i8* %2, i64 %3, i64 %4) {
%6 = alloca i64
%7 = alloca i8*
%8 = alloca i8*
%9 = alloca i64
%10 = alloca i64
%11 = alloca i64
%12 = alloca i64
%13 = alloca i64
%14 = alloca i64
%15 = alloca i64
%16 = alloca i64
%17 = alloca i64
store i64 %0, i64* %6
store i8* %1, i8** %7
store i8* %2, i8** %8
store i64 %3, i64* %9
store i64 %4, i64* %10
store i64 1, i64* %14
store i64 1, i64* %15
%18 = load i8*, i8** %7
%19 = icmp eq i8* %18, null
br i1 %19, label %20, label %22
20: ; preds = %5
store i64 0, i64* %14
store i64 4294967295, i64* %16
%21 = bitcast i64* %16 to i8*
store i8* %21, i8** %7
br label %22
22: ; preds = %20, %5
%23 = load i8*, i8** %8
%24 = icmp eq i8* %23, null
br i1 %24, label %25, label %27
25: ; preds = %22
store i64 0, i64* %15
%26 = bitcast i64* %17 to i8*
store i8* %26, i8** %8
br label %27
27: ; preds = %25, %22
%28 = load i64, i64* %6
%29 = add i64 %28, 316
store i64 %29, i64* %11
%30 = load i64, i64* %6
%31 = add i64 %30, 312
store i64 %31, i64* %12
%32 = load i64, i64* %6
%33 = add i64 %32, 304
store i64 %33, i64* %13
%34 = load i64, i64* %10
%35 = and i64 %34, 1
%36 = icmp ne i64 %35, 0
br i1 %36, label %37, label %43
37: ; preds = %27
%38 = load i64, i64* %6
%39 = add i64 %38, 300
%40 = inttoptr i64 %39 to i64*
%41 = load volatile i64, i64* %40
%42 = or i64 %41, 1048576
store volatile i64 %42, i64* %40
br label %43
43: ; preds = %37, %27
br label %44
44: ; preds = %70, %43
%45 = load i64, i64* %9
%46 = icmp ne i64 %45, 0
br i1 %46, label %47, label %84
47: ; preds = %44
br label %48
48: ; preds = %55, %47
%49 = load i64, i64* %13
%50 = inttoptr i64 %49 to i64*
%51 = load volatile i64, i64* %50
%52 = and i64 %51, 2
%53 = icmp ne i64 %52, 0
%54 = xor i1 %53, true
br i1 %54, label %55, label %56
55: ; preds = %48
br label %48
56: ; preds = %48
%57 = load i8*, i8** %7
%58 = load i8, i8* %57
%59 = zext i8 %58 to i64
%60 = load i64, i64* %12
%61 = inttoptr i64 %60 to i64*
store volatile i64 %59, i64* %61
br label %62
62: ; preds = %69, %56
%63 = load i64, i64* %13
%64 = inttoptr i64 %63 to i64*
%65 = load volatile i64, i64* %64
%66 = and i64 %65, 1
%67 = icmp ne i64 %66, 0
%68 = xor i1 %67, true
br i1 %68, label %69, label %70
69: ; preds = %62
br label %62
70: ; preds = %62
%71 = load i64, i64* %11
%72 = inttoptr i64 %71 to i64*
%73 = load volatile i64, i64* %72
%74 = trunc i64 %73 to i8
%75 = load i8*, i8** %8
store i8 %74, i8* %75
%76 = load i8*, i8** %7
%77 = load i64, i64* %14
%78 = getelementptr inbounds i8, i8* %76, i64 %77
store i8* %78, i8** %7
%79 = load i8*, i8** %8
%80 = load i64, i64* %15
%81 = getelementptr inbounds i8, i8* %79, i64 %80
store i8* %81, i8** %8
%82 = load i64, i64* %9
%83 = add i64 %82, -1
store i64 %83, i64* %9
br label %44
84: ; preds = %44
%85 = load i64, i64* %10
%86 = and i64 %85, 2
%87 = icmp ne i64 %86, 0
br i1 %87, label %88, label %94
88: ; preds = %84
%89 = load i64, i64* %6
%90 = add i64 %89, 300
%91 = inttoptr i64 %90 to i64*
%92 = load volatile i64, i64* %91
%93 = and i64 %92, -1048577
store volatile i64 %93, i64* %91
br label %94
94: ; preds = %88, %84
ret i64 0
}

LLVM IR (-O2):
define i64 @SPITransfer8(i64 %0, i8* %1, i8* writeonly %2, i64 %3, i64 %4) {
%6 = alloca i64
%7 = alloca i64
%8 = bitcast i64* %6 to i8*
%9 = bitcast i64* %7 to i8*
%10 = icmp eq i8* %1, null
br i1 %10, label %11, label %12
11: ; preds = %5
store i64 4294967295, i64* %6
br label %12
12: ; preds = %11, %5
%13 = phi i8* [ %8, %11 ], [ %1, %5 ]
%14 = phi i64 [ 0, %11 ], [ 1, %5 ]
%15 = icmp eq i8* %2, null
%16 = select i1 %15, i8* %9, i8* %2
%17 = xor i1 %15, true
%18 = zext i1 %17 to i64
%19 = add i64 %0, 316
%20 = add i64 %0, 312
%21 = add i64 %0, 304
%22 = and i64 %4, 1
%23 = icmp eq i64 %22, 0
br i1 %23, label %29, label %24
24: ; preds = %12
%25 = add i64 %0, 300
%26 = inttoptr i64 %25 to i64*
%27 = load volatile i64, i64* %26
%28 = or i64 %27, 1048576
store volatile i64 %28, i64* %26
br label %29
29: ; preds = %24, %12
%30 = icmp eq i64 %3, 0
br i1 %30, label %57, label %31
31: ; preds = %29
%32 = inttoptr i64 %21 to i64*
%33 = inttoptr i64 %20 to i64*
%34 = inttoptr i64 %19 to i64*
br label %35
35: ; preds = %31, %50
%36 = phi i8* [ %13, %31 ], [ %53, %50 ]
%37 = phi i8* [ %16, %31 ], [ %54, %50 ]
%38 = phi i64 [ %3, %31 ], [ %55, %50 ]
br label %39
39: ; preds = %35, %39
%40 = load volatile i64, i64* %32
%41 = and i64 %40, 2
%42 = icmp eq i64 %41, 0
br i1 %42, label %39, label %43
43: ; preds = %39
%44 = load i8, i8* %36
%45 = zext i8 %44 to i64
store volatile i64 %45, i64* %33
br label %46
46: ; preds = %46, %43
%47 = load volatile i64, i64* %32
%48 = and i64 %47, 1
%49 = icmp eq i64 %48, 0
br i1 %49, label %46, label %50
50: ; preds = %46
%51 = load volatile i64, i64* %34
%52 = trunc i64 %51 to i8
store i8 %52, i8* %37
%53 = getelementptr inbounds i8, i8* %36, i64 %14
%54 = getelementptr inbounds i8, i8* %37, i64 %18
%55 = add i64 %38, -1
%56 = icmp eq i64 %55, 0
br i1 %56, label %57, label %35
57: ; preds = %50, %29
%58 = and i64 %4, 2
%59 = icmp eq i64 %58, 0
br i1 %59, label %65, label %60
60: ; preds = %57
%61 = add i64 %0, 300
%62 = inttoptr i64 %61 to i64*
%63 = load volatile i64, i64* %62
%64 = and i64 %63, -1048577
store volatile i64 %64, i64* %62
br label %65
65: ; preds = %60, %57
ret i64 0
}