unsigned short norflash_read(unsigned long src, unsigned short *dst,
                             unsigned short length) {
  unsigned long i;
  unsigned short *psrc16 = (unsigned short *)(src + 0x400000);
  unsigned short *pdst16 = (unsigned short *)dst;
  *(volatile unsigned short *)(0x0400000) = 0xFF;
  for (i = 0; i < length; i++)
    *pdst16++ = *psrc16++;
  return 0;
}


x86 assembly (clang, -O0):
<norflash_read>:
push   %rbp
mov    %rsp,%rbp
mov    %dx,%ax
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %ax,-0x12(%rbp)
mov    -0x8(%rbp),%rax
add    $0x400000,%rax
mov    %rax,-0x28(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x30(%rbp)
mov    $0x400000,%eax
movw   $0xff,(%rax)
movq   $0x0,-0x20(%rbp)
mov    -0x20(%rbp),%rax
movzwl -0x12(%rbp),%ecx
cmp    %rcx,%rax
jae    1181 <norflash_read+0x81>
mov    -0x28(%rbp),%rax
mov    %rax,%rcx
add    $0x2,%rcx
mov    %rcx,-0x28(%rbp)
mov    (%rax),%cx
mov    -0x30(%rbp),%rax
mov    %rax,%rdx
add    $0x2,%rdx
mov    %rdx,-0x30(%rbp)
mov    %cx,(%rax)
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
jmp    113b <norflash_read+0x3b>
xor    %eax,%eax
movzwl %ax,%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<norflash_read>:
movw   $0xff,0x400000
test   %edx,%edx
je     12c0 <norflash_read+0x1c0>
mov    %edx,%r10d
add    $0x400000,%rdi
cmp    $0x10,%dx
jb     113c <norflash_read+0x3c>
lea    (%rdi,%r10,2),%rax
cmp    %rsi,%rax
jbe    11ec <norflash_read+0xec>
lea    (%rsi,%r10,2),%rax
cmp    %rax,%rdi
jae    11ec <norflash_read+0xec>
xor    %r8d,%r8d
mov    %r8,%r9
not    %r9
add    %r10,%r9
mov    %r10,%rcx
and    $0x7,%rcx
je     117a <norflash_read+0x7a>
neg    %rcx
xor    %edx,%edx
cs nopw 0x0(%rax,%rax,1)
movzwl (%rdi),%eax
add    $0x2,%rdi
mov    %ax,(%rsi)
add    $0x2,%rsi
add    $0xffffffffffffffff,%rdx
cmp    %rdx,%rcx
jne    1160 <norflash_read+0x60>
sub    %rdx,%r8
cmp    $0x7,%r9
jb     12c0 <norflash_read+0x1c0>
sub    %r8,%r10
xor    %ecx,%ecx
nopl   0x0(%rax)
movzwl (%rdi,%rcx,2),%eax
mov    %ax,(%rsi,%rcx,2)
movzwl 0x2(%rdi,%rcx,2),%eax
mov    %ax,0x2(%rsi,%rcx,2)
movzwl 0x4(%rdi,%rcx,2),%eax
mov    %ax,0x4(%rsi,%rcx,2)
movzwl 0x6(%rdi,%rcx,2),%eax
mov    %ax,0x6(%rsi,%rcx,2)
movzwl 0x8(%rdi,%rcx,2),%eax
mov    %ax,0x8(%rsi,%rcx,2)
movzwl 0xa(%rdi,%rcx,2),%eax
mov    %ax,0xa(%rsi,%rcx,2)
movzwl 0xc(%rdi,%rcx,2),%eax
mov    %ax,0xc(%rsi,%rcx,2)
movzwl 0xe(%rdi,%rcx,2),%eax
mov    %ax,0xe(%rsi,%rcx,2)
add    $0x8,%rcx
cmp    %rcx,%r10
jne    1190 <norflash_read+0x90>
jmp    12c0 <norflash_read+0x1c0>
mov    %r10d,%r8d
and    $0xfffffff0,%r8d
lea    -0x10(%r8),%rax
mov    %rax,%rdx
shr    $0x4,%rdx
add    $0x1,%rdx
mov    %edx,%r9d
and    $0x3,%r9d
cmp    $0x30,%rax
jae    1213 <norflash_read+0x113>
xor    %ecx,%ecx
jmp    1278 <norflash_read+0x178>
and    $0xfffffffffffffffc,%rdx
xor    %ecx,%ecx
nopl   0x0(%rax)
movups (%rdi,%rcx,2),%xmm0
movups 0x10(%rdi,%rcx,2),%xmm1
movups %xmm0,(%rsi,%rcx,2)
movups %xmm1,0x10(%rsi,%rcx,2)
movups 0x20(%rdi,%rcx,2),%xmm0
movups 0x30(%rdi,%rcx,2),%xmm1
movups %xmm0,0x20(%rsi,%rcx,2)
movups %xmm1,0x30(%rsi,%rcx,2)
movups 0x40(%rdi,%rcx,2),%xmm0
movups 0x50(%rdi,%rcx,2),%xmm1
movups %xmm0,0x40(%rsi,%rcx,2)
movups %xmm1,0x50(%rsi,%rcx,2)
movups 0x60(%rdi,%rcx,2),%xmm0
movups 0x70(%rdi,%rcx,2),%xmm1
movups %xmm0,0x60(%rsi,%rcx,2)
movups %xmm1,0x70(%rsi,%rcx,2)
add    $0x40,%rcx
add    $0xfffffffffffffffc,%rdx
jne    1220 <norflash_read+0x120>
test   %r9,%r9
je     12bb <norflash_read+0x1bb>
lea    (%rdi,%rcx,2),%rdx
add    $0x10,%rdx
lea    (%rsi,%rcx,2),%rcx
add    $0x10,%rcx
shl    $0x5,%r9
xor    %eax,%eax
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movups -0x10(%rdx,%rax,1),%xmm0
movups (%rdx,%rax,1),%xmm1
movups %xmm0,-0x10(%rcx,%rax,1)
movups %xmm1,(%rcx,%rax,1)
add    $0x20,%rax
cmp    %rax,%r9
jne    12a0 <norflash_read+0x1a0>
cmp    %r10,%r8
jne    12c3 <norflash_read+0x1c3>
xor    %eax,%eax
ret
lea    (%rsi,%r8,2),%rsi
lea    (%rdi,%r8,2),%rdi
jmp    113f <norflash_read+0x3f>

LLVM IR (-O0):
define zeroext i16 @norflash_read(i64 %0, i16* %1, i16 zeroext %2) {
%4 = alloca i64
%5 = alloca i16*
%6 = alloca i16
%7 = alloca i64
%8 = alloca i16*
%9 = alloca i16*
store i64 %0, i64* %4
store i16* %1, i16** %5
store i16 %2, i16* %6
%10 = load i64, i64* %4
%11 = add i64 %10, 4194304
%12 = inttoptr i64 %11 to i16*
store i16* %12, i16** %8
%13 = load i16*, i16** %5
store i16* %13, i16** %9
store volatile i16 255, i16* inttoptr (i64 4194304 to i16*)
store i64 0, i64* %7
br label %14
14: ; preds = %25, %3
%15 = load i64, i64* %7
%16 = load i16, i16* %6
%17 = zext i16 %16 to i64
%18 = icmp ult i64 %15, %17
br i1 %18, label %19, label %28
19: ; preds = %14
%20 = load i16*, i16** %8
%21 = getelementptr inbounds i16, i16* %20, i32 1
store i16* %21, i16** %8
%22 = load i16, i16* %20
%23 = load i16*, i16** %9
%24 = getelementptr inbounds i16, i16* %23, i32 1
store i16* %24, i16** %9
store i16 %22, i16* %23
br label %25
25: ; preds = %19
%26 = load i64, i64* %7
%27 = add i64 %26, 1
store i64 %27, i64* %7
br label %14
28: ; preds = %14
ret i16 0
}

LLVM IR (-O2):
define zeroext i16 @norflash_read(i64 %0, i16* nocapture writeonly %1, i16 zeroext %2) {
store volatile i16 255, i16* inttoptr (i64 4194304 to i16*)
%4 = zext i16 %2 to i64
%5 = icmp eq i16 %2, 0
br i1 %5, label %153, label %6
6: ; preds = %3
%7 = add i64 %0, 4194304
%8 = inttoptr i64 %7 to i16*
%9 = icmp ult i16 %2, 16
br i1 %9, label %99, label %10
10: ; preds = %6
%11 = inttoptr i64 %7 to i8*
%12 = getelementptr i16, i16* %1, i64 %4
%13 = bitcast i16* %12 to i8*
%14 = getelementptr i16, i16* %8, i64 %4
%15 = icmp ugt i16* %14, %1
%16 = icmp ult i8* %11, %13
%17 = and i1 %15, %16
br i1 %17, label %99, label %18
18: ; preds = %10
%19 = and i64 %4, 65520
%20 = getelementptr i16, i16* %1, i64 %19
%21 = getelementptr i16, i16* %8, i64 %19
%22 = add nsw i64 %19, -16
%23 = lshr exact i64 %22, 4
%24 = add nuw nsw i64 %23, 1
%25 = and i64 %24, 3
%26 = icmp ult i64 %22, 48
br i1 %26, label %78, label %27
27: ; preds = %18
%28 = and i64 %24, 2305843009213693948
br label %29
29: ; preds = %29, %27
%30 = phi i64 [ 0, %27 ], [ %75, %29 ]
%31 = phi i64 [ 0, %27 ], [ %76, %29 ]
%32 = getelementptr i16, i16* %1, i64 %30
%33 = getelementptr i16, i16* %8, i64 %30
%34 = bitcast i16* %33 to <8 x i16>*
%35 = load <8 x i16>, <8 x i16>* %34
%36 = getelementptr i16, i16* %33, i64 8
%37 = bitcast i16* %36 to <8 x i16>*
%38 = load <8 x i16>, <8 x i16>* %37
%39 = bitcast i16* %32 to <8 x i16>*
store <8 x i16> %35, <8 x i16>* %39
%40 = getelementptr i16, i16* %32, i64 8
%41 = bitcast i16* %40 to <8 x i16>*
store <8 x i16> %38, <8 x i16>* %41
%42 = or i64 %30, 16
%43 = getelementptr i16, i16* %1, i64 %42
%44 = getelementptr i16, i16* %8, i64 %42
%45 = bitcast i16* %44 to <8 x i16>*
%46 = load <8 x i16>, <8 x i16>* %45
%47 = getelementptr i16, i16* %44, i64 8
%48 = bitcast i16* %47 to <8 x i16>*
%49 = load <8 x i16>, <8 x i16>* %48
%50 = bitcast i16* %43 to <8 x i16>*
store <8 x i16> %46, <8 x i16>* %50
%51 = getelementptr i16, i16* %43, i64 8
%52 = bitcast i16* %51 to <8 x i16>*
store <8 x i16> %49, <8 x i16>* %52
%53 = or i64 %30, 32
%54 = getelementptr i16, i16* %1, i64 %53
%55 = getelementptr i16, i16* %8, i64 %53
%56 = bitcast i16* %55 to <8 x i16>*
%57 = load <8 x i16>, <8 x i16>* %56
%58 = getelementptr i16, i16* %55, i64 8
%59 = bitcast i16* %58 to <8 x i16>*
%60 = load <8 x i16>, <8 x i16>* %59
%61 = bitcast i16* %54 to <8 x i16>*
store <8 x i16> %57, <8 x i16>* %61
%62 = getelementptr i16, i16* %54, i64 8
%63 = bitcast i16* %62 to <8 x i16>*
store <8 x i16> %60, <8 x i16>* %63
%64 = or i64 %30, 48
%65 = getelementptr i16, i16* %1, i64 %64
%66 = getelementptr i16, i16* %8, i64 %64
%67 = bitcast i16* %66 to <8 x i16>*
%68 = load <8 x i16>, <8 x i16>* %67
%69 = getelementptr i16, i16* %66, i64 8
%70 = bitcast i16* %69 to <8 x i16>*
%71 = load <8 x i16>, <8 x i16>* %70
%72 = bitcast i16* %65 to <8 x i16>*
store <8 x i16> %68, <8 x i16>* %72
%73 = getelementptr i16, i16* %65, i64 8
%74 = bitcast i16* %73 to <8 x i16>*
store <8 x i16> %71, <8 x i16>* %74
%75 = add nuw i64 %30, 64
%76 = add i64 %31, 4
%77 = icmp eq i64 %76, %28
br i1 %77, label %78, label %29
78: ; preds = %29, %18
%79 = phi i64 [ 0, %18 ], [ %75, %29 ]
%80 = icmp eq i64 %25, 0
br i1 %80, label %97, label %81
81: ; preds = %78, %81
%82 = phi i64 [ %94, %81 ], [ %79, %78 ]
%83 = phi i64 [ %95, %81 ], [ 0, %78 ]
%84 = getelementptr i16, i16* %1, i64 %82
%85 = getelementptr i16, i16* %8, i64 %82
%86 = bitcast i16* %85 to <8 x i16>*
%87 = load <8 x i16>, <8 x i16>* %86
%88 = getelementptr i16, i16* %85, i64 8
%89 = bitcast i16* %88 to <8 x i16>*
%90 = load <8 x i16>, <8 x i16>* %89
%91 = bitcast i16* %84 to <8 x i16>*
store <8 x i16> %87, <8 x i16>* %91
%92 = getelementptr i16, i16* %84, i64 8
%93 = bitcast i16* %92 to <8 x i16>*
store <8 x i16> %90, <8 x i16>* %93
%94 = add nuw i64 %82, 16
%95 = add i64 %83, 1
%96 = icmp eq i64 %95, %25
br i1 %96, label %97, label %81
97: ; preds = %81, %78
%98 = icmp eq i64 %19, %4
br i1 %98, label %153, label %99
99: ; preds = %10, %6, %97
%100 = phi i16* [ %1, %10 ], [ %1, %6 ], [ %20, %97 ]
%101 = phi i16* [ %8, %10 ], [ %8, %6 ], [ %21, %97 ]
%102 = phi i64 [ 0, %10 ], [ 0, %6 ], [ %19, %97 ]
%103 = xor i64 %102, -1
%104 = add nsw i64 %103, %4
%105 = and i64 %4, 7
%106 = icmp eq i64 %105, 0
br i1 %106, label %118, label %107
107: ; preds = %99, %107
%108 = phi i16* [ %114, %107 ], [ %100, %99 ]
%109 = phi i16* [ %112, %107 ], [ %101, %99 ]
%110 = phi i64 [ %115, %107 ], [ %102, %99 ]
%111 = phi i64 [ %116, %107 ], [ 0, %99 ]
%112 = getelementptr inbounds i16, i16* %109, i64 1
%113 = load i16, i16* %109
%114 = getelementptr inbounds i16, i16* %108, i64 1
store i16 %113, i16* %108
%115 = add nuw nsw i64 %110, 1
%116 = add i64 %111, 1
%117 = icmp eq i64 %116, %105
br i1 %117, label %118, label %107
118: ; preds = %107, %99
%119 = phi i16* [ %100, %99 ], [ %114, %107 ]
%120 = phi i16* [ %101, %99 ], [ %112, %107 ]
%121 = phi i64 [ %102, %99 ], [ %115, %107 ]
%122 = icmp ult i64 %104, 7
br i1 %122, label %153, label %123
123: ; preds = %118, %123
%124 = phi i16* [ %150, %123 ], [ %119, %118 ]
%125 = phi i16* [ %148, %123 ], [ %120, %118 ]
%126 = phi i64 [ %151, %123 ], [ %121, %118 ]
%127 = getelementptr inbounds i16, i16* %125, i64 1
%128 = load i16, i16* %125
%129 = getelementptr inbounds i16, i16* %124, i64 1
store i16 %128, i16* %124
%130 = getelementptr inbounds i16, i16* %125, i64 2
%131 = load i16, i16* %127
%132 = getelementptr inbounds i16, i16* %124, i64 2
store i16 %131, i16* %129
%133 = getelementptr inbounds i16, i16* %125, i64 3
%134 = load i16, i16* %130
%135 = getelementptr inbounds i16, i16* %124, i64 3
store i16 %134, i16* %132
%136 = getelementptr inbounds i16, i16* %125, i64 4
%137 = load i16, i16* %133
%138 = getelementptr inbounds i16, i16* %124, i64 4
store i16 %137, i16* %135
%139 = getelementptr inbounds i16, i16* %125, i64 5
%140 = load i16, i16* %136
%141 = getelementptr inbounds i16, i16* %124, i64 5
store i16 %140, i16* %138
%142 = getelementptr inbounds i16, i16* %125, i64 6
%143 = load i16, i16* %139
%144 = getelementptr inbounds i16, i16* %124, i64 6
store i16 %143, i16* %141
%145 = getelementptr inbounds i16, i16* %125, i64 7
%146 = load i16, i16* %142
%147 = getelementptr inbounds i16, i16* %124, i64 7
store i16 %146, i16* %144
%148 = getelementptr inbounds i16, i16* %125, i64 8
%149 = load i16, i16* %145
%150 = getelementptr inbounds i16, i16* %124, i64 8
store i16 %149, i16* %147
%151 = add nuw nsw i64 %126, 8
%152 = icmp eq i64 %151, %4
br i1 %152, label %153, label %123
153: ; preds = %118, %123, %97, %3
ret i16 0
}