#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 */
int /*<<< orphan*/ _add(short, short, short);
int /*<<< orphan*/ _beq(short, short, short);
int /*<<< orphan*/ _bgt(short, short, short);
int /*<<< orphan*/ _div(short, short, short);
int /*<<< orphan*/ _inc(short, short);
int /*<<< orphan*/ _jmp(short, short);
int /*<<< orphan*/ _lc(short, short);
int /*<<< orphan*/ _ld(short, short, short);
int /*<<< orphan*/ _mul(short, short, short);
int /*<<< orphan*/ _st(short, short, short);
int /*<<< orphan*/ _sub(short, short, short);
int /*<<< orphan*/ _sys(short, short);
int /*<<< orphan*/ printf(char *, short);
int /*<<< orphan*/ sys_dump(int);
int /*<<< orphan*/ sys_halt(int);
void execute(unsigned short int ins) {
  short int a0 = (ins >> 12) % 16;
  short int a1 = (ins >> 8) % 16;
  short int a2 = (ins >> 4) % 16;
  short int a3 = (ins >> 0) % 16;
  switch (a0) {
  case 0x0:
    _add(a1, a2, a3);
    break;
  case 0x1:
    _sub(a1, a2, a3);
    break;
  case 0x2:
    _mul(a1, a2, a3);
    break;
  case 0x3:
    _div(a1, a2, a3);
    break;
  case 0x6:
    _beq(a1, a2, a3);
    break;
  case 0x7:
    _bgt(a1, a2, a3);
    break;
  case 0x8:
    _ld(a1, a2, a3);
    break;
  case 0x9:
    _st(a1, a2, a3);
    break;
  case 0xa:
    _lc(a1, a3);
    break;
  case 0xb:
    _jmp(a1, a3);
    break;
  case 0xc:
    _inc(a1, a3);
    break;
  case 0xf:
    _sys(a1, a3);
    break;
  default:
    printf("Error: invalid opcode %#x.\n", a0);
    sys_dump(0x0);
    sys_halt(0x0);
  }
}


x86 assembly (clang, -O0):
<execute>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %di,%ax
mov    %ax,-0x2(%rbp)
movzwl -0x2(%rbp),%eax
shr    $0xc,%eax
mov    %ax,-0x4(%rbp)
movzbl -0x1(%rbp),%eax
and    $0xf,%eax
mov    %ax,-0x6(%rbp)
movzwl -0x2(%rbp),%eax
shr    $0x4,%eax
and    $0xf,%eax
mov    %ax,-0x8(%rbp)
movzwl -0x2(%rbp),%eax
and    $0xf,%eax
mov    %ax,-0xa(%rbp)
movswl -0x4(%rbp),%eax
mov    %eax,%ecx
mov    %rcx,-0x18(%rbp)
sub    $0xf,%eax
ja     1389 <execute+0x199>
mov    -0x18(%rbp),%rax
lea    0xdb4(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
mov    -0x6(%rbp),%cx
mov    -0x8(%rbp),%ax
movswl %cx,%edi
movswl %ax,%esi
movswl -0xa(%rbp),%edx
call   1060 <_add@plt>
jmp    13a7 <execute+0x1b7>
mov    -0x6(%rbp),%cx
mov    -0x8(%rbp),%ax
movswl %cx,%edi
movswl %ax,%esi
movswl -0xa(%rbp),%edx
call   1090 <_sub@plt>
jmp    13a7 <execute+0x1b7>
mov    -0x6(%rbp),%cx
mov    -0x8(%rbp),%ax
movswl %cx,%edi
movswl %ax,%esi
movswl -0xa(%rbp),%edx
call   1030 <_mul@plt>
jmp    13a7 <execute+0x1b7>
mov    -0x6(%rbp),%cx
mov    -0x8(%rbp),%ax
movswl %cx,%edi
movswl %ax,%esi
movswl -0xa(%rbp),%edx
call   10d0 <_div@plt>
jmp    13a7 <execute+0x1b7>
mov    -0x6(%rbp),%cx
mov    -0x8(%rbp),%ax
movswl %cx,%edi
movswl %ax,%esi
movswl -0xa(%rbp),%edx
call   10c0 <_beq@plt>
jmp    13a7 <execute+0x1b7>
mov    -0x6(%rbp),%cx
mov    -0x8(%rbp),%ax
movswl %cx,%edi
movswl %ax,%esi
movswl -0xa(%rbp),%edx
call   1100 <_bgt@plt>
jmp    13a7 <execute+0x1b7>
mov    -0x6(%rbp),%cx
mov    -0x8(%rbp),%ax
movswl %cx,%edi
movswl %ax,%esi
movswl -0xa(%rbp),%edx
call   1110 <_ld@plt>
jmp    13a7 <execute+0x1b7>
mov    -0x6(%rbp),%cx
mov    -0x8(%rbp),%ax
movswl %cx,%edi
movswl %ax,%esi
movswl -0xa(%rbp),%edx
call   10f0 <_st@plt>
jmp    13a7 <execute+0x1b7>
mov    -0x6(%rbp),%ax
movswl %ax,%edi
movswl -0xa(%rbp),%esi
call   1080 <_lc@plt>
jmp    13a7 <execute+0x1b7>
mov    -0x6(%rbp),%ax
movswl %ax,%edi
movswl -0xa(%rbp),%esi
call   1070 <_jmp@plt>
jmp    13a7 <execute+0x1b7>
mov    -0x6(%rbp),%ax
movswl %ax,%edi
movswl -0xa(%rbp),%esi
call   10b0 <_inc@plt>
jmp    13a7 <execute+0x1b7>
mov    -0x6(%rbp),%ax
movswl %ax,%edi
movswl -0xa(%rbp),%esi
call   10a0 <_sys@plt>
jmp    13a7 <execute+0x1b7>
lea    0xcb0(%rip),%rdi
movswl -0x4(%rbp),%esi
call   1040 <printf@plt>
xor    %edi,%edi
call   10e0 <sys_dump@plt>
xor    %edi,%edi
call   1050 <sys_halt@plt>
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<execute>:
push   %rax
mov    %edi,%edx
shr    $0xc,%edx
cmp    $0xf,%dx
ja     1263 <execute+0x73>
mov    %edi,%eax
shr    $0x8,%eax
and    $0xf,%eax
mov    %edi,%ecx
shr    $0x4,%ecx
and    $0xf,%ecx
and    $0xf,%edi
lea    0xdea(%rip),%r8
movslq (%r8,%rdx,4),%rsi
add    %r8,%rsi
jmp    *%rsi
movzwl %ax,%eax
movzwl %cx,%esi
movzwl %di,%edx
mov    %eax,%edi
pop    %rax
jmp    1060 <_add@plt>
movzwl %ax,%eax
movzwl %cx,%esi
movzwl %di,%edx
mov    %eax,%edi
pop    %rax
jmp    1090 <_sub@plt>
movzwl %ax,%eax
movzwl %cx,%esi
movzwl %di,%edx
mov    %eax,%edi
pop    %rax
jmp    1030 <_mul@plt>
movzwl %ax,%eax
movzwl %cx,%esi
movzwl %di,%edx
mov    %eax,%edi
pop    %rax
jmp    10d0 <_div@plt>
movzwl %dx,%esi
lea    0xdd3(%rip),%rdi
call   1040 <printf@plt>
xor    %edi,%edi
call   10e0 <sys_dump@plt>
xor    %edi,%edi
pop    %rax
jmp    1050 <sys_halt@plt>
movzwl %ax,%eax
movzwl %cx,%esi
movzwl %di,%edx
mov    %eax,%edi
pop    %rax
jmp    10c0 <_beq@plt>
movzwl %ax,%eax
movzwl %cx,%esi
movzwl %di,%edx
mov    %eax,%edi
pop    %rax
jmp    1100 <_bgt@plt>
movzwl %ax,%eax
movzwl %cx,%esi
movzwl %di,%edx
mov    %eax,%edi
pop    %rax
jmp    1110 <_ld@plt>
movzwl %ax,%eax
movzwl %cx,%esi
movzwl %di,%edx
mov    %eax,%edi
pop    %rax
jmp    10f0 <_st@plt>
movzwl %ax,%eax
movzwl %di,%esi
mov    %eax,%edi
pop    %rax
jmp    1080 <_lc@plt>
movzwl %ax,%eax
movzwl %di,%esi
mov    %eax,%edi
pop    %rax
jmp    1070 <_jmp@plt>
movzwl %ax,%eax
movzwl %di,%esi
mov    %eax,%edi
pop    %rax
jmp    10b0 <_inc@plt>
movzwl %ax,%eax
movzwl %di,%esi
mov    %eax,%edi
pop    %rax
jmp    10a0 <_sys@plt>

LLVM IR (-O0):
@.str = [28 x i8] c"Error: invalid opcode %#x.\0A\00"
define void @execute(i16 zeroext %0) {
%2 = alloca i16
%3 = alloca i16
%4 = alloca i16
%5 = alloca i16
%6 = alloca i16
store i16 %0, i16* %2
%7 = load i16, i16* %2
%8 = zext i16 %7 to i32
%9 = ashr i32 %8, 12
%10 = srem i32 %9, 16
%11 = trunc i32 %10 to i16
store i16 %11, i16* %3
%12 = load i16, i16* %2
%13 = zext i16 %12 to i32
%14 = ashr i32 %13, 8
%15 = srem i32 %14, 16
%16 = trunc i32 %15 to i16
store i16 %16, i16* %4
%17 = load i16, i16* %2
%18 = zext i16 %17 to i32
%19 = ashr i32 %18, 4
%20 = srem i32 %19, 16
%21 = trunc i32 %20 to i16
store i16 %21, i16* %5
%22 = load i16, i16* %2
%23 = zext i16 %22 to i32
%24 = ashr i32 %23, 0
%25 = srem i32 %24, 16
%26 = trunc i32 %25 to i16
store i16 %26, i16* %6
%27 = load i16, i16* %3
%28 = sext i16 %27 to i32
switch i32 %28, label %85 [
i32 0, label %29
i32 1, label %34
i32 2, label %39
i32 3, label %44
i32 6, label %49
i32 7, label %54
i32 8, label %59
i32 9, label %64
i32 10, label %69
i32 11, label %73
i32 12, label %77
i32 15, label %81
]
29: ; preds = %1
%30 = load i16, i16* %4
%31 = load i16, i16* %5
%32 = load i16, i16* %6
%33 = call i32 @_add(i16 signext %30, i16 signext %31, i16 signext %32)
br label %90
34: ; preds = %1
%35 = load i16, i16* %4
%36 = load i16, i16* %5
%37 = load i16, i16* %6
%38 = call i32 @_sub(i16 signext %35, i16 signext %36, i16 signext %37)
br label %90
39: ; preds = %1
%40 = load i16, i16* %4
%41 = load i16, i16* %5
%42 = load i16, i16* %6
%43 = call i32 @_mul(i16 signext %40, i16 signext %41, i16 signext %42)
br label %90
44: ; preds = %1
%45 = load i16, i16* %4
%46 = load i16, i16* %5
%47 = load i16, i16* %6
%48 = call i32 @_div(i16 signext %45, i16 signext %46, i16 signext %47)
br label %90
49: ; preds = %1
%50 = load i16, i16* %4
%51 = load i16, i16* %5
%52 = load i16, i16* %6
%53 = call i32 @_beq(i16 signext %50, i16 signext %51, i16 signext %52)
br label %90
54: ; preds = %1
%55 = load i16, i16* %4
%56 = load i16, i16* %5
%57 = load i16, i16* %6
%58 = call i32 @_bgt(i16 signext %55, i16 signext %56, i16 signext %57)
br label %90
59: ; preds = %1
%60 = load i16, i16* %4
%61 = load i16, i16* %5
%62 = load i16, i16* %6
%63 = call i32 @_ld(i16 signext %60, i16 signext %61, i16 signext %62)
br label %90
64: ; preds = %1
%65 = load i16, i16* %4
%66 = load i16, i16* %5
%67 = load i16, i16* %6
%68 = call i32 @_st(i16 signext %65, i16 signext %66, i16 signext %67)
br label %90
69: ; preds = %1
%70 = load i16, i16* %4
%71 = load i16, i16* %6
%72 = call i32 @_lc(i16 signext %70, i16 signext %71)
br label %90
73: ; preds = %1
%74 = load i16, i16* %4
%75 = load i16, i16* %6
%76 = call i32 @_jmp(i16 signext %74, i16 signext %75)
br label %90
77: ; preds = %1
%78 = load i16, i16* %4
%79 = load i16, i16* %6
%80 = call i32 @_inc(i16 signext %78, i16 signext %79)
br label %90
81: ; preds = %1
%82 = load i16, i16* %4
%83 = load i16, i16* %6
%84 = call i32 @_sys(i16 signext %82, i16 signext %83)
br label %90
85: ; preds = %1
%86 = load i16, i16* %3
%87 = call i32 @printf(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str, i64 0, i64 0), i16 signext %86)
%88 = call i32 @sys_dump(i32 0)
%89 = call i32 @sys_halt(i32 0)
br label %90
90: ; preds = %85, %81, %77, %73, %69, %64, %59, %54, %49, %44, %39, %34, %29
ret void
}

LLVM IR (-O2):
@.str = [28 x i8] c"Error: invalid opcode %#x.\0A\00"
define void @execute(i16 zeroext %0) {
%2 = lshr i16 %0, 12
%3 = lshr i16 %0, 8
%4 = and i16 %3, 15
%5 = lshr i16 %0, 4
%6 = and i16 %5, 15
%7 = and i16 %0, 15
%8 = zext i16 %2 to i32
switch i32 %8, label %33 [
i32 0, label %9
i32 1, label %11
i32 2, label %13
i32 3, label %15
i32 6, label %17
i32 7, label %19
i32 8, label %21
i32 9, label %23
i32 10, label %25
i32 11, label %27
i32 12, label %29
i32 15, label %31
]
9: ; preds = %1
%10 = tail call i32 @_add(i16 signext %4, i16 signext %6, i16 signext %7)
br label %37
11: ; preds = %1
%12 = tail call i32 @_sub(i16 signext %4, i16 signext %6, i16 signext %7)
br label %37
13: ; preds = %1
%14 = tail call i32 @_mul(i16 signext %4, i16 signext %6, i16 signext %7)
br label %37
15: ; preds = %1
%16 = tail call i32 @_div(i16 signext %4, i16 signext %6, i16 signext %7)
br label %37
17: ; preds = %1
%18 = tail call i32 @_beq(i16 signext %4, i16 signext %6, i16 signext %7)
br label %37
19: ; preds = %1
%20 = tail call i32 @_bgt(i16 signext %4, i16 signext %6, i16 signext %7)
br label %37
21: ; preds = %1
%22 = tail call i32 @_ld(i16 signext %4, i16 signext %6, i16 signext %7)
br label %37
23: ; preds = %1
%24 = tail call i32 @_st(i16 signext %4, i16 signext %6, i16 signext %7)
br label %37
25: ; preds = %1
%26 = tail call i32 @_lc(i16 signext %4, i16 signext %7)
br label %37
27: ; preds = %1
%28 = tail call i32 @_jmp(i16 signext %4, i16 signext %7)
br label %37
29: ; preds = %1
%30 = tail call i32 @_inc(i16 signext %4, i16 signext %7)
br label %37
31: ; preds = %1
%32 = tail call i32 @_sys(i16 signext %4, i16 signext %7)
br label %37
33: ; preds = %1
%34 = tail call i32 @printf(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str, i64 0, i64 0), i16 signext %2)
%35 = tail call i32 @sys_dump(i32 0)
%36 = tail call i32 @sys_halt(i32 0)
br label %37
37: ; preds = %33, %31, %29, %27, %25, %23, %21, %19, %17, %15, %13, %11, %9
ret void
}