void uart_set_speed(unsigned int uart, unsigned int speed) {
  unsigned int i = 0;
  if (!uart) {
    i = *((volatile unsigned int *)(0xF1000000 + 0x14)) & 0xFF;
    i |= (speed >> 16);
    *((volatile unsigned int *)(0xF1000000 + 0x14)) = i;
    i = ((speed << 16) >> 16);
    *((volatile unsigned int *)(0xF1000000 + 0x18)) = i;
  } else {
    i = *((volatile unsigned int *)(0xF1800000 + 0x14)) & 0xFF;
    i |= (speed >> 16);
    *((volatile unsigned int *)(0xF1800000 + 0x14)) = i;
    i = ((speed << 16) >> 16);
    *((volatile unsigned int *)(0xF1800000 + 0x18)) = i;
  }
}


x86 assembly (clang, -O0):
<uart_set_speed>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
movl   $0x0,-0xc(%rbp)
cmpl   $0x0,-0x4(%rbp)
jne    115b <uart_set_speed+0x5b>
mov    $0xf1000014,%eax
mov    (%rax),%eax
and    $0xff,%eax
mov    %eax,-0xc(%rbp)
mov    -0x8(%rbp),%eax
shr    $0x10,%eax
or     -0xc(%rbp),%eax
mov    %eax,-0xc(%rbp)
mov    -0xc(%rbp),%ecx
mov    $0xf1000014,%eax
mov    %ecx,(%rax)
mov    -0x8(%rbp),%eax
shl    $0x10,%eax
shr    $0x10,%eax
mov    %eax,-0xc(%rbp)
mov    -0xc(%rbp),%ecx
mov    $0xf1000018,%eax
mov    %ecx,(%rax)
jmp    1196 <uart_set_speed+0x96>
mov    $0xf1800014,%eax
mov    (%rax),%eax
and    $0xff,%eax
mov    %eax,-0xc(%rbp)
mov    -0x8(%rbp),%eax
shr    $0x10,%eax
or     -0xc(%rbp),%eax
mov    %eax,-0xc(%rbp)
mov    -0xc(%rbp),%ecx
mov    $0xf1800014,%eax
mov    %ecx,(%rax)
mov    -0x8(%rbp),%eax
shl    $0x10,%eax
shr    $0x10,%eax
mov    %eax,-0xc(%rbp)
mov    -0xc(%rbp),%ecx
mov    $0xf1800018,%eax
mov    %ecx,(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<uart_set_speed>:
mov    $0xf1000014,%r8d
lea    0x800000(%r8),%rcx
xor    %edx,%edx
test   %edi,%edi
setne  %dl
cmove  %r8,%rcx
shl    $0x17,%rdx
mov    (%rcx),%edi
movzbl %dil,%edi
movzwl %si,%eax
shr    $0x10,%esi
or     %edi,%esi
mov    %esi,(%rcx)
mov    %eax,0x4(%rdx,%r8,1)
ret

LLVM IR (-O0):
define void @uart_set_speed(i32 %0, i32 %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca i32
store i32 %0, i32* %3
store i32 %1, i32* %4
store i32 0, i32* %5
%6 = load i32, i32* %3
%7 = icmp ne i32 %6, 0
br i1 %7, label %20, label %8
8: ; preds = %2
%9 = load volatile i32, i32* inttoptr (i64 4043309076 to i32*)
%10 = and i32 %9, 255
store i32 %10, i32* %5
%11 = load i32, i32* %4
%12 = lshr i32 %11, 16
%13 = load i32, i32* %5
%14 = or i32 %13, %12
store i32 %14, i32* %5
%15 = load i32, i32* %5
store volatile i32 %15, i32* inttoptr (i64 4043309076 to i32*)
%16 = load i32, i32* %4
%17 = shl i32 %16, 16
%18 = lshr i32 %17, 16
store i32 %18, i32* %5
%19 = load i32, i32* %5
store volatile i32 %19, i32* inttoptr (i64 4043309080 to i32*)
br label %32
20: ; preds = %2
%21 = load volatile i32, i32* inttoptr (i64 4051697684 to i32*)
%22 = and i32 %21, 255
store i32 %22, i32* %5
%23 = load i32, i32* %4
%24 = lshr i32 %23, 16
%25 = load i32, i32* %5
%26 = or i32 %25, %24
store i32 %26, i32* %5
%27 = load i32, i32* %5
store volatile i32 %27, i32* inttoptr (i64 4051697684 to i32*)
%28 = load i32, i32* %4
%29 = shl i32 %28, 16
%30 = lshr i32 %29, 16
store i32 %30, i32* %5
%31 = load i32, i32* %5
store volatile i32 %31, i32* inttoptr (i64 4051697688 to i32*)
br label %32
32: ; preds = %20, %8
ret void
}

LLVM IR (-O2):
define void @uart_set_speed(i32 %0, i32 %1) {
%3 = icmp eq i32 %0, 0
%4 = select i1 %3, i32* inttoptr (i64 4043309076 to i32*), i32* inttoptr (i64 4051697684 to i32*)
%5 = select i1 %3, i32* inttoptr (i64 4043309080 to i32*), i32* inttoptr (i64 4051697688 to i32*)
%6 = load volatile i32, i32* %4
%7 = and i32 %6, 255
%8 = lshr i32 %1, 16
%9 = or i32 %7, %8
store volatile i32 %9, i32* %4
%10 = and i32 %1, 65535
store volatile i32 %10, i32* %5
ret void
}