#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 IP {
  int dummy;
};
struct CPU {
  int dummy;
};

/* Variables and functions */
int /*<<< orphan*/ ADD_A(struct CPU *, struct IP *);
int /*<<< orphan*/ ADD_B(struct CPU *, struct IP *);
int /*<<< orphan*/ ADD_C(struct CPU *, struct IP *);
int /*<<< orphan*/ ADD_D(struct CPU *, struct IP *);
int /*<<< orphan*/ ADD_E(struct CPU *, struct IP *);
int /*<<< orphan*/ ADD_H(struct CPU *, struct IP *);
int /*<<< orphan*/ ADD_L(struct CPU *, struct IP *);
int /*<<< orphan*/ ADD_M(struct CPU *, struct IP *);
int /*<<< orphan*/ printf(char *, unsigned int);
void execute(struct CPU *t, struct IP *ip, unsigned int inst[],
             unsigned int e) {
  unsigned int c = 0;
  while (c < e) {
    switch (inst[c]) {
    case 0x87:
      ADD_A(t, ip);
      break;
    case 0x80:
      ADD_B(t, ip);
      break;
    case 0x81:
      ADD_C(t, ip);
      break;
    case 0x82:
      ADD_D(t, ip);
      break;
    case 0x83:
      ADD_E(t, ip);
      break;
    case 0x84:
      ADD_H(t, ip);
      break;
    case 0x85:
      ADD_L(t, ip);
      break;
    case 0x86:
      ADD_M(t, ip);
      break;
    default:
      printf("UNKOWN OPCODE: 0x%x\n", inst[c]);
    }
    c++;
  }
}


x86 assembly (clang, -O0):
<execute>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %ecx,-0x1c(%rbp)
movl   $0x0,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jae    129e <execute+0x10e>
mov    -0x18(%rbp),%rax
mov    -0x20(%rbp),%ecx
mov    (%rax,%rcx,4),%eax
add    $0xffffff80,%eax
mov    %eax,%ecx
mov    %rcx,-0x28(%rbp)
sub    $0x7,%eax
ja     127a <execute+0xea>
mov    -0x28(%rbp),%rax
lea    0xe1f(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1080 <ADD_A@plt>
jmp    1290 <execute+0x100>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1040 <ADD_B@plt>
jmp    1290 <execute+0x100>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1090 <ADD_C@plt>
jmp    1290 <execute+0x100>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1030 <ADD_D@plt>
jmp    1290 <execute+0x100>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   10a0 <ADD_E@plt>
jmp    1290 <execute+0x100>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1050 <ADD_H@plt>
jmp    1290 <execute+0x100>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1060 <ADD_L@plt>
jmp    1290 <execute+0x100>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   10b0 <ADD_M@plt>
jmp    1290 <execute+0x100>
mov    -0x18(%rbp),%rax
mov    -0x20(%rbp),%ecx
mov    (%rax,%rcx,4),%esi
lea    0xd95(%rip),%rdi
call   1070 <printf@plt>
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    11ae <execute+0x1e>
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<execute>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
push   %rax
test   %ecx,%ecx
je     125e <execute+0xce>
mov    %rdx,%r13
mov    %rsi,%r14
mov    %rdi,%r15
mov    %ecx,%ebx
xor    %ebp,%ebp
lea    0xe49(%rip),%r12
jmp    11dd <execute+0x4d>
lea    0xe60(%rip),%rdi
call   1070 <printf@plt>
cs nopw 0x0(%rax,%rax,1)
nop
add    $0x1,%rbp
cmp    %rbp,%rbx
je     125e <execute+0xce>
mov    0x0(%r13,%rbp,4),%esi
lea    -0x80(%rsi),%eax
cmp    $0x7,%eax
ja     11b9 <execute+0x29>
movslq (%r12,%rax,4),%rax
add    %r12,%rax
jmp    *%rax
mov    %r15,%rdi
mov    %r14,%rsi
call   1040 <ADD_B@plt>
jmp    11d0 <execute+0x40>
mov    %r15,%rdi
mov    %r14,%rsi
call   1090 <ADD_C@plt>
jmp    11d0 <execute+0x40>
mov    %r15,%rdi
mov    %r14,%rsi
call   1030 <ADD_D@plt>
jmp    11d0 <execute+0x40>
mov    %r15,%rdi
mov    %r14,%rsi
call   10a0 <ADD_E@plt>
jmp    11d0 <execute+0x40>
mov    %r15,%rdi
mov    %r14,%rsi
call   1050 <ADD_H@plt>
jmp    11d0 <execute+0x40>
mov    %r15,%rdi
mov    %r14,%rsi
call   1060 <ADD_L@plt>
jmp    11d0 <execute+0x40>
mov    %r15,%rdi
mov    %r14,%rsi
call   10b0 <ADD_M@plt>
jmp    11d0 <execute+0x40>
mov    %r15,%rdi
mov    %r14,%rsi
call   1080 <ADD_A@plt>
jmp    11d0 <execute+0x40>
add    $0x8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
%struct.CPU = type { i32 }
%struct.IP = type { i32 }
@.str = [21 x i8] c"UNKOWN OPCODE: 0x%x\0A\00"
define void @execute(%struct.CPU* %0, %struct.IP* %1, i32* %2, i32 %3) {
%5 = alloca %struct.CPU*
%6 = alloca %struct.IP*
%7 = alloca i32*
%8 = alloca i32
%9 = alloca i32
store %struct.CPU* %0, %struct.CPU** %5
store %struct.IP* %1, %struct.IP** %6
store i32* %2, i32** %7
store i32 %3, i32* %8
store i32 0, i32* %9
br label %10
10: ; preds = %59, %4
%11 = load i32, i32* %9
%12 = load i32, i32* %8
%13 = icmp ult i32 %11, %12
br i1 %13, label %14, label %62
14: ; preds = %10
%15 = load i32*, i32** %7
%16 = load i32, i32* %9
%17 = zext i32 %16 to i64
%18 = getelementptr inbounds i32, i32* %15, i64 %17
%19 = load i32, i32* %18
switch i32 %19, label %52 [
i32 135, label %20
i32 128, label %24
i32 129, label %28
i32 130, label %32
i32 131, label %36
i32 132, label %40
i32 133, label %44
i32 134, label %48
]
20: ; preds = %14
%21 = load %struct.CPU*, %struct.CPU** %5
%22 = load %struct.IP*, %struct.IP** %6
%23 = call i32 @ADD_A(%struct.CPU* %21, %struct.IP* %22)
br label %59
24: ; preds = %14
%25 = load %struct.CPU*, %struct.CPU** %5
%26 = load %struct.IP*, %struct.IP** %6
%27 = call i32 @ADD_B(%struct.CPU* %25, %struct.IP* %26)
br label %59
28: ; preds = %14
%29 = load %struct.CPU*, %struct.CPU** %5
%30 = load %struct.IP*, %struct.IP** %6
%31 = call i32 @ADD_C(%struct.CPU* %29, %struct.IP* %30)
br label %59
32: ; preds = %14
%33 = load %struct.CPU*, %struct.CPU** %5
%34 = load %struct.IP*, %struct.IP** %6
%35 = call i32 @ADD_D(%struct.CPU* %33, %struct.IP* %34)
br label %59
36: ; preds = %14
%37 = load %struct.CPU*, %struct.CPU** %5
%38 = load %struct.IP*, %struct.IP** %6
%39 = call i32 @ADD_E(%struct.CPU* %37, %struct.IP* %38)
br label %59
40: ; preds = %14
%41 = load %struct.CPU*, %struct.CPU** %5
%42 = load %struct.IP*, %struct.IP** %6
%43 = call i32 @ADD_H(%struct.CPU* %41, %struct.IP* %42)
br label %59
44: ; preds = %14
%45 = load %struct.CPU*, %struct.CPU** %5
%46 = load %struct.IP*, %struct.IP** %6
%47 = call i32 @ADD_L(%struct.CPU* %45, %struct.IP* %46)
br label %59
48: ; preds = %14
%49 = load %struct.CPU*, %struct.CPU** %5
%50 = load %struct.IP*, %struct.IP** %6
%51 = call i32 @ADD_M(%struct.CPU* %49, %struct.IP* %50)
br label %59
52: ; preds = %14
%53 = load i32*, i32** %7
%54 = load i32, i32* %9
%55 = zext i32 %54 to i64
%56 = getelementptr inbounds i32, i32* %53, i64 %55
%57 = load i32, i32* %56
%58 = call i32 @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str, i64 0, i64 0), i32 %57)
br label %59
59: ; preds = %52, %48, %44, %40, %36, %32, %28, %24, %20
%60 = load i32, i32* %9
%61 = add i32 %60, 1
store i32 %61, i32* %9
br label %10
62: ; preds = %10
ret void
}

LLVM IR (-O2):
%struct.CPU = type { i32 }
%struct.IP = type { i32 }
@.str = [21 x i8] c"UNKOWN OPCODE: 0x%x\0A\00"
define void @execute(%struct.CPU* %0, %struct.IP* %1, i32* nocapture %2, i32 %3) {
%5 = icmp eq i32 %3, 0
br i1 %5, label %33, label %6
6: ; preds = %4
%7 = zext i32 %3 to i64
br label %8
8: ; preds = %6, %30
%9 = phi i64 [ 0, %6 ], [ %31, %30 ]
%10 = getelementptr inbounds i32, i32* %2, i64 %9
%11 = load i32, i32* %10
switch i32 %11, label %28 [
i32 135, label %12
i32 128, label %14
i32 129, label %16
i32 130, label %18
i32 131, label %20
i32 132, label %22
i32 133, label %24
i32 134, label %26
]
12: ; preds = %8
%13 = tail call i32 @ADD_A(%struct.CPU* %0, %struct.IP* %1)
br label %30
14: ; preds = %8
%15 = tail call i32 @ADD_B(%struct.CPU* %0, %struct.IP* %1)
br label %30
16: ; preds = %8
%17 = tail call i32 @ADD_C(%struct.CPU* %0, %struct.IP* %1)
br label %30
18: ; preds = %8
%19 = tail call i32 @ADD_D(%struct.CPU* %0, %struct.IP* %1)
br label %30
20: ; preds = %8
%21 = tail call i32 @ADD_E(%struct.CPU* %0, %struct.IP* %1)
br label %30
22: ; preds = %8
%23 = tail call i32 @ADD_H(%struct.CPU* %0, %struct.IP* %1)
br label %30
24: ; preds = %8
%25 = tail call i32 @ADD_L(%struct.CPU* %0, %struct.IP* %1)
br label %30
26: ; preds = %8
%27 = tail call i32 @ADD_M(%struct.CPU* %0, %struct.IP* %1)
br label %30
28: ; preds = %8
%29 = tail call i32 @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str, i64 0, i64 0), i32 %11)
br label %30
30: ; preds = %28, %26, %24, %22, %20, %18, %16, %14, %12
%31 = add nuw nsw i64 %9, 1
%32 = icmp eq i64 %31, %7
br i1 %32, label %33, label %8
33: ; preds = %30, %4
ret void
}