#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 */
struct tm {
  unsigned long tm_hour;
  unsigned long tm_min;
  unsigned long tm_sec;
  unsigned long tm_year;
  unsigned long tm_mon;
  unsigned long tm_mday;
};
typedef struct tm u_int8_t;

/* Variables and functions */
int /*<<< orphan*/ assert(struct tm *);
unsigned long little_endian_16(struct tm *);
void parse_time(struct tm *time, u_int8_t *buf) {
  unsigned long value;
  enum {
    HOURS_MASK = 0xF8000000L,
    MINUTES_MASK = 0x07E00000L,
    SECONDS_MASK = 0x001F0000L,
    YEAR_MASK = 0x0000FE00L,
    MONTH_MASK = 0x000001E0L,
    DAY_MASK = 0x0000001FL,
    HOURS_MAG = 32 - 5,
    MINUTES_MAG = HOURS_MAG - 6,
    SECONDS_MAG = MINUTES_MAG - 5,
    YEAR_MAG = SECONDS_MAG - 7,
    MONTH_MAG = YEAR_MAG - 4,
    DAY_MAG = MONTH_MAG - 5
  };
  assert(time);
  assert(buf);
  value = little_endian_16(buf) << 16;
  value += little_endian_16(buf + 2);
  time->tm_hour = (value & HOURS_MASK) >> HOURS_MAG;
  time->tm_min = (value & MINUTES_MASK) >> MINUTES_MAG;
  time->tm_sec = (value & SECONDS_MASK) >> SECONDS_MAG;
  time->tm_sec *= 2;
  time->tm_year = (value & YEAR_MASK) >> YEAR_MAG;
  time->tm_year += 80;
  time->tm_mon = (value & MONTH_MASK) >> MONTH_MAG;
  time->tm_mon -= 1;
  time->tm_mday = (value & DAY_MASK) >> DAY_MAG;
}


x86 assembly (clang, -O0):
<parse_time>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x8(%rbp),%rdi
call   1040 <assert@plt>
mov    -0x10(%rbp),%rdi
call   1040 <assert@plt>
mov    -0x10(%rbp),%rdi
call   1030 <little_endian_16@plt>
shl    $0x10,%rax
mov    %rax,-0x18(%rbp)
mov    -0x10(%rbp),%rdi
add    $0x60,%rdi
call   1030 <little_endian_16@plt>
add    -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
movabs $0xf8000000,%rcx
and    -0x18(%rbp),%rcx
shr    $0x1b,%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x18(%rbp),%rcx
and    $0x7e00000,%rcx
shr    $0x15,%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,0x8(%rax)
mov    -0x18(%rbp),%rcx
and    $0x1f0000,%rcx
shr    $0x10,%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,0x10(%rax)
mov    -0x8(%rbp),%rax
mov    0x10(%rax),%rcx
shl    $0x1,%rcx
mov    %rcx,0x10(%rax)
mov    -0x18(%rbp),%rcx
and    $0xfe00,%rcx
shr    $0x9,%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,0x18(%rax)
mov    -0x8(%rbp),%rax
mov    0x18(%rax),%rcx
add    $0x50,%rcx
mov    %rcx,0x18(%rax)
mov    -0x18(%rbp),%rcx
and    $0x1e0,%rcx
shr    $0x5,%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,0x20(%rax)
mov    -0x8(%rbp),%rax
mov    0x20(%rax),%rcx
sub    $0x1,%rcx
mov    %rcx,0x20(%rax)
mov    -0x18(%rbp),%rcx
and    $0x1f,%rcx
shr    $0x0,%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,0x28(%rax)
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<parse_time>:
push   %r15
push   %r14
push   %rbx
mov    %rsi,%rbx
mov    %rdi,%r14
call   1040 <assert@plt>
mov    %rbx,%rdi
call   1040 <assert@plt>
mov    %rbx,%rdi
call   1030 <little_endian_16@plt>
mov    %rax,%r15
shl    $0x10,%r15
add    $0x60,%rbx
mov    %rbx,%rdi
call   1030 <little_endian_16@plt>
add    %r15,%rax
mov    %eax,%ecx
shr    $0x1b,%ecx
mov    %rcx,(%r14)
mov    %eax,%ecx
shr    $0x15,%ecx
and    $0x3f,%ecx
mov    %rcx,0x8(%r14)
mov    %rax,%rcx
shr    $0xf,%rcx
and    $0x3e,%ecx
mov    %rcx,0x10(%r14)
mov    %eax,%ecx
shr    $0x9,%ecx
and    $0x7f,%ecx
add    $0x50,%rcx
mov    %rcx,0x18(%r14)
mov    %eax,%ecx
shr    $0x5,%ecx
and    $0xf,%ecx
add    $0xffffffffffffffff,%rcx
mov    %rcx,0x20(%r14)
and    $0x1f,%eax
mov    %rax,0x28(%r14)
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
%struct.tm = type { i64, i64, i64, i64, i64, i64 }
define void @parse_time(%struct.tm* %0, %struct.tm* %1) {
%3 = alloca %struct.tm*
%4 = alloca %struct.tm*
%5 = alloca i64
store %struct.tm* %0, %struct.tm** %3
store %struct.tm* %1, %struct.tm** %4
%6 = load %struct.tm*, %struct.tm** %3
%7 = call i32 @assert(%struct.tm* %6)
%8 = load %struct.tm*, %struct.tm** %4
%9 = call i32 @assert(%struct.tm* %8)
%10 = load %struct.tm*, %struct.tm** %4
%11 = call i64 @little_endian_16(%struct.tm* %10)
%12 = shl i64 %11, 16
store i64 %12, i64* %5
%13 = load %struct.tm*, %struct.tm** %4
%14 = getelementptr inbounds %struct.tm, %struct.tm* %13, i64 2
%15 = call i64 @little_endian_16(%struct.tm* %14)
%16 = load i64, i64* %5
%17 = add i64 %16, %15
store i64 %17, i64* %5
%18 = load i64, i64* %5
%19 = and i64 %18, 4160749568
%20 = lshr i64 %19, 27
%21 = load %struct.tm*, %struct.tm** %3
%22 = getelementptr inbounds %struct.tm, %struct.tm* %21, i32 0, i32 0
store i64 %20, i64* %22
%23 = load i64, i64* %5
%24 = and i64 %23, 132120576
%25 = lshr i64 %24, 21
%26 = load %struct.tm*, %struct.tm** %3
%27 = getelementptr inbounds %struct.tm, %struct.tm* %26, i32 0, i32 1
store i64 %25, i64* %27
%28 = load i64, i64* %5
%29 = and i64 %28, 2031616
%30 = lshr i64 %29, 16
%31 = load %struct.tm*, %struct.tm** %3
%32 = getelementptr inbounds %struct.tm, %struct.tm* %31, i32 0, i32 2
store i64 %30, i64* %32
%33 = load %struct.tm*, %struct.tm** %3
%34 = getelementptr inbounds %struct.tm, %struct.tm* %33, i32 0, i32 2
%35 = load i64, i64* %34
%36 = mul i64 %35, 2
store i64 %36, i64* %34
%37 = load i64, i64* %5
%38 = and i64 %37, 65024
%39 = lshr i64 %38, 9
%40 = load %struct.tm*, %struct.tm** %3
%41 = getelementptr inbounds %struct.tm, %struct.tm* %40, i32 0, i32 3
store i64 %39, i64* %41
%42 = load %struct.tm*, %struct.tm** %3
%43 = getelementptr inbounds %struct.tm, %struct.tm* %42, i32 0, i32 3
%44 = load i64, i64* %43
%45 = add i64 %44, 80
store i64 %45, i64* %43
%46 = load i64, i64* %5
%47 = and i64 %46, 480
%48 = lshr i64 %47, 5
%49 = load %struct.tm*, %struct.tm** %3
%50 = getelementptr inbounds %struct.tm, %struct.tm* %49, i32 0, i32 4
store i64 %48, i64* %50
%51 = load %struct.tm*, %struct.tm** %3
%52 = getelementptr inbounds %struct.tm, %struct.tm* %51, i32 0, i32 4
%53 = load i64, i64* %52
%54 = sub i64 %53, 1
store i64 %54, i64* %52
%55 = load i64, i64* %5
%56 = and i64 %55, 31
%57 = lshr i64 %56, 0
%58 = load %struct.tm*, %struct.tm** %3
%59 = getelementptr inbounds %struct.tm, %struct.tm* %58, i32 0, i32 5
store i64 %57, i64* %59
ret void
}

LLVM IR (-O2):
%struct.tm = type { i64, i64, i64, i64, i64, i64 }
define void @parse_time(%struct.tm* %0, %struct.tm* %1) {
%3 = tail call i32 @assert(%struct.tm* %0)
%4 = tail call i32 @assert(%struct.tm* %1)
%5 = tail call i64 @little_endian_16(%struct.tm* %1)
%6 = shl i64 %5, 16
%7 = getelementptr inbounds %struct.tm, %struct.tm* %1, i64 2
%8 = tail call i64 @little_endian_16(%struct.tm* %7)
%9 = add i64 %6, %8
%10 = lshr i64 %9, 27
%11 = and i64 %10, 31
%12 = getelementptr inbounds %struct.tm, %struct.tm* %0, i64 0, i32 0
store i64 %11, i64* %12
%13 = lshr i64 %9, 21
%14 = and i64 %13, 63
%15 = getelementptr inbounds %struct.tm, %struct.tm* %0, i64 0, i32 1
store i64 %14, i64* %15
%16 = getelementptr inbounds %struct.tm, %struct.tm* %0, i64 0, i32 2
%17 = lshr i64 %9, 15
%18 = and i64 %17, 62
store i64 %18, i64* %16
%19 = lshr i64 %9, 9
%20 = and i64 %19, 127
%21 = getelementptr inbounds %struct.tm, %struct.tm* %0, i64 0, i32 3
%22 = add nuw nsw i64 %20, 80
store i64 %22, i64* %21
%23 = lshr i64 %9, 5
%24 = and i64 %23, 15
%25 = getelementptr inbounds %struct.tm, %struct.tm* %0, i64 0, i32 4
%26 = add nsw i64 %24, -1
store i64 %26, i64* %25
%27 = and i64 %9, 31
%28 = getelementptr inbounds %struct.tm, %struct.tm* %0, i64 0, i32 5
store i64 %27, i64* %28
ret void
}