void hex2char(char *ptr, char *val) {
  if ((ptr[1] >= 'A') && (ptr[1] <= 'F'))
    *val = ptr[1] - 'A' + 10;
  else if ((ptr[1] >= 'a') && (ptr[1] <= 'f'))
    *val = ptr[1] - 'a' + 10;
  else if ((ptr[1] >= '0') && (ptr[1] <= '9'))
    *val = ptr[1] - '0';
  else {
    *val = 0;
    return;
  }
  if ((ptr[0] >= 'A') && (ptr[0] <= 'F'))
    *val += (16 * (ptr[0] - 'A' + 10));
  else if ((ptr[0] >= 'a') && (ptr[0] <= 'f'))
    *val += (16 * (ptr[0] - 'a' + 10));
  else if ((ptr[0] >= '0') && (ptr[0] <= '9'))
    *val += (16 * (ptr[0] - '0'));
  else {
    *val = 0;
    return;
  }
}


x86 assembly (clang, -O0):
<hex2char>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x8(%rbp),%rax
movsbl 0x1(%rax),%eax
cmp    $0x41,%eax
jl     1149 <hex2char+0x49>
mov    -0x8(%rbp),%rax
movsbl 0x1(%rax),%eax
cmp    $0x46,%eax
jg     1149 <hex2char+0x49>
mov    -0x8(%rbp),%rax
movsbl 0x1(%rax),%eax
sub    $0x41,%eax
add    $0xa,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %cl,(%rax)
jmp    11d6 <hex2char+0xd6>
mov    -0x8(%rbp),%rax
movsbl 0x1(%rax),%eax
cmp    $0x61,%eax
jl     1186 <hex2char+0x86>
mov    -0x8(%rbp),%rax
movsbl 0x1(%rax),%eax
cmp    $0x66,%eax
jg     1186 <hex2char+0x86>
mov    -0x8(%rbp),%rax
movsbl 0x1(%rax),%eax
sub    $0x61,%eax
add    $0xa,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %cl,(%rax)
jmp    11d1 <hex2char+0xd1>
mov    -0x8(%rbp),%rax
movsbl 0x1(%rax),%eax
cmp    $0x30,%eax
jl     11c0 <hex2char+0xc0>
mov    -0x8(%rbp),%rax
movsbl 0x1(%rax),%eax
cmp    $0x39,%eax
jg     11c0 <hex2char+0xc0>
mov    -0x8(%rbp),%rax
movsbl 0x1(%rax),%eax
sub    $0x30,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %cl,(%rax)
jmp    11cc <hex2char+0xcc>
mov    -0x10(%rbp),%rax
movb   $0x0,(%rax)
jmp    12a9 <hex2char+0x1a9>
jmp    11d1 <hex2char+0xd1>
jmp    11d6 <hex2char+0xd6>
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x41,%eax
jl     1216 <hex2char+0x116>
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x46,%eax
jg     1216 <hex2char+0x116>
mov    -0x8(%rbp),%rax
movsbl (%rax),%edx
sub    $0x41,%edx
add    $0xa,%edx
shl    $0x4,%edx
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
add    %edx,%ecx
mov    %cl,(%rax)
jmp    12a9 <hex2char+0x1a9>
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x61,%eax
jl     1256 <hex2char+0x156>
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x66,%eax
jg     1256 <hex2char+0x156>
mov    -0x8(%rbp),%rax
movsbl (%rax),%edx
sub    $0x61,%edx
add    $0xa,%edx
shl    $0x4,%edx
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
add    %edx,%ecx
mov    %cl,(%rax)
jmp    12a4 <hex2char+0x1a4>
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x30,%eax
jl     1293 <hex2char+0x193>
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x39,%eax
jg     1293 <hex2char+0x193>
mov    -0x8(%rbp),%rax
movsbl (%rax),%edx
sub    $0x30,%edx
shl    $0x4,%edx
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
add    %edx,%ecx
mov    %cl,(%rax)
jmp    129f <hex2char+0x19f>
mov    -0x10(%rbp),%rax
movb   $0x0,(%rax)
jmp    12a9 <hex2char+0x1a9>
jmp    12a4 <hex2char+0x1a4>
jmp    12a9 <hex2char+0x1a9>
pop    %rbp
ret

x86 assembly (clang, -O2):
<hex2char>:
mov    0x1(%rdi),%al
lea    -0x41(%rax),%ecx
cmp    $0x5,%cl
ja     110f <hex2char+0xf>
add    $0xc9,%al
jmp    1121 <hex2char+0x21>
lea    -0x61(%rax),%ecx
cmp    $0x5,%cl
ja     111b <hex2char+0x1b>
add    $0xa9,%al
jmp    1121 <hex2char+0x21>
add    $0xd0,%al
cmp    $0x9,%al
ja     1152 <hex2char+0x52>
mov    %al,(%rsi)
mov    (%rdi),%cl
lea    -0x41(%rcx),%edx
cmp    $0x5,%dl
jbe    1135 <hex2char+0x35>
lea    -0x61(%rcx),%edx
cmp    $0x5,%dl
ja     1140 <hex2char+0x40>
shl    $0x4,%cl
add    %al,%cl
add    $0x90,%cl
mov    %cl,(%rsi)
ret
lea    -0x30(%rcx),%edx
cmp    $0x9,%dl
ja     1152 <hex2char+0x52>
shl    $0x4,%cl
add    %cl,%al
mov    %eax,%ecx
mov    %cl,(%rsi)
ret
xor    %ecx,%ecx
mov    %cl,(%rsi)
ret

LLVM IR (-O0):
define void @hex2char(i8* %0, i8* %1) {
%3 = alloca i8*
%4 = alloca i8*
store i8* %0, i8** %3
store i8* %1, i8** %4
%5 = load i8*, i8** %3
%6 = getelementptr inbounds i8, i8* %5, i64 1
%7 = load i8, i8* %6
%8 = sext i8 %7 to i32
%9 = icmp sge i32 %8, 65
br i1 %9, label %10, label %25
10: ; preds = %2
%11 = load i8*, i8** %3
%12 = getelementptr inbounds i8, i8* %11, i64 1
%13 = load i8, i8* %12
%14 = sext i8 %13 to i32
%15 = icmp sle i32 %14, 70
br i1 %15, label %16, label %25
16: ; preds = %10
%17 = load i8*, i8** %3
%18 = getelementptr inbounds i8, i8* %17, i64 1
%19 = load i8, i8* %18
%20 = sext i8 %19 to i32
%21 = sub nsw i32 %20, 65
%22 = add nsw i32 %21, 10
%23 = trunc i32 %22 to i8
%24 = load i8*, i8** %4
store i8 %23, i8* %24
br label %70
25: ; preds = %10, %2
%26 = load i8*, i8** %3
%27 = getelementptr inbounds i8, i8* %26, i64 1
%28 = load i8, i8* %27
%29 = sext i8 %28 to i32
%30 = icmp sge i32 %29, 97
br i1 %30, label %31, label %46
31: ; preds = %25
%32 = load i8*, i8** %3
%33 = getelementptr inbounds i8, i8* %32, i64 1
%34 = load i8, i8* %33
%35 = sext i8 %34 to i32
%36 = icmp sle i32 %35, 102
br i1 %36, label %37, label %46
37: ; preds = %31
%38 = load i8*, i8** %3
%39 = getelementptr inbounds i8, i8* %38, i64 1
%40 = load i8, i8* %39
%41 = sext i8 %40 to i32
%42 = sub nsw i32 %41, 97
%43 = add nsw i32 %42, 10
%44 = trunc i32 %43 to i8
%45 = load i8*, i8** %4
store i8 %44, i8* %45
br label %69
46: ; preds = %31, %25
%47 = load i8*, i8** %3
%48 = getelementptr inbounds i8, i8* %47, i64 1
%49 = load i8, i8* %48
%50 = sext i8 %49 to i32
%51 = icmp sge i32 %50, 48
br i1 %51, label %52, label %66
52: ; preds = %46
%53 = load i8*, i8** %3
%54 = getelementptr inbounds i8, i8* %53, i64 1
%55 = load i8, i8* %54
%56 = sext i8 %55 to i32
%57 = icmp sle i32 %56, 57
br i1 %57, label %58, label %66
58: ; preds = %52
%59 = load i8*, i8** %3
%60 = getelementptr inbounds i8, i8* %59, i64 1
%61 = load i8, i8* %60
%62 = sext i8 %61 to i32
%63 = sub nsw i32 %62, 48
%64 = trunc i32 %63 to i8
%65 = load i8*, i8** %4
store i8 %64, i8* %65
br label %68
66: ; preds = %52, %46
%67 = load i8*, i8** %4
store i8 0, i8* %67
br label %148
68: ; preds = %58
br label %69
69: ; preds = %68, %37
br label %70
70: ; preds = %69, %16
%71 = load i8*, i8** %3
%72 = getelementptr inbounds i8, i8* %71, i64 0
%73 = load i8, i8* %72
%74 = sext i8 %73 to i32
%75 = icmp sge i32 %74, 65
br i1 %75, label %76, label %95
76: ; preds = %70
%77 = load i8*, i8** %3
%78 = getelementptr inbounds i8, i8* %77, i64 0
%79 = load i8, i8* %78
%80 = sext i8 %79 to i32
%81 = icmp sle i32 %80, 70
br i1 %81, label %82, label %95
82: ; preds = %76
%83 = load i8*, i8** %3
%84 = getelementptr inbounds i8, i8* %83, i64 0
%85 = load i8, i8* %84
%86 = sext i8 %85 to i32
%87 = sub nsw i32 %86, 65
%88 = add nsw i32 %87, 10
%89 = mul nsw i32 16, %88
%90 = load i8*, i8** %4
%91 = load i8, i8* %90
%92 = sext i8 %91 to i32
%93 = add nsw i32 %92, %89
%94 = trunc i32 %93 to i8
store i8 %94, i8* %90
br label %148
95: ; preds = %76, %70
%96 = load i8*, i8** %3
%97 = getelementptr inbounds i8, i8* %96, i64 0
%98 = load i8, i8* %97
%99 = sext i8 %98 to i32
%100 = icmp sge i32 %99, 97
br i1 %100, label %101, label %120
101: ; preds = %95
%102 = load i8*, i8** %3
%103 = getelementptr inbounds i8, i8* %102, i64 0
%104 = load i8, i8* %103
%105 = sext i8 %104 to i32
%106 = icmp sle i32 %105, 102
br i1 %106, label %107, label %120
107: ; preds = %101
%108 = load i8*, i8** %3
%109 = getelementptr inbounds i8, i8* %108, i64 0
%110 = load i8, i8* %109
%111 = sext i8 %110 to i32
%112 = sub nsw i32 %111, 97
%113 = add nsw i32 %112, 10
%114 = mul nsw i32 16, %113
%115 = load i8*, i8** %4
%116 = load i8, i8* %115
%117 = sext i8 %116 to i32
%118 = add nsw i32 %117, %114
%119 = trunc i32 %118 to i8
store i8 %119, i8* %115
br label %147
120: ; preds = %101, %95
%121 = load i8*, i8** %3
%122 = getelementptr inbounds i8, i8* %121, i64 0
%123 = load i8, i8* %122
%124 = sext i8 %123 to i32
%125 = icmp sge i32 %124, 48
br i1 %125, label %126, label %144
126: ; preds = %120
%127 = load i8*, i8** %3
%128 = getelementptr inbounds i8, i8* %127, i64 0
%129 = load i8, i8* %128
%130 = sext i8 %129 to i32
%131 = icmp sle i32 %130, 57
br i1 %131, label %132, label %144
132: ; preds = %126
%133 = load i8*, i8** %3
%134 = getelementptr inbounds i8, i8* %133, i64 0
%135 = load i8, i8* %134
%136 = sext i8 %135 to i32
%137 = sub nsw i32 %136, 48
%138 = mul nsw i32 16, %137
%139 = load i8*, i8** %4
%140 = load i8, i8* %139
%141 = sext i8 %140 to i32
%142 = add nsw i32 %141, %138
%143 = trunc i32 %142 to i8
store i8 %143, i8* %139
br label %146
144: ; preds = %126, %120
%145 = load i8*, i8** %4
store i8 0, i8* %145
br label %148
146: ; preds = %132
br label %147
147: ; preds = %146, %107
br label %148
148: ; preds = %66, %144, %147, %82
ret void
}

LLVM IR (-O2):
define void @hex2char(i8* nocapture %0, i8* nocapture %1) {
%3 = getelementptr inbounds i8, i8* %0, i64 1
%4 = load i8, i8* %3
%5 = add i8 %4, -65
%6 = icmp ult i8 %5, 6
br i1 %6, label %7, label %9
7: ; preds = %2
%8 = add nsw i8 %4, -55
br label %17
9: ; preds = %2
%10 = add i8 %4, -97
%11 = icmp ult i8 %10, 6
br i1 %11, label %12, label %14
12: ; preds = %9
%13 = add nsw i8 %4, -87
br label %17
14: ; preds = %9
%15 = add i8 %4, -48
%16 = icmp ult i8 %15, 10
br i1 %16, label %17, label %39
17: ; preds = %14, %12, %7
%18 = phi i8 [ %13, %12 ], [ %8, %7 ], [ %15, %14 ]
store i8 %18, i8* %1
%19 = load i8, i8* %0
%20 = add i8 %19, -65
%21 = icmp ult i8 %20, 6
br i1 %21, label %22, label %26
22: ; preds = %17
%23 = shl i8 %19, 4
%24 = add nuw nsw i8 %23, -112
%25 = add nuw nsw i8 %24, %18
br label %39
26: ; preds = %17
%27 = add i8 %19, -97
%28 = icmp ult i8 %27, 6
br i1 %28, label %29, label %33
29: ; preds = %26
%30 = shl i8 %19, 4
%31 = add nuw nsw i8 %30, -112
%32 = add nuw nsw i8 %31, %18
br label %39
33: ; preds = %26
%34 = add i8 %19, -48
%35 = icmp ult i8 %34, 10
br i1 %35, label %36, label %39
36: ; preds = %33
%37 = shl i8 %19, 4
%38 = add nuw i8 %18, %37
br label %39
39: ; preds = %33, %14, %29, %36, %22
%40 = phi i8 [ %32, %29 ], [ %38, %36 ], [ %25, %22 ], [ 0, %14 ], [ 0, %33 ]
store i8 %40, i8* %1
ret void
}