void NicRead16(unsigned char *buf, unsigned short len) {
  unsigned short val;
  len = (len + 1) / 2;
  while (len--) {
    val = (*((volatile unsigned short *)((0x20000000 + 4))));
    *buf++ = (unsigned char)val;
    *buf++ = (unsigned char)(val >> 8);
  }
}


x86 assembly (clang, -O0):
<NicRead16>:
push   %rbp
mov    %rsp,%rbp
mov    %si,%ax
mov    %rdi,-0x8(%rbp)
mov    %ax,-0xa(%rbp)
movzwl -0xa(%rbp),%eax
add    $0x1,%eax
mov    $0x2,%ecx
cltd
idiv   %ecx
mov    %ax,-0xa(%rbp)
mov    -0xa(%rbp),%ax
mov    %ax,%cx
add    $0xffff,%cx
mov    %cx,-0xa(%rbp)
cmp    $0x0,%ax
je     117d <NicRead16+0x7d>
mov    $0x20000004,%eax
mov    (%rax),%ax
mov    %ax,-0xc(%rbp)
mov    -0xc(%rbp),%ax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x8(%rbp)
mov    %cl,(%rax)
movzwl -0xc(%rbp),%eax
sar    $0x8,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x8(%rbp)
mov    %cl,(%rax)
jmp    1122 <NicRead16+0x22>
pop    %rbp
ret

x86 assembly (clang, -O2):
<NicRead16>:
lea    0x1(%rsi),%eax
shr    %eax
je     118c <NicRead16+0x8c>
lea    -0x1(%rax),%r8d
test   $0x3,%al
je     1142 <NicRead16+0x42>
and    $0x3,%eax
xor    %edx,%edx
nopl   0x0(%rax,%rax,1)
movzwl 0x20000004,%ecx
20
mov    %cx,(%rdi)
add    $0x2,%rdi
add    $0x1,%rdx
cmp    %dx,%ax
jne    1120 <NicRead16+0x20>
movzwl %si,%eax
add    $0x1,%eax
shr    %eax
sub    %edx,%eax
cmp    $0x3,%r8w
jb     118c <NicRead16+0x8c>
movzwl %ax,%eax
xor    %ecx,%ecx
xchg   %ax,%ax
movzwl 0x20000004,%edx
20
mov    %dx,(%rdi,%rcx,2)
movzwl 0x20000004,%edx
20
mov    %dx,0x2(%rdi,%rcx,2)
movzwl 0x20000004,%edx
20
mov    %dx,0x4(%rdi,%rcx,2)
movzwl 0x20000004,%edx
20
mov    %dx,0x6(%rdi,%rcx,2)
add    $0x4,%rcx
cmp    %cx,%ax
jne    1150 <NicRead16+0x50>
ret

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

LLVM IR (-O2):
define void @NicRead16(i8* nocapture writeonly %0, i16 zeroext %1) {
%3 = zext i16 %1 to i32
%4 = add nuw nsw i32 %3, 1
%5 = lshr i32 %4, 1
%6 = trunc i32 %5 to i16
%7 = icmp eq i16 %6, 0
br i1 %7, label %58, label %8
8: ; preds = %2
%9 = add i16 %6, -1
%10 = and i16 %6, 3
%11 = icmp eq i16 %10, 0
br i1 %11, label %25, label %12
12: ; preds = %8, %12
%13 = phi i8* [ %22, %12 ], [ %0, %8 ]
%14 = phi i16 [ %16, %12 ], [ %6, %8 ]
%15 = phi i16 [ %23, %12 ], [ 0, %8 ]
%16 = add i16 %14, -1
%17 = load volatile i16, i16* inttoptr (i64 536870916 to i16*)
%18 = trunc i16 %17 to i8
%19 = getelementptr inbounds i8, i8* %13, i64 1
store i8 %18, i8* %13
%20 = lshr i16 %17, 8
%21 = trunc i16 %20 to i8
%22 = getelementptr inbounds i8, i8* %13, i64 2
store i8 %21, i8* %19
%23 = add i16 %15, 1
%24 = icmp eq i16 %23, %10
br i1 %24, label %25, label %12
25: ; preds = %12, %8
%26 = phi i8* [ %0, %8 ], [ %22, %12 ]
%27 = phi i16 [ %6, %8 ], [ %16, %12 ]
%28 = icmp ult i16 %9, 3
br i1 %28, label %58, label %29
29: ; preds = %25, %29
%30 = phi i8* [ %56, %29 ], [ %26, %25 ]
%31 = phi i16 [ %50, %29 ], [ %27, %25 ]
%32 = load volatile i16, i16* inttoptr (i64 536870916 to i16*)
%33 = trunc i16 %32 to i8
%34 = getelementptr inbounds i8, i8* %30, i64 1
store i8 %33, i8* %30
%35 = lshr i16 %32, 8
%36 = trunc i16 %35 to i8
%37 = getelementptr inbounds i8, i8* %30, i64 2
store i8 %36, i8* %34
%38 = load volatile i16, i16* inttoptr (i64 536870916 to i16*)
%39 = trunc i16 %38 to i8
%40 = getelementptr inbounds i8, i8* %30, i64 3
store i8 %39, i8* %37
%41 = lshr i16 %38, 8
%42 = trunc i16 %41 to i8
%43 = getelementptr inbounds i8, i8* %30, i64 4
store i8 %42, i8* %40
%44 = load volatile i16, i16* inttoptr (i64 536870916 to i16*)
%45 = trunc i16 %44 to i8
%46 = getelementptr inbounds i8, i8* %30, i64 5
store i8 %45, i8* %43
%47 = lshr i16 %44, 8
%48 = trunc i16 %47 to i8
%49 = getelementptr inbounds i8, i8* %30, i64 6
store i8 %48, i8* %46
%50 = add i16 %31, -4
%51 = load volatile i16, i16* inttoptr (i64 536870916 to i16*)
%52 = trunc i16 %51 to i8
%53 = getelementptr inbounds i8, i8* %30, i64 7
store i8 %52, i8* %49
%54 = lshr i16 %51, 8
%55 = trunc i16 %54 to i8
%56 = getelementptr inbounds i8, i8* %30, i64 8
store i8 %55, i8* %53
%57 = icmp eq i16 %50, 0
br i1 %57, label %58, label %29
58: ; preds = %25, %29, %2
ret void
}