#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
void putc(char c) {
  (*(volatile unsigned long *)(0x2002c08c)) |= (0x1 << 22);
  (*(volatile unsigned long *)(0x48001300)) = (unsigned long)c;
  (*(volatile unsigned long *)(0x48001300 + 60)) = (unsigned long)'\0';
  (*(volatile unsigned long *)(0x20029000 + 0x0)) |= (0x1 << 28);
  (*(volatile unsigned long *)(0x20029000 + 0x4)) |= (1 << 4) | (0x1 << 16);
  while (((*(volatile unsigned long *)(0x20029000 + 0x4)) & (1 << 19)) == 0) {
  }
}


x86 assembly (clang, -O0):
<putc>:
push   %rbp
mov    %rsp,%rbp
mov    %dil,%al
mov    %al,-0x1(%rbp)
mov    $0x2002c08c,%eax
mov    (%rax),%rcx
or     $0x400000,%rcx
mov    $0x2002c08c,%eax
mov    %rcx,(%rax)
movsbq -0x1(%rbp),%rcx
mov    $0x48001300,%eax
mov    %rcx,(%rax)
mov    $0x4800133c,%eax
movq   $0x0,(%rax)
mov    $0x20029000,%eax
mov    (%rax),%rcx
or     $0x10000000,%rcx
mov    $0x20029000,%eax
mov    %rcx,(%rax)
mov    $0x20029004,%eax
mov    (%rax),%rcx
or     $0x10010,%rcx
mov    $0x20029004,%eax
mov    %rcx,(%rax)
mov    $0x20029004,%eax
mov    (%rax),%rax
and    $0x80000,%rax
cmp    $0x0,%rax
jne    1185 <putc+0x85>
jmp    1168 <putc+0x68>
pop    %rbp
ret

x86 assembly (clang, -O2):
<putc>:
orq    $0x400000,0x2002c08c
movslq %edi,%rax
mov    %rax,0x48001300
48
movq   $0x0,0x4800133c
orq    $0x10000000,0x20029000
orq    $0x10010,0x20029004
nopl   0x0(%rax,%rax,1)
testq  $0x80000,0x20029004
je     1140 <putc+0x40>
ret

LLVM IR (-O0):
define void @putc(i8 signext %0) {
%2 = alloca i8
store i8 %0, i8* %2
%3 = load volatile i64, i64* inttoptr (i64 537051276 to i64*)
%4 = or i64 %3, 4194304
store volatile i64 %4, i64* inttoptr (i64 537051276 to i64*)
%5 = load i8, i8* %2
%6 = sext i8 %5 to i64
store volatile i64 %6, i64* inttoptr (i64 1207964416 to i64*)
store volatile i64 0, i64* inttoptr (i64 1207964476 to i64*)
%7 = load volatile i64, i64* inttoptr (i64 537038848 to i64*)
%8 = or i64 %7, 268435456
store volatile i64 %8, i64* inttoptr (i64 537038848 to i64*)
%9 = load volatile i64, i64* inttoptr (i64 537038852 to i64*)
%10 = or i64 %9, 65552
store volatile i64 %10, i64* inttoptr (i64 537038852 to i64*)
br label %11
11: ; preds = %15, %1
%12 = load volatile i64, i64* inttoptr (i64 537038852 to i64*)
%13 = and i64 %12, 524288
%14 = icmp eq i64 %13, 0
br i1 %14, label %15, label %16
15: ; preds = %11
br label %11
16: ; preds = %11
ret void
}

LLVM IR (-O2):
define void @putc(i8 signext %0) {
%2 = load volatile i64, i64* inttoptr (i64 537051276 to i64*)
%3 = or i64 %2, 4194304
store volatile i64 %3, i64* inttoptr (i64 537051276 to i64*)
%4 = sext i8 %0 to i64
store volatile i64 %4, i64* inttoptr (i64 1207964416 to i64*)
store volatile i64 0, i64* inttoptr (i64 1207964476 to i64*)
%5 = load volatile i64, i64* inttoptr (i64 537038848 to i64*)
%6 = or i64 %5, 268435456
store volatile i64 %6, i64* inttoptr (i64 537038848 to i64*)
%7 = load volatile i64, i64* inttoptr (i64 537038852 to i64*)
%8 = or i64 %7, 65552
store volatile i64 %8, i64* inttoptr (i64 537038852 to i64*)
br label %9
9: ; preds = %9, %1
%10 = load volatile i64, i64* inttoptr (i64 537038852 to i64*)
%11 = and i64 %10, 524288
%12 = icmp eq i64 %11, 0
br i1 %12, label %9, label %13
13: ; preds = %9
ret void
}