CpuExecuteOpcode

decompiled_code:
__int64 __fastcall CpuExecuteOpcode(__int64 a1, int a2, unsigned __int16 a3)
{
__int16 v3; // r14
int v4; // er12
unsigned int v6; // er13
__int16 v7; // ax
__int16 v8; // ax
char v9; // r15
char v10; // al
char v11; // dl
char v12; // r15
int v13; // er15
int v14; // er15
unsigned __int8 v15; // bl
char v16; // al
char v17; // bl
unsigned __int8 v18; // al
int v19; // eax
char v20; // bl
unsigned __int8 v21; // al
char v22; // al
char v23; // bl
char v24; // al
char v25; // bl
unsigned int v26; // eax
char v27; // bl
unsigned __int8 v28; // al
char v29; // al
unsigned __int8 v30; // al
char v31; // al
char v32; // bl
unsigned __int8 v33; // al
int v34; // eax
char v35; // bl
unsigned __int8 v36; // al
unsigned __int8 v37; // al
unsigned __int8 v38; // bl
unsigned __int8 v39; // al
unsigned __int8 v40; // al
unsigned __int8 v41; // r15
char v42; // al
char v43; // dl
char v44; // r15
unsigned __int8 v45; // r15
char v46; // r14
unsigned __int8 v47; // r14
int v48; // eax
char v49; // bl
unsigned __int8 v50; // al
__int16 v51; // ax
__int16 v52; // ax
__int16 v53; // ax
char v54; // al
char v55; // al
unsigned __int16 v56; // ax
__int16 v57; // dx
__int16 v58; // cx
__int16 v59; // dx
char v60; // di
char v61; // al
char v62; // si
unsigned __int8 v63; // di
unsigned __int8 v64; // dl
char v66; // si
char v67; // si
unsigned __int8 v68; // al
unsigned __int8 v69; // al
char v70; // dl
char v71; // cl
char v72; // al
char v73; // si
unsigned __int8 v74; // al
char v76; // [rsp+8h] [rbp-40h]
char v77; // [rsp+8h] [rbp-40h]
unsigned int v78; // [rsp+8h] [rbp-40h]
char v79; // [rsp+8h] [rbp-40h]

v3 = *(unsigned __int8 *)(a1 + 3);
v4 = *(unsigned __int8 *)(a1 + 138);
if ( (a2 & 0xC000) != 0 )
{
puts("Invalid high bits in opcode");
return (unsigned int)-1;
}
v6 = a3 + 1;
v7 = a2 & 0x3000;
if ( (a2 & 0x3000) != 0 )
{
if ( v7 == 4096 )
{
v53 = a2 & 0x3C00;
if ( (a2 & 0x3C00) == 6144 )
{
if ( ((unsigned __int8)(1 << (((__int16)a2 >> 7) & 7)) & (unsigned __int8)RegsGetValue(a1, a2 & 0x7F)) == 0 )
v6 = a3 + 2;
goto LABEL_166;
}
if ( (a2 & 0x3C00u) > 0x1800 )
{
if ( v53 == 7168 )
{
if ( ((unsigned __int8)(1 << (((__int16)a2 >> 7) & 7)) & (unsigned __int8)RegsGetValue(a1, a2 & 0x7F)) != 0 )
v6 = a3 + 2;
goto LABEL_166;
}
}
else
{
if ( v53 == 4096 )
{
v55 = RegsGetValue(a1, a2 & 0x7F);
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)(v55 & ~(1 << (((__int16)a2 >> 7) & 7))));
goto LABEL_166;
}
if ( v53 == 5120 )
{
v54 = RegsGetValue(a1, a2 & 0x7F);
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)((1 << (((__int16)a2 >> 7) & 7)) | v54));
goto LABEL_166;
}
}
puts("Invalid 01 opcode!");
return (unsigned int)-1;
}
if ( v7 == 0x2000 )
{
if ( (a2 & 0x800) != 0 )
{
LOWORD(a2) = a2 & 0x7FF;
LOWORD(v6) = v6 & 0x1800;
v6 |= a2;
return v6;
}
StkPush(a1 + 139, (unsigned __int8)(a3 + 1));
LOWORD(a2) = a2 & 0x7FF;
LOWORD(v6) = v6 & 0x1800;
v6 |= a2;
goto LABEL_166;
}
if ( (a2 & 0xE00) == 3584 )
{
v56 = v3 & 0xFFFD;
if ( (((a2 & 0xF) + (v4 & 0xF)) & 0x10) != 0 )
v56 = v3 | 2;
HIBYTE(v57) = BYTE1(v4);
LOBYTE(v57) = (unsigned __int8)v4 >> 4;
HIBYTE(v58) = BYTE1(a2);
LOBYTE(v58) = (unsigned __int8)a2 >> 4;
v59 = v57 + v58 + ((v56 >> 1) & 1);
v60 = v56 | 1;
v61 = v56 & 0xFE;
if ( (v59 & 0x10) == 0 )
v60 = v61;
v62 = v4 + a2;
*(_BYTE *)(a1 + 138) = v62;
v15 = v60 | 4;
v63 = v60 & 0xFB;
if ( v62 )
v15 = v63;
goto LABEL_164;
}
v51 = a2 & 0xF00;
if ( (a2 & 0xF00) == 2304 )
{
v66 = v4 & a2;
*(_BYTE *)(a1 + 138) = v66;
v15 = v3 & 0xFB;
if ( !v66 )
v15 = v3 | 4;
goto LABEL_164;
}
if ( v51 == 2048 )
{
v67 = v4 | a2;
*(_BYTE *)(a1 + 138) = v67;
if ( v67 )
{
v15 = v3 & 0xFB;
goto LABEL_164;
}
v15 = v3 | 4;
goto LABEL_174;
}
if ( v51 == 2560 )
{
*(_BYTE *)(a1 + 138) = a2 ^ v4;
v68 = v3 | 4;
if ( (_BYTE)v4 != (_BYTE)a2 )
v68 = v3 & 0xFB;
v15 = v68;
goto LABEL_164;
}
v52 = a2 & 0xC00;
if ( (a2 & 0xC00) == 0 )
{
*(_BYTE *)(a1 + 138) = a2;
goto LABEL_166;
}
if ( v52 != 1024 )
{
if ( v52 != 3072 )
{
puts("Invalid 11 opcode!");
return (unsigned int)-1;
}
v69 = v3 & 0xFD;
if ( (((a2 & 0xF) - (v4 & 0xF)) & 0x10) == 0 )
v69 = v3 | 2;
v70 = ((unsigned __int8)a2 >> 4) - ((unsigned __int8)v4 >> 4) - (((v69 >> 1) ^ 1) & 1);
v71 = v69 | 1;
v72 = v69 & 0xFE;
if ( (v70 & 0x10) == 0 )
v72 = v71;
v73 = a2 - v4;
*(_BYTE *)(a1 + 138) = v73;
v15 = v72 | 4;
v74 = v72 & 0xFB;
if ( v73 )
v15 = v74;
goto LABEL_164;
}
*(_BYTE *)(a1 + 138) = a2;
v6 = (unsigned __int8)StkPop(a1 + 139);
}
else
{
v8 = a2 & 0xF00;
if ( (a2 & 0xF00) == 2048 )
{
v37 = RegsGetValue(a1, a2 & 0x7F);
v38 = v37;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, v37);
else
*(_BYTE *)(a1 + 138) = v37;
v39 = v3 | 4;
if ( v38 )
v39 = v3 & 0xFB;
v15 = v39;
goto LABEL_164;
}
if ( (a2 & 0xF00u) <= 0x800 )
{
if ( v8 == 1024 )
{
v34 = v4 | RegsGetValue(a1, a2 & 0x7F);
v35 = v34;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v34);
else
*(_BYTE *)(a1 + 138) = v34;
v36 = v3 | 4;
if ( v35 )
v36 = v3 & 0xFB;
v15 = v36;
goto LABEL_164;
}
if ( (a2 & 0xF00u) > 0x400 )
{
if ( v8 != 1536 )
{
if ( v8 == 1792 )
{
v9 = v3 & 0xFD;
if ( (((RegsGetValue(a1, a2 & 0x7F) & 0xF) + (v4 & 0xF)) & 0x10) != 0 )
v9 = v3 | 2;
v76 = *(_BYTE *)(a1 + 138) >> 4;
v10 = ((char)RegsGetValue(a1, a2 & 0x7F) >> 4) + v76 + ((v9 & 2) != 0);
v11 = v9 | 1;
v12 = v9 & 0xFE;
if ( (v10 & 0x10) == 0 )
v11 = v12;
v77 = v11;
v13 = *(unsigned __int8 *)(a1 + 138);
v14 = RegsGetValue(a1, a2 & 0x7F) + v13;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v14);
else
*(_BYTE *)(a1 + 138) = v14;
v15 = v77 & 0xFB;
if ( !(_BYTE)v14 )
v15 = v77 | 4;
goto LABEL_164;
}
if ( v8 == 1280 )
{
v19 = v4 & RegsGetValue(a1, a2 & 0x7F);
v20 = v19;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v19);
else
*(_BYTE *)(a1 + 138) = v19;
v21 = v3 | 4;
if ( v20 )
v21 = v3 & 0xFB;
v15 = v21;
goto LABEL_164;
}
LABEL_132:
puts("Invalid 00 opcode!");
return (unsigned int)-1;
}
v48 = v4 ^ RegsGetValue(a1, a2 & 0x7F);
v49 = v48;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v48);
else
*(_BYTE *)(a1 + 138) = v48;
v50 = v3 | 4;
if ( v49 )
v50 = v3 & 0xFB;
v15 = v50;
LABEL_164:
if ( v15 == (_BYTE)v3 )
goto LABEL_166;
goto LABEL_165;
}
if ( v8 == 512 )
{
v41 = v3 & 0xFD;
if ( (((RegsGetValue(a1, a2 & 0x7F) & 0xF) - (*(_BYTE *)(a1 + 138) & 0xF)) & 0x10) == 0 )
v41 = v3 | 2;
v42 = ((char)RegsGetValue(a1, a2 & 0x7F) >> 4) - (*(_BYTE *)(a1 + 138) >> 4) - (((v41 >> 1) ^ 1) & 1);
v43 = v41 | 1;
v44 = v41 & 0xFE;
if ( (v42 & 0x10) != 0 )
v43 = v44;
v79 = v43;
v45 = RegsGetValue(a1, a2 & 0x7F) - *(_BYTE *)(a1 + 138);
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, v45);
else
*(_BYTE *)(a1 + 138) = v45;
v15 = v79 & 0xFB;
if ( !v45 )
v15 = v79 | 4;
goto LABEL_164;
}
if ( (a2 & 0xF00u) > 0x200 )
{
if ( v8 != 768 )
goto LABEL_132;
v16 = RegsGetValue(a1, a2 & 0x7F);
v17 = v16 - 1;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)(v16 - 1));
else
*(_BYTE *)(a1 + 138) = v17;
v18 = v3 | 4;
if ( v17 )
v18 = v3 & 0xFB;
v15 = v18;
goto LABEL_164;
}
if ( v8 )
{
if ( v8 == 256 )
{
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, 0LL);
else
*(_BYTE *)(a1 + 138) = 0;
v15 = v3 | 4;
goto LABEL_164;
}
goto LABEL_132;
}
if ( (a2 & 0x80u) != 0 )
{
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v4);
goto LABEL_166;
}
if ( (a2 & 0xF) == 0 )
return v6;
if ( (_BYTE)a2 == 99 )
{
v15 = v3 & 0xF7 | 0x10;
}
else
{
if ( (unsigned __int8)a2 <= 0x63u )
{
if ( (unsigned __int8)a2 == 8 || (unsigned __int8)a2 == 9 )
{
v6 = (unsigned __int8)StkPop(a1 + 139);
goto LABEL_166;
}
LABEL_104:
puts("Invalid 00 0000 opcode!");
return (unsigned int)-1;
}
if ( (unsigned __int8)a2 != 100 )
goto LABEL_104;
v15 = v3 | 0x18;
}
LABEL_174:
if ( (_BYTE)v3 == v15 )
return v6;
LABEL_165:
printf("STATUS:[");
RegsPrintStatusRegister(*(unsigned __int8 *)(a1 + 3));
printf("] -> [");
*(_BYTE *)(a1 + 3) = v15;
RegsPrintStatusRegister(v15);
puts("]");
goto LABEL_166;
}
if ( v8 == 3072 )
{
v78 = a2 & 0x7F;
v40 = RegsGetValue(a1, a2 & 0x7F);
v15 = v3 & 0xFE;
if ( (v40 & 1) != 0 )
v15 = v3 | 1;
v30 = v40 >> 1;
if ( (*(_BYTE *)(a1 + 3) & 1) != 0 )
v30 |= 0x80u;
if ( (a2 & 0x80u) == 0 )
{
*(_BYTE *)(a1 + 138) = v30;
goto LABEL_164;
}
goto LABEL_105;
}
if ( (a2 & 0xF00u) <= 0xC00 )
{
switch ( v8 )
{
case 2560:
v31 = RegsGetValue(a1, a2 & 0x7F);
v32 = v31 + 1;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)(v31 + 1));
else
*(_BYTE *)(a1 + 138) = v32;
v33 = v3 | 4;
if ( v32 )
v33 = v3 & 0xFB;
v15 = v33;
break;
case 2816:
v24 = RegsGetValue(a1, a2 & 0x7F);
v25 = v24 - 1;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)(v24 - 1));
else
*(_BYTE *)(a1 + 138) = v25;
if ( !v25 )
v6 = a3 + 2;
goto LABEL_166;
case 2304:
v26 = ~(unsigned int)RegsGetValue(a1, a2 & 0x7F);
v27 = v26;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v26);
else
*(_BYTE *)(a1 + 138) = v26;
v28 = v3 | 4;
if ( v27 )
v28 = v3 & 0xFB;
v15 = v28;
break;
default:
goto LABEL_132;
}
goto LABEL_164;
}
if ( v8 != 3584 )
{
if ( v8 == 3840 )
{
v22 = RegsGetValue(a1, a2 & 0x7F);
v23 = v22 + 1;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)(v22 + 1));
else
*(_BYTE *)(a1 + 138) = v23;
if ( !v23 )
v6 = a3 + 2;
goto LABEL_166;
}
if ( v8 != 3328 )
goto LABEL_132;
v78 = a2 & 0x7F;
v29 = RegsGetValue(a1, a2 & 0x7F);
v15 = v3 & 0xFE;
if ( v29 < 0 )
v15 = v3 | 1;
v30 = 2 * v29;
if ( (*(_BYTE *)(a1 + 3) & 1) != 0 )
v30 |= 1u;
if ( (a2 & 0x80u) == 0 )
{
*(_BYTE *)(a1 + 138) = v30;
goto LABEL_164;
}
LABEL_105:
RegsSetValue(a1, v78, v30);
goto LABEL_164;
}
v46 = RegsGetValue(a1, a2 & 0x7F);
v47 = ((unsigned __int8)RegsGetValue(a1, a2 & 0x7F) >> 4) | (16 * v46);
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, v47);
else
*(_BYTE *)(a1 + 138) = v47;
}
LABEL_166:
v64 = *(_BYTE *)(a1 + 138);
if ( v64 != (_BYTE)v4 )
printf("W: %d -> %d\n", (unsigned __int8)v4, v64);
return v6;
}

canonical_decompiled_code:
__int64 __fastcall func6(__int64 a1, int a2, unsigned __int16 a3)
{
__int16 v3; // r14
int v4; // er12
unsigned int v6; // er13
__int16 v7; // ax
__int16 v8; // ax
char v9; // r15
char v10; // al
char v11; // dl
char v12; // r15
int v13; // er15
int v14; // er15
unsigned __int8 v15; // bl
char v16; // al
char v17; // bl
unsigned __int8 v18; // al
int v19; // eax
char v20; // bl
unsigned __int8 v21; // al
char v22; // al
char v23; // bl
char v24; // al
char v25; // bl
unsigned int v26; // eax
char v27; // bl
unsigned __int8 v28; // al
char v29; // al
unsigned __int8 v30; // al
char v31; // al
char v32; // bl
unsigned __int8 v33; // al
int v34; // eax
char v35; // bl
unsigned __int8 v36; // al
unsigned __int8 v37; // al
unsigned __int8 v38; // bl
unsigned __int8 v39; // al
unsigned __int8 v40; // al
unsigned __int8 v41; // r15
char v42; // al
char v43; // dl
char v44; // r15
unsigned __int8 v45; // r15
char v46; // r14
unsigned __int8 v47; // r14
int v48; // eax
char v49; // bl
unsigned __int8 v50; // al
__int16 v51; // ax
__int16 v52; // ax
__int16 v53; // ax
char v54; // al
char v55; // al
unsigned __int16 v56; // ax
__int16 v57; // dx
__int16 v58; // cx
__int16 v59; // dx
char v60; // di
char v61; // al
char v62; // si
unsigned __int8 v63; // di
unsigned __int8 v64; // dl
char v66; // si
char v67; // si
unsigned __int8 v68; // al
unsigned __int8 v69; // al
char v70; // dl
char v71; // cl
char v72; // al
char v73; // si
unsigned __int8 v74; // al
char v76; // [rsp+8h] [rbp-40h]
char v77; // [rsp+8h] [rbp-40h]
unsigned int v78; // [rsp+8h] [rbp-40h]
char v79; // [rsp+8h] [rbp-40h]

v3 = *(unsigned __int8 *)(a1 + 3);
v4 = *(unsigned __int8 *)(a1 + 138);
if ( (a2 & 0xC000) != 0 )
{
puts("Invalid high bits in opcode");
return (unsigned int)-1;
}
v6 = a3 + 1;
v7 = a2 & 0x3000;
if ( (a2 & 0x3000) != 0 )
{
if ( v7 == 4096 )
{
v53 = a2 & 0x3C00;
if ( (a2 & 0x3C00) == 6144 )
{
if ( ((unsigned __int8)(1 << (((__int16)a2 >> 7) & 7)) & (unsigned __int8)RegsGetValue(a1, a2 & 0x7F)) == 0 )
v6 = a3 + 2;
goto LABEL_166;
}
if ( (a2 & 0x3C00u) > 0x1800 )
{
if ( v53 == 7168 )
{
if ( ((unsigned __int8)(1 << (((__int16)a2 >> 7) & 7)) & (unsigned __int8)RegsGetValue(a1, a2 & 0x7F)) != 0 )
v6 = a3 + 2;
goto LABEL_166;
}
}
else
{
if ( v53 == 4096 )
{
v55 = RegsGetValue(a1, a2 & 0x7F);
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)(v55 & ~(1 << (((__int16)a2 >> 7) & 7))));
goto LABEL_166;
}
if ( v53 == 5120 )
{
v54 = RegsGetValue(a1, a2 & 0x7F);
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)((1 << (((__int16)a2 >> 7) & 7)) | v54));
goto LABEL_166;
}
}
puts("Invalid 01 opcode!");
return (unsigned int)-1;
}
if ( v7 == 0x2000 )
{
if ( (a2 & 0x800) != 0 )
{
LOWORD(a2) = a2 & 0x7FF;
LOWORD(v6) = v6 & 0x1800;
v6 |= a2;
return v6;
}
StkPush(a1 + 139, (unsigned __int8)(a3 + 1));
LOWORD(a2) = a2 & 0x7FF;
LOWORD(v6) = v6 & 0x1800;
v6 |= a2;
goto LABEL_166;
}
if ( (a2 & 0xE00) == 3584 )
{
v56 = v3 & 0xFFFD;
if ( (((a2 & 0xF) + (v4 & 0xF)) & 0x10) != 0 )
v56 = v3 | 2;
HIBYTE(v57) = BYTE1(v4);
LOBYTE(v57) = (unsigned __int8)v4 >> 4;
HIBYTE(v58) = BYTE1(a2);
LOBYTE(v58) = (unsigned __int8)a2 >> 4;
v59 = v57 + v58 + ((v56 >> 1) & 1);
v60 = v56 | 1;
v61 = v56 & 0xFE;
if ( (v59 & 0x10) == 0 )
v60 = v61;
v62 = v4 + a2;
*(_BYTE *)(a1 + 138) = v62;
v15 = v60 | 4;
v63 = v60 & 0xFB;
if ( v62 )
v15 = v63;
goto LABEL_164;
}
v51 = a2 & 0xF00;
if ( (a2 & 0xF00) == 2304 )
{
v66 = v4 & a2;
*(_BYTE *)(a1 + 138) = v66;
v15 = v3 & 0xFB;
if ( !v66 )
v15 = v3 | 4;
goto LABEL_164;
}
if ( v51 == 2048 )
{
v67 = v4 | a2;
*(_BYTE *)(a1 + 138) = v67;
if ( v67 )
{
v15 = v3 & 0xFB;
goto LABEL_164;
}
v15 = v3 | 4;
goto LABEL_174;
}
if ( v51 == 2560 )
{
*(_BYTE *)(a1 + 138) = a2 ^ v4;
v68 = v3 | 4;
if ( (_BYTE)v4 != (_BYTE)a2 )
v68 = v3 & 0xFB;
v15 = v68;
goto LABEL_164;
}
v52 = a2 & 0xC00;
if ( (a2 & 0xC00) == 0 )
{
*(_BYTE *)(a1 + 138) = a2;
goto LABEL_166;
}
if ( v52 != 1024 )
{
if ( v52 != 3072 )
{
puts("Invalid 11 opcode!");
return (unsigned int)-1;
}
v69 = v3 & 0xFD;
if ( (((a2 & 0xF) - (v4 & 0xF)) & 0x10) == 0 )
v69 = v3 | 2;
v70 = ((unsigned __int8)a2 >> 4) - ((unsigned __int8)v4 >> 4) - (((v69 >> 1) ^ 1) & 1);
v71 = v69 | 1;
v72 = v69 & 0xFE;
if ( (v70 & 0x10) == 0 )
v72 = v71;
v73 = a2 - v4;
*(_BYTE *)(a1 + 138) = v73;
v15 = v72 | 4;
v74 = v72 & 0xFB;
if ( v73 )
v15 = v74;
goto LABEL_164;
}
*(_BYTE *)(a1 + 138) = a2;
v6 = (unsigned __int8)StkPop(a1 + 139);
}
else
{
v8 = a2 & 0xF00;
if ( (a2 & 0xF00) == 2048 )
{
v37 = RegsGetValue(a1, a2 & 0x7F);
v38 = v37;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, v37);
else
*(_BYTE *)(a1 + 138) = v37;
v39 = v3 | 4;
if ( v38 )
v39 = v3 & 0xFB;
v15 = v39;
goto LABEL_164;
}
if ( (a2 & 0xF00u) <= 0x800 )
{
if ( v8 == 1024 )
{
v34 = v4 | RegsGetValue(a1, a2 & 0x7F);
v35 = v34;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v34);
else
*(_BYTE *)(a1 + 138) = v34;
v36 = v3 | 4;
if ( v35 )
v36 = v3 & 0xFB;
v15 = v36;
goto LABEL_164;
}
if ( (a2 & 0xF00u) > 0x400 )
{
if ( v8 != 1536 )
{
if ( v8 == 1792 )
{
v9 = v3 & 0xFD;
if ( (((RegsGetValue(a1, a2 & 0x7F) & 0xF) + (v4 & 0xF)) & 0x10) != 0 )
v9 = v3 | 2;
v76 = *(_BYTE *)(a1 + 138) >> 4;
v10 = ((char)RegsGetValue(a1, a2 & 0x7F) >> 4) + v76 + ((v9 & 2) != 0);
v11 = v9 | 1;
v12 = v9 & 0xFE;
if ( (v10 & 0x10) == 0 )
v11 = v12;
v77 = v11;
v13 = *(unsigned __int8 *)(a1 + 138);
v14 = RegsGetValue(a1, a2 & 0x7F) + v13;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v14);
else
*(_BYTE *)(a1 + 138) = v14;
v15 = v77 & 0xFB;
if ( !(_BYTE)v14 )
v15 = v77 | 4;
goto LABEL_164;
}
if ( v8 == 1280 )
{
v19 = v4 & RegsGetValue(a1, a2 & 0x7F);
v20 = v19;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v19);
else
*(_BYTE *)(a1 + 138) = v19;
v21 = v3 | 4;
if ( v20 )
v21 = v3 & 0xFB;
v15 = v21;
goto LABEL_164;
}
LABEL_132:
puts("Invalid 00 opcode!");
return (unsigned int)-1;
}
v48 = v4 ^ RegsGetValue(a1, a2 & 0x7F);
v49 = v48;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v48);
else
*(_BYTE *)(a1 + 138) = v48;
v50 = v3 | 4;
if ( v49 )
v50 = v3 & 0xFB;
v15 = v50;
LABEL_164:
if ( v15 == (_BYTE)v3 )
goto LABEL_166;
goto LABEL_165;
}
if ( v8 == 512 )
{
v41 = v3 & 0xFD;
if ( (((RegsGetValue(a1, a2 & 0x7F) & 0xF) - (*(_BYTE *)(a1 + 138) & 0xF)) & 0x10) == 0 )
v41 = v3 | 2;
v42 = ((char)RegsGetValue(a1, a2 & 0x7F) >> 4) - (*(_BYTE *)(a1 + 138) >> 4) - (((v41 >> 1) ^ 1) & 1);
v43 = v41 | 1;
v44 = v41 & 0xFE;
if ( (v42 & 0x10) != 0 )
v43 = v44;
v79 = v43;
v45 = RegsGetValue(a1, a2 & 0x7F) - *(_BYTE *)(a1 + 138);
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, v45);
else
*(_BYTE *)(a1 + 138) = v45;
v15 = v79 & 0xFB;
if ( !v45 )
v15 = v79 | 4;
goto LABEL_164;
}
if ( (a2 & 0xF00u) > 0x200 )
{
if ( v8 != 768 )
goto LABEL_132;
v16 = RegsGetValue(a1, a2 & 0x7F);
v17 = v16 - 1;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)(v16 - 1));
else
*(_BYTE *)(a1 + 138) = v17;
v18 = v3 | 4;
if ( v17 )
v18 = v3 & 0xFB;
v15 = v18;
goto LABEL_164;
}
if ( v8 )
{
if ( v8 == 256 )
{
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, 0LL);
else
*(_BYTE *)(a1 + 138) = 0;
v15 = v3 | 4;
goto LABEL_164;
}
goto LABEL_132;
}
if ( (a2 & 0x80u) != 0 )
{
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v4);
goto LABEL_166;
}
if ( (a2 & 0xF) == 0 )
return v6;
if ( (_BYTE)a2 == 99 )
{
v15 = v3 & 0xF7 | 0x10;
}
else
{
if ( (unsigned __int8)a2 <= 0x63u )
{
if ( (unsigned __int8)a2 == 8 || (unsigned __int8)a2 == 9 )
{
v6 = (unsigned __int8)StkPop(a1 + 139);
goto LABEL_166;
}
LABEL_104:
puts("Invalid 00 0000 opcode!");
return (unsigned int)-1;
}
if ( (unsigned __int8)a2 != 100 )
goto LABEL_104;
v15 = v3 | 0x18;
}
LABEL_174:
if ( (_BYTE)v3 == v15 )
return v6;
LABEL_165:
printf("STATUS:[");
RegsPrintStatusRegister(*(unsigned __int8 *)(a1 + 3));
printf("] -> [");
*(_BYTE *)(a1 + 3) = v15;
RegsPrintStatusRegister(v15);
puts("]");
goto LABEL_166;
}
if ( v8 == 3072 )
{
v78 = a2 & 0x7F;
v40 = RegsGetValue(a1, a2 & 0x7F);
v15 = v3 & 0xFE;
if ( (v40 & 1) != 0 )
v15 = v3 | 1;
v30 = v40 >> 1;
if ( (*(_BYTE *)(a1 + 3) & 1) != 0 )
v30 |= 0x80u;
if ( (a2 & 0x80u) == 0 )
{
*(_BYTE *)(a1 + 138) = v30;
goto LABEL_164;
}
goto LABEL_105;
}
if ( (a2 & 0xF00u) <= 0xC00 )
{
switch ( v8 )
{
case 2560:
v31 = RegsGetValue(a1, a2 & 0x7F);
v32 = v31 + 1;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)(v31 + 1));
else
*(_BYTE *)(a1 + 138) = v32;
v33 = v3 | 4;
if ( v32 )
v33 = v3 & 0xFB;
v15 = v33;
break;
case 2816:
v24 = RegsGetValue(a1, a2 & 0x7F);
v25 = v24 - 1;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)(v24 - 1));
else
*(_BYTE *)(a1 + 138) = v25;
if ( !v25 )
v6 = a3 + 2;
goto LABEL_166;
case 2304:
v26 = ~(unsigned int)RegsGetValue(a1, a2 & 0x7F);
v27 = v26;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)v26);
else
*(_BYTE *)(a1 + 138) = v26;
v28 = v3 | 4;
if ( v27 )
v28 = v3 & 0xFB;
v15 = v28;
break;
default:
goto LABEL_132;
}
goto LABEL_164;
}
if ( v8 != 3584 )
{
if ( v8 == 3840 )
{
v22 = RegsGetValue(a1, a2 & 0x7F);
v23 = v22 + 1;
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, (unsigned __int8)(v22 + 1));
else
*(_BYTE *)(a1 + 138) = v23;
if ( !v23 )
v6 = a3 + 2;
goto LABEL_166;
}
if ( v8 != 3328 )
goto LABEL_132;
v78 = a2 & 0x7F;
v29 = RegsGetValue(a1, a2 & 0x7F);
v15 = v3 & 0xFE;
if ( v29 < 0 )
v15 = v3 | 1;
v30 = 2 * v29;
if ( (*(_BYTE *)(a1 + 3) & 1) != 0 )
v30 |= 1u;
if ( (a2 & 0x80u) == 0 )
{
*(_BYTE *)(a1 + 138) = v30;
goto LABEL_164;
}
LABEL_105:
RegsSetValue(a1, v78, v30);
goto LABEL_164;
}
v46 = RegsGetValue(a1, a2 & 0x7F);
v47 = ((unsigned __int8)RegsGetValue(a1, a2 & 0x7F) >> 4) | (16 * v46);
if ( (a2 & 0x80u) != 0 )
RegsSetValue(a1, a2 & 0x7F, v47);
else
*(_BYTE *)(a1 + 138) = v47;
}
LABEL_166:
v64 = *(_BYTE *)(a1 + 138);
if ( v64 != (_BYTE)v4 )
printf("W: %d -> %d\n", (unsigned __int8)v4, v64);
return v6;
}

original_code:
unsigned short CpuExecuteOpcode(PIC_CPU *Cpu, short opcode, unsigned short PC)
{
    unsigned char result;
    unsigned char op1, op2;
    unsigned char status = Cpu->Regs.STATUS;
    unsigned char oldW = Cpu->W;
    unsigned char oldStatus = status;
    if ((opcode & 0xC000) != 0)
    {
        printf("Invalid high bits in opcode\n");
        return 0xFFFF;
    }
    PC ++;
    if ((opcode & 0x3000) == 0x0000)
    {
        switch (opcode & 0xF00)
        {
            case 0x700:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = (Cpu->W & 0x0F) + (RegsGetValue(&Cpu->Regs, op1) & 0x0F);
                if ((result & 0x10) != 0)
                    status |= (1 << 1);
                else
                    status &= ~(1 << 1);
                result = (Cpu->W >> 4) + (RegsGetValue(&Cpu->Regs, op1) >> 4);
                result += (status & (1 << 1)) ? 1 : 0;
                if ((result & 0x10) != 0)
                    status |= (1 << 0);
                else
                    status &= ~(1 << 0);
                result = Cpu->W + RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0x500:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = Cpu->W & RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0x100:
                if ((opcode & 0x80) != 0)
                {
                    op1 = (opcode & 0x7F);
                    RegsSetValue(&Cpu->Regs, op1, 0);
                    status |= (1 << 2);
                }
                else
                {
                    Cpu->W = 0;
                    status |= (1 << 2);
                }
                break;
            case 0x900:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = ~ RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0x300:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) - 1;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0xB00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) - 1;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    PC ++;
                break;
            case 0xA00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) + 1;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0xF00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) + 1;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    PC ++;
                break;
            case 0x400:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = Cpu->W | RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0x800:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0x000:
                if ((opcode & 0x80) != 0)
                {
                    op1 = (opcode & 0x7F);
                    RegsSetValue(&Cpu->Regs, op1, Cpu->W);
                }
                else if ((opcode & 0xF) == 0)
                {
                }
                else
                {
                    switch (opcode & 0xFF)
                    {
                        case 0x64:
                            status |= ((1 << 3) | (1 << 4));
                            break;
                        case 0x09:
                            PC = StkPop(&Cpu->Stack);
                            break;
                        case 0x08:
                            PC = StkPop(&Cpu->Stack);
                            break;
                        case 0x63:
                            status |= (1 << 4);
                            status &= ~(1 << 3);
                            break;
                        default:
                            printf("Invalid 00 0000 opcode!\n");
                            return 0xFFFF;
                    }
                }
                break;
            case 0xD00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1);
                if ((result & 0x80) != 0)
                    status |= (1 << 0);
                else
                    status &= ~(1 << 0);
                result = result << 1;
                if ((Cpu->Regs.STATUS & (1 << 0)) != 0)
                    result |= 0x01;
                else
                    result &= ~0x01;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                break;
            case 0xC00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1);
                if (result & 0x01)
                    status |= (1 << 0);
                else
                    status &= ~(1 << 0);
                result = result >> 1;
                if ((Cpu->Regs.STATUS & (1 << 0)) != 0)
                    result |= 0x80;
                else
                    result &= ~0x80;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                break;
            case 0x200:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = (RegsGetValue(&Cpu->Regs, op1) & 0x0F) - (Cpu->W & 0x0F);
                if ((result & 0x10) == 0)
                    status |= (1 << 1);
                else
                    status &= ~(1 << 1);
                result = RegsGetValue(&Cpu->Regs, op1) >> 4;
                result -= (status & (1 << 1)) ? 0 : 1;
                result -= Cpu->W >> 4;
                if ((result & 0x10) == 0)
                    status |= (1 << 0);
                else
                    status &= ~(1 << 0);
                result = RegsGetValue(&Cpu->Regs, op1) - Cpu->W;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0xE00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = (RegsGetValue(&Cpu->Regs, op1) << 4) & 0xF0;
                result |= (RegsGetValue(&Cpu->Regs, op1) >> 4) & 0x0F;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                break;
            case 0x600:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = Cpu->W ^ RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            default:
                printf("Invalid 00 opcode!\n");
                return 0xFFFF;
        }
    }
    else if ((opcode & 0x3000) == 0x1000)
    {
        switch (opcode & 0x3C00)
        {
            case 0x1000:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x380) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) & ~(1 << op2);
                RegsSetValue(&Cpu->Regs, op1, result);
                break;
            case 0x1400:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x380) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) | (1 << op2);
                RegsSetValue(&Cpu->Regs, op1, result);
                break;
            case 0x1800:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x380) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) & (1 << op2);
                if (result == 0)
                    PC ++;
                break;
            case 0x1C00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x380) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) & (1 << op2);
                if (result != 0)
                    PC ++;
                break;
            default:
                printf("Invalid 01 opcode!\n");
                return 0xFFFF;
        }
    }
    else if ((opcode & 0x3000) == 0x2000)
    {
        if ((opcode & 0x800) != 0)
        {
            PC = PC & 0x1800;
            PC |= (opcode & 0x7FF);
        }
        else
        {
            StkPush(&Cpu->Stack, PC);
            PC = PC & 0x1800;
            PC |= (opcode & 0x7FF);
        }
    }
    else
    {
        if ((opcode & 0xE00) == 0xE00)
        {
            op1 = (opcode & 0xFF);
            result = (Cpu->W & 0x0F) + (op1 & 0x0F);
            if ((result & 0x10) != 0)
                status |= (1 << 1);
            else
                status &= ~(1 << 1);
            result = (Cpu->W >> 4) + (op1 >> 4);
            result += (status & (1 << 1)) ? 1 : 0;
            if ((result & 0x10) != 0)
                status |= (1 << 0);
            else
                status &= ~(1 << 0);
            result = Cpu->W + op1;
            Cpu->W = result;
            if (result == 0)
                status |= (1 << 2);
            else
                status &= ~(1 << 2);
        }
        else if ((opcode & 0xF00) == 0x900)
        {
            op1 = (opcode & 0xFF);
            result = Cpu->W & op1;
            Cpu->W = result;
            if (result == 0)
                status |= (1 << 2);
            else
                status &= ~(1 << 2);
        }
        else if ((opcode & 0xF00) == 0x800)
        {
            op1 = (opcode & 0xFF);
            result = Cpu->W | op1;
            Cpu->W = result;
            if (result == 0)
                status |= (1 << 2);
            else
                status &= ~(1 << 2);
        }
        else if ((opcode & 0xF00) == 0xA00)
        {
            op1 = (opcode & 0xFF);
            result = Cpu->W ^ op1;
            Cpu->W = result;
            if (result == 0)
                status |= (1 << 2);
            else
                status &= ~(1 << 2);
        }
        else if ((opcode & 0xC00) == 0x000)
        {
            op1 = (opcode & 0xFF);
            result = op1;
            Cpu->W = result;
        }
        else if ((opcode & 0xC00) == 0x400)
        {
            op1 = (opcode & 0xFF);
            Cpu->W = op1;
            PC = StkPop(&Cpu->Stack);
        }
        else if ((opcode & 0xC00) == 0xC00)
        {
            op1 = (opcode & 0xFF);
            result = (op1 & 0x0F) - (Cpu->W & 0x0F);
            if ((result & 0x10) == 0)
                status |= (1 << 1);
            else
                status &= ~(1 << 1);
            result = op1 >> 4;
            result -= (status & (1 << 1)) ? 0 : 1;
            result -= Cpu->W >> 4;
            if ((result & 0x10) == 0)
                status |= (1 << 0);
            else
                status &= ~(1 << 0);
            result = op1 - Cpu->W;
            Cpu->W = result;
            if (result == 0)
                status |= (1 << 2);
            else
                status &= ~(1 << 2);
        }
        else
        {
            printf("Invalid 11 opcode!\n");
            return 0xFFFF;
        }
    }
    if (status != oldStatus)
    {
        printf("STATUS:[");
        RegsPrintStatusRegister(Cpu->Regs.STATUS);
        printf("] -> [");
        Cpu->Regs.STATUS = status;
        RegsPrintStatusRegister(Cpu->Regs.STATUS);
        printf("]\n");
    }
    if (oldW != Cpu->W)
    {
        printf("W: %d -> %d\n", oldW, Cpu->W);
    }
    return PC;
}

canonical_original_code:
unsigned short CpuExecuteOpcode(struct _PIC_CPU *Cpu, short opcode, unsigned short PC)
{
    unsigned char result;
    unsigned char op1; unsigned char op2;
    unsigned char status = Cpu->Regs.STATUS;
    unsigned char oldW = Cpu->W;
    unsigned char oldStatus = status;
    if ((opcode & 0xC000) != 0)
    {
        printf("Invalid high bits in opcode\n");
        return 0xFFFF;
    }
    PC ++;
    if ((opcode & 0x3000) == 0x0000)
    {
        switch (opcode & 0xF00)
        {
            case 0x700:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = (Cpu->W & 0x0F) + (RegsGetValue(&Cpu->Regs, op1) & 0x0F);
                if ((result & 0x10) != 0)
                    status |= (1 << 1);
                else
                    status &= ~(1 << 1);
                result = (Cpu->W >> 4) + (RegsGetValue(&Cpu->Regs, op1) >> 4);
                result += (status & (1 << 1)) ? 1 : 0;
                if ((result & 0x10) != 0)
                    status |= (1 << 0);
                else
                    status &= ~(1 << 0);
                result = Cpu->W + RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0x500:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = Cpu->W & RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0x100:
                if ((opcode & 0x80) != 0)
                {
                    op1 = (opcode & 0x7F);
                    RegsSetValue(&Cpu->Regs, op1, 0);
                    status |= (1 << 2);
                }
                else
                {
                    Cpu->W = 0;
                    status |= (1 << 2);
                }
                break;
            case 0x900:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = ~ RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0x300:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) - 1;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0xB00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) - 1;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    PC ++;
                break;
            case 0xA00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) + 1;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0xF00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) + 1;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    PC ++;
                break;
            case 0x400:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = Cpu->W | RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0x800:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0x000:
                if ((opcode & 0x80) != 0)
                {
                    op1 = (opcode & 0x7F);
                    RegsSetValue(&Cpu->Regs, op1, Cpu->W);
                }
                else if ((opcode & 0xF) == 0)
                {
                }
                else
                {
                    switch (opcode & 0xFF)
                    {
                        case 0x64:
                            status |= ((1 << 3) | (1 << 4));
                            break;
                        case 0x09:
                            PC = StkPop(&Cpu->Stack);
                            break;
                        case 0x08:
                            PC = StkPop(&Cpu->Stack);
                            break;
                        case 0x63:
                            status |= (1 << 4);
                            status &= ~(1 << 3);
                            break;
                        default:
                            printf("Invalid 00 0000 opcode!\n");
                            return 0xFFFF;
                    }
                }
                break;
            case 0xD00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1);
                if ((result & 0x80) != 0)
                    status |= (1 << 0);
                else
                    status &= ~(1 << 0);
                result = result << 1;
                if ((Cpu->Regs.STATUS & (1 << 0)) != 0)
                    result |= 0x01;
                else
                    result &= ~0x01;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                break;
            case 0xC00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1);
                if (result & 0x01)
                    status |= (1 << 0);
                else
                    status &= ~(1 << 0);
                result = result >> 1;
                if ((Cpu->Regs.STATUS & (1 << 0)) != 0)
                    result |= 0x80;
                else
                    result &= ~0x80;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                break;
            case 0x200:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = (RegsGetValue(&Cpu->Regs, op1) & 0x0F) - (Cpu->W & 0x0F);
                if ((result & 0x10) == 0)
                    status |= (1 << 1);
                else
                    status &= ~(1 << 1);
                result = RegsGetValue(&Cpu->Regs, op1) >> 4;
                result -= (status & (1 << 1)) ? 0 : 1;
                result -= Cpu->W >> 4;
                if ((result & 0x10) == 0)
                    status |= (1 << 0);
                else
                    status &= ~(1 << 0);
                result = RegsGetValue(&Cpu->Regs, op1) - Cpu->W;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            case 0xE00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = (RegsGetValue(&Cpu->Regs, op1) << 4) & 0xF0;
                result |= (RegsGetValue(&Cpu->Regs, op1) >> 4) & 0x0F;
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                break;
            case 0x600:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x80) >> 7;
                result = Cpu->W ^ RegsGetValue(&Cpu->Regs, op1);
                if (op2 == 0)
                    Cpu->W = result;
                else
                    RegsSetValue(&Cpu->Regs, op1, result);
                if (result == 0)
                    status |= (1 << 2);
                else
                    status &= ~(1 << 2);
                break;
            default:
                printf("Invalid 00 opcode!\n");
                return 0xFFFF;
        }
    }
    else if ((opcode & 0x3000) == 0x1000)
    {
        switch (opcode & 0x3C00)
        {
            case 0x1000:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x380) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) & ~(1 << op2);
                RegsSetValue(&Cpu->Regs, op1, result);
                break;
            case 0x1400:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x380) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) | (1 << op2);
                RegsSetValue(&Cpu->Regs, op1, result);
                break;
            case 0x1800:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x380) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) & (1 << op2);
                if (result == 0)
                    PC ++;
                break;
            case 0x1C00:
                op1 = (opcode & 0x7F);
                op2 = (opcode & 0x380) >> 7;
                result = RegsGetValue(&Cpu->Regs, op1) & (1 << op2);
                if (result != 0)
                    PC ++;
                break;
            default:
                printf("Invalid 01 opcode!\n");
                return 0xFFFF;
        }
    }
    else if ((opcode & 0x3000) == 0x2000)
    {
        if ((opcode & 0x800) != 0)
        {
            PC = PC & 0x1800;
            PC |= (opcode & 0x7FF);
        }
        else
        {
            StkPush(&Cpu->Stack, PC);
            PC = PC & 0x1800;
            PC |= (opcode & 0x7FF);
        }
    }
    else
    {
        if ((opcode & 0xE00) == 0xE00)
        {
            op1 = (opcode & 0xFF);
            result = (Cpu->W & 0x0F) + (op1 & 0x0F);
            if ((result & 0x10) != 0)
                status |= (1 << 1);
            else
                status &= ~(1 << 1);
            result = (Cpu->W >> 4) + (op1 >> 4);
            result += (status & (1 << 1)) ? 1 : 0;
            if ((result & 0x10) != 0)
                status |= (1 << 0);
            else
                status &= ~(1 << 0);
            result = Cpu->W + op1;
            Cpu->W = result;
            if (result == 0)
                status |= (1 << 2);
            else
                status &= ~(1 << 2);
        }
        else if ((opcode & 0xF00) == 0x900)
        {
            op1 = (opcode & 0xFF);
            result = Cpu->W & op1;
            Cpu->W = result;
            if (result == 0)
                status |= (1 << 2);
            else
                status &= ~(1 << 2);
        }
        else if ((opcode & 0xF00) == 0x800)
        {
            op1 = (opcode & 0xFF);
            result = Cpu->W | op1;
            Cpu->W = result;
            if (result == 0)
                status |= (1 << 2);
            else
                status &= ~(1 << 2);
        }
        else if ((opcode & 0xF00) == 0xA00)
        {
            op1 = (opcode & 0xFF);
            result = Cpu->W ^ op1;
            Cpu->W = result;
            if (result == 0)
                status |= (1 << 2);
            else
                status &= ~(1 << 2);
        }
        else if ((opcode & 0xC00) == 0x000)
        {
            op1 = (opcode & 0xFF);
            result = op1;
            Cpu->W = result;
        }
        else if ((opcode & 0xC00) == 0x400)
        {
            op1 = (opcode & 0xFF);
            Cpu->W = op1;
            PC = StkPop(&Cpu->Stack);
        }
        else if ((opcode & 0xC00) == 0xC00)
        {
            op1 = (opcode & 0xFF);
            result = (op1 & 0x0F) - (Cpu->W & 0x0F);
            if ((result & 0x10) == 0)
                status |= (1 << 1);
            else
                status &= ~(1 << 1);
            result = op1 >> 4;
            result -= (status & (1 << 1)) ? 0 : 1;
            result -= Cpu->W >> 4;
            if ((result & 0x10) == 0)
                status |= (1 << 0);
            else
                status &= ~(1 << 0);
            result = op1 - Cpu->W;
            Cpu->W = result;
            if (result == 0)
                status |= (1 << 2);
            else
                status &= ~(1 << 2);
        }
        else
        {
            printf("Invalid 11 opcode!\n");
            return 0xFFFF;
        }
    }
    if (status != oldStatus)
    {
        printf("STATUS:[");
        RegsPrintStatusRegister(Cpu->Regs.STATUS);
        printf("] -> [");
        Cpu->Regs.STATUS = status;
        RegsPrintStatusRegister(Cpu->Regs.STATUS);
        printf("]\n");
    }
    if (oldW != Cpu->W)
    {
        printf("W: %d -> %d\n", oldW, Cpu->W);
    }
    return PC;
}

variable_types: opcode short

variable_types:
result
unsigned char

variable_types:
status
unsigned char

variable_types:
oldW
unsigned char

variable_types:
oldStatus
unsigned char


CpuExec

repo: cgutman/PIC-EMULATOR

decompiled_code:
__int64 __fastcall CpuExec(__int64 a1)
{
__int16 v1; // bp
__int16 v2; // ax
unsigned __int16 v3; // ax
char v4; // bp
__int64 result; // rax

v1 = CpuGetPC(a1);
v2 = CpuGetOpcode(a1, v1);
v3 = CpuExecuteOpcode(a1, v2, v1);
if ( v3 == 0xFFFF )
{
puts("Opcode unsupported");
result = 0xFFFFFFFFLL;
}
else if ( (*(_BYTE *)(a1 + 3) & 8) != 0 )
{
v4 = v3;
printf("PC -> 0x%x\n", v3);
CpuSetPC(a1, v4);
result = 0LL;
}
else
{
puts("CPU is halted");
result = 0xFFFFFFFFLL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func7(__int64 a1)
{
__int16 v1; // bp
__int16 v2; // ax
unsigned __int16 v3; // ax
char v4; // bp
__int64 result; // rax

v1 = func2(a1);
v2 = func4(a1, v1);
v3 = func6(a1, v2, v1);
if ( v3 == 0xFFFF )
{
puts("Opcode unsupported");
result = 0xFFFFFFFFLL;
}
else if ( (*(_BYTE *)(a1 + 3) & 8) != 0 )
{
v4 = v3;
printf("PC -> 0x%x\n", v3);
func3(a1, v4);
result = 0LL;
}
else
{
puts("CPU is halted");
result = 0xFFFFFFFFLL;
}
return result;
}

original_code:
int CpuExec(PIC_CPU *Cpu)
{
    unsigned short PC;
    PC = CpuGetPC(Cpu);
    PC = CpuExecuteOpcode(Cpu, CpuGetOpcode(Cpu, PC), PC);
    if (PC == 0xFFFF)
    {
        printf("Opcode unsupported\n");
        return -1;
    }
    if (!(Cpu->Regs.STATUS & (1 << 3)))
    {
        printf("CPU is halted\n");
        return -1;
    }
    printf("PC -> 0x%x\n", PC);
    CpuSetPC(Cpu, PC);
    return 0;
}

canonical_original_code:
int CpuExec(struct _PIC_CPU *Cpu)
{
    unsigned short PC;
    PC = CpuGetPC(Cpu);
    PC = CpuExecuteOpcode(Cpu, CpuGetOpcode(Cpu, PC), PC);
    if (PC == 0xFFFF)
    {
        printf("Opcode unsupported\n");
        return -1;
    }
    if (!(Cpu->Regs.STATUS & (1 << 3)))
    {
        printf("CPU is halted\n");
        return -1;
    }
    printf("PC -> 0x%x\n", PC);
    CpuSetPC(Cpu, PC);
    return 0;
}

variable_types: struct _PIC_CPU { struct _REGISTER_FILE { unsigned char INDF; unsigned char TMR0; unsigned char PCL; unsigned char STATUS; unsigned char FSR; unsigned char PORTA; unsigned char PORTB; unsigned char Unused1; unsigned char EEDATA; unsigned char EEADR; unsigned char PCLATH; unsigned char INTCON; unsigned char SRAM[68]; unsigned char Unused2[48]; unsigned char Unused3; unsigned char OPTION_REG; unsigned char Unused4[3]; unsigned char TRISA; unsigned char TRISB; unsigned char Unused5; unsigned char EECON1; unsigned char EECON2; } Regs; unsigned char W; struct _PIC_STACK { unsigned char Entries[8]; unsigned char NextTop; } Stack; struct _PIC_OPCODE { unsigned short Opcode; } ProgMem[1024]; } *

variable_types:
PC
unsigned short

return_type: int

user_defined_types: struct _PIC_CPU { struct _REGISTER_FILE Regs; unsigned char W; struct _PIC_STACK Stack; struct _PIC_OPCODE ProgMem[1024]; }


RegsPrintRegisterName

decompiled_code:
int __fastcall RegsPrintRegisterName(unsigned __int8 a1)
{
int result; // eax

result = a1;
switch ( a1 )
{
case 1u:
result = printf("TMR0");
break;
case 2u:
case 0x82u:
result = printf("PCL");
break;
case 3u:
case 0x83u:
result = printf("STATUS");
break;
case 4u:
case 0x84u:
result = printf("FSR");
break;
case 5u:
result = printf("PORTA");
break;
case 6u:
result = printf("PORTB");
break;
case 8u:
result = printf("EEDATA");
break;
case 9u:
result = printf("EEADR");
break;
case 0xAu:
case 0x8Au:
result = printf("PCLATH");
break;
case 0xBu:
case 0x8Bu:
result = printf("INTCON");
break;
case 0x81u:
result = printf("OPTION_REG");
break;
case 0x85u:
result = printf("TRISA");
break;
case 0x86u:
result = printf("TRISB");
break;
case 0x88u:
result = printf("EECON1");
break;
case 0x89u:
return result;
default:
result = a1 & 0x7F;
if ( result > 79 || result == 7 )
{
result = printf("Unimplemented");
}
else if ( (unsigned __int8)result > 0xBu )
{
result = printf("GPR[0x%x]", (unsigned int)(result - 12));
}
break;
}
return result;
}

canonical_decompiled_code:
int __fastcall func0(unsigned __int8 a1)
{
int result; // eax

result = a1;
switch ( a1 )
{
case 1u:
result = printf("TMR0");
break;
case 2u:
case 0x82u:
result = printf("PCL");
break;
case 3u:
case 0x83u:
result = printf("STATUS");
break;
case 4u:
case 0x84u:
result = printf("FSR");
break;
case 5u:
result = printf("PORTA");
break;
case 6u:
result = printf("PORTB");
break;
case 8u:
result = printf("EEDATA");
break;
case 9u:
result = printf("EEADR");
break;
case 0xAu:
case 0x8Au:
result = printf("PCLATH");
break;
case 0xBu:
case 0x8Bu:
result = printf("INTCON");
break;
case 0x81u:
result = printf("OPTION_REG");
break;
case 0x85u:
result = printf("TRISA");
break;
case 0x86u:
result = printf("TRISB");
break;
case 0x88u:
result = printf("EECON1");
break;
case 0x89u:
return result;
default:
result = a1 & 0x7F;
if ( result > 79 || result == 7 )
{
result = printf("Unimplemented");
}
else if ( (unsigned __int8)result > 0xBu )
{
result = printf("GPR[0x%x]", (unsigned int)(result - 12));
}
break;
}
return result;
}

original_code:
void RegsPrintRegisterName(unsigned char RegFileAddr)
{
    switch (RegFileAddr)
    {
        case 0x01:
            printf("TMR0");
            return;
        case 0x81:
            printf("OPTION_REG");
            return;
        case 0x02:
        case 0x02 | 0x80:
            printf("PCL");
            return;
        case 0x03:
        case 0x03 | 0x80:
            printf("STATUS");
            return;
        case 0x04:
        case 0x04 | 0x80:
            printf("FSR");
            return;
        case 0x05:
            printf("PORTA");
            return;
        case 0x85:
            printf("TRISA");
            return;
        case 0x06:
            printf("PORTB");
            return;
        case 0x86:
            printf("TRISB");
            return;
        case 0x08:
            printf("EEDATA");
            return;
        case 0x88:
            printf("EECON1");
            return;
        case 0x09:
            printf("EEADR");
            return;
        case 0x89:
            return;
        case 0x0A:
        case 0x0A | 0x80:
            printf("PCLATH");
            return;
        case 0x0B:
        case 0x0B | 0x80:
            printf("INTCON");
            return;
    }
    if (((RegFileAddr & 0x7F) >= 0x50) ||
        ((RegFileAddr & 0x7F) == 0x07))
    {
        printf("Unimplemented");
    }
    else if ((RegFileAddr & 0x7F) >= 0x0C)
    {
        RegFileAddr &= 0x7F;
        printf("GPR[0x%x]", (RegFileAddr - 0x0C));
    }
}

variable_types:
RegFileAddr
unsigned char

return_type: void


RegsPrintStatusRegister

decompiled_code:
int __fastcall RegsPrintStatusRegister(char a1)
{
int result; // eax

if ( (a1 & 0x20) != 0 )
result = printf(" RP0");
if ( (a1 & 0x10) != 0 )
result = printf(" ~TO");
if ( (a1 & 8) != 0 )
result = printf(" ~PD");
if ( (a1 & 4) != 0 )
result = printf(" Z");
if ( (a1 & 2) != 0 )
result = printf(" DC");
if ( (a1 & 1) != 0 )
result = printf(" C");
return result;
}

canonical_decompiled_code:
int __fastcall func1(char a1)
{
int result; // eax

if ( (a1 & 0x20) != 0 )
result = printf(" RP0");
if ( (a1 & 0x10) != 0 )
result = printf(" ~TO");
if ( (a1 & 8) != 0 )
result = printf(" ~PD");
if ( (a1 & 4) != 0 )
result = printf(" Z");
if ( (a1 & 2) != 0 )
result = printf(" DC");
if ( (a1 & 1) != 0 )
result = printf(" C");
return result;
}

original_code:
void RegsPrintStatusRegister(unsigned char StatusVal)
{
    if (StatusVal & (1 << 5))
        printf(" RP0");
    if (StatusVal & (1 << 4))
        printf(" ~TO");
    if (StatusVal & (1 << 3))
        printf(" ~PD");
    if (StatusVal & (1 << 2))
        printf(" Z");
    if (StatusVal & (1 << 1))
        printf(" DC");
    if (StatusVal & (1 << 0))
        printf(" C");
}

variable_types:
StatusVal
unsigned char


RegsSetValue

decompiled_code:
unsigned int __fastcall RegsSetValue(char *a1, char a2, unsigned __int8 a3)
{
char v4; // bl
unsigned __int8 v5; // al
unsigned __int8 v6; // bl
unsigned int result; // eax
char *v8; // rbp
char v9; // r13
unsigned __int8 *v10; // rbx

v4 = a2;
if ( (a2 & 0x7F) == 0 )
v4 = a1[4];
v5 = v4 | 0x80;
v6 = v4 & 0x7F;
if ( (a1[3] & 0x20) != 0 )
v6 = v5;
result = v6;
switch ( v6 )
{
case 1u:
printf("TMR0");
v8 = a1 + 1;
v9 = -1;
goto LABEL_7;
case 2u:
case 0x82u:
printf("PCL");
v8 = a1 + 2;
v9 = -1;
goto LABEL_12;
case 3u:
case 0x83u:
printf("STATUS");
v8 = a1 + 3;
v9 = 63;
goto LABEL_12;
case 4u:
case 0x84u:
printf("FSR");
v8 = a1 + 4;
v9 = -1;
goto LABEL_12;
case 5u:
printf("PORTA");
v8 = a1 + 5;
v9 = 31;
goto LABEL_7;
case 6u:
printf("PORTB");
v8 = a1 + 6;
v9 = -1;
goto LABEL_7;
case 8u:
printf("EEDATA");
v8 = a1 + 8;
v9 = -1;
goto LABEL_7;
case 9u:
printf("EEADR");
v8 = a1 + 9;
v9 = -1;
goto LABEL_7;
case 0xAu:
case 0x8Au:
printf("PCLATH");
v8 = a1 + 10;
v9 = 30;
goto LABEL_12;
case 0xBu:
case 0x8Bu:
printf("INTCON");
v8 = a1 + 11;
v9 = -1;
LABEL_12:
if ( (v6 & 0x7F) != 3 )
goto LABEL_7;
printf(": [");
RegsPrintStatusRegister(*v8);
printf("] -> [");
RegsPrintStatusRegister(a3 & v9);
result = puts("]");
goto LABEL_8;
case 0x81u:
printf("OPTION_REG");
v8 = a1 + 129;
v9 = -1;
goto LABEL_7;
case 0x85u:
printf("TRISA");
v8 = a1 + 133;
v9 = 31;
goto LABEL_7;
case 0x86u:
printf("TRISB");
v8 = a1 + 134;
v9 = -1;
goto LABEL_7;
case 0x88u:
printf("EECON1");
v8 = a1 + 136;
v9 = 31;
LABEL_7:
result = printf(": 0x%x -> 0x%x\n", (unsigned __int8)*v8, (unsigned __int8)(a3 & v9));
LABEL_8:
*v8 = *v8 & ~v9 | a3 & v9;
break;
case 0x89u:
return result;
default:
result = v6 & 0x7F;
if ( result <= 0x4F && result != 7 )
{
if ( (v6 & 0x7Fu) >= 0xC )
v6 &= 0x7Fu;
RegsPrintRegisterName(v6);
v10 = (unsigned __int8 *)&a1[v6];
result = printf(": %d -> %d\n", *v10, a3);
*v10 = a3;
}
break;
}
return result;
}

canonical_decompiled_code:
unsigned int __fastcall func3(char *a1, char a2, unsigned __int8 a3)
{
char v4; // bl
unsigned __int8 v5; // al
unsigned __int8 v6; // bl
unsigned int result; // eax
char *v8; // rbp
char v9; // r13
unsigned __int8 *v10; // rbx

v4 = a2;
if ( (a2 & 0x7F) == 0 )
v4 = a1[4];
v5 = v4 | 0x80;
v6 = v4 & 0x7F;
if ( (a1[3] & 0x20) != 0 )
v6 = v5;
result = v6;
switch ( v6 )
{
case 1u:
printf("TMR0");
v8 = a1 + 1;
v9 = -1;
goto LABEL_7;
case 2u:
case 0x82u:
printf("PCL");
v8 = a1 + 2;
v9 = -1;
goto LABEL_12;
case 3u:
case 0x83u:
printf("STATUS");
v8 = a1 + 3;
v9 = 63;
goto LABEL_12;
case 4u:
case 0x84u:
printf("FSR");
v8 = a1 + 4;
v9 = -1;
goto LABEL_12;
case 5u:
printf("PORTA");
v8 = a1 + 5;
v9 = 31;
goto LABEL_7;
case 6u:
printf("PORTB");
v8 = a1 + 6;
v9 = -1;
goto LABEL_7;
case 8u:
printf("EEDATA");
v8 = a1 + 8;
v9 = -1;
goto LABEL_7;
case 9u:
printf("EEADR");
v8 = a1 + 9;
v9 = -1;
goto LABEL_7;
case 0xAu:
case 0x8Au:
printf("PCLATH");
v8 = a1 + 10;
v9 = 30;
goto LABEL_12;
case 0xBu:
case 0x8Bu:
printf("INTCON");
v8 = a1 + 11;
v9 = -1;
LABEL_12:
if ( (v6 & 0x7F) != 3 )
goto LABEL_7;
printf(": [");
func1(*v8);
printf("] -> [");
func1(a3 & v9);
result = puts("]");
goto LABEL_8;
case 0x81u:
printf("OPTION_REG");
v8 = a1 + 129;
v9 = -1;
goto LABEL_7;
case 0x85u:
printf("TRISA");
v8 = a1 + 133;
v9 = 31;
goto LABEL_7;
case 0x86u:
printf("TRISB");
v8 = a1 + 134;
v9 = -1;
goto LABEL_7;
case 0x88u:
printf("EECON1");
v8 = a1 + 136;
v9 = 31;
LABEL_7:
result = printf(": 0x%x -> 0x%x\n", (unsigned __int8)*v8, (unsigned __int8)(a3 & v9));
LABEL_8:
*v8 = *v8 & ~v9 | a3 & v9;
break;
case 0x89u:
return result;
default:
result = v6 & 0x7F;
if ( result <= 0x4F && result != 7 )
{
if ( (v6 & 0x7Fu) >= 0xC )
v6 &= 0x7Fu;
func0(v6);
v10 = (unsigned __int8 *)&a1[v6];
result = printf(": %d -> %d\n", *v10, a3);
*v10 = a3;
}
break;
}
return result;
}

original_code:
void RegsSetValue(REGISTER_FILE *Regs, unsigned char RegFileAddr, unsigned char Value)
{
    unsigned char WriteMask;
    unsigned char *Destination;
    if ((RegFileAddr & 0x7F) == 0)
    {
        RegFileAddr = Regs->FSR;
    }
    if ((Regs->STATUS & (1 << 5)) != 0)
    {
        RegFileAddr |= 0x80;
    }
    else
    {
        RegFileAddr &= ~0x80;
    }
    Destination = ((void *)0);
    switch (RegFileAddr)
    {
        case 0x01:
            printf("TMR0");
            WriteMask = 0xFF;
            Destination = &Regs->TMR0;
            break;
        case 0x81:
            printf("OPTION_REG");
            WriteMask = 0xFF;
            Destination = &Regs->OPTION_REG;
            break;
        case 0x02:
        case 0x02 | 0x80:
            printf("PCL");
            WriteMask = 0xFF;
            Destination = &Regs->PCL;
            break;
        case 0x03:
        case 0x03 | 0x80:
            printf("STATUS");
            WriteMask = 0x3F;
            Destination = &Regs->STATUS;
            break;
        case 0x04:
        case 0x04 | 0x80:
            printf("FSR");
            WriteMask = 0xFF;
            Destination = &Regs->FSR;
            break;
        case 0x05:
            printf("PORTA");
            WriteMask = 0x1F;
            Destination = &Regs->PORTA;
            break;
        case 0x85:
            printf("TRISA");
            WriteMask = 0x1F;
            Destination = &Regs->TRISA;
            break;
        case 0x06:
            printf("PORTB");
            WriteMask = 0xFF;
            Destination = &Regs->PORTB;
            break;
        case 0x86:
            printf("TRISB");
            WriteMask = 0xFF;
            Destination = &Regs->TRISB;
            break;
        case 0x08:
            printf("EEDATA");
            WriteMask = 0xFF;
            Destination = &Regs->EEDATA;
            break;
        case 0x88:
            printf("EECON1");
            WriteMask = 0x1F;
            Destination = &Regs->EECON1;
            break;
        case 0x09:
            printf("EEADR");
            WriteMask = 0xFF;
            Destination = &Regs->EEADR;
            break;
        case 0x89:
            return;
        case 0x0A:
        case 0x0A | 0x80:
            printf("PCLATH");
            WriteMask = 0x1E;
            Destination = &Regs->PCLATH;
            break;
        case 0x0B:
        case 0x0B | 0x80:
            printf("INTCON");
            WriteMask = 0xFF;
            Destination = &Regs->INTCON;
            break;
    }
    if (Destination != ((void *)0))
    {
        if ((RegFileAddr & 0x7F) == 0x03)
        {
            printf(": [");
            RegsPrintStatusRegister(*Destination);
            printf("] -> [");
            RegsPrintStatusRegister(Value & WriteMask);
            printf("]\n");
        }
        else
        {
            printf(": 0x%x -> 0x%x\n", *Destination, (Value & WriteMask));
        }
        *Destination &= ~WriteMask;
        *Destination |= (Value & WriteMask);
    }
    else
    {
        if (((RegFileAddr & 0x7F) >= 0x50) ||
            ((RegFileAddr & 0x7F) == 0x07))
        {
            return;
        }
        else if ((RegFileAddr & 0x7F) >= 0x0C)
        {
            RegFileAddr &= 0x7F;
        }
        RegsPrintRegisterName(RegFileAddr);
        printf(": %d -> %d\n", ((unsigned char *)Regs)[RegFileAddr], Value);
        ((unsigned char *)Regs)[RegFileAddr] = Value;
    }
}

canonical_original_code:
void RegsSetValue(struct _REGISTER_FILE *Regs, unsigned char RegFileAddr, unsigned char Value)
{
    unsigned char WriteMask;
    unsigned char *Destination;
    if ((RegFileAddr & 0x7F) == 0)
    {
        RegFileAddr = Regs->FSR;
    }
    if ((Regs->STATUS & (1 << 5)) != 0)
    {
        RegFileAddr |= 0x80;
    }
    else
    {
        RegFileAddr &= ~0x80;
    }
    Destination = ((void *)0);
    switch (RegFileAddr)
    {
        case 0x01:
            printf("TMR0");
            WriteMask = 0xFF;
            Destination = &Regs->TMR0;
            break;
        case 0x81:
            printf("OPTION_REG");
            WriteMask = 0xFF;
            Destination = &Regs->OPTION_REG;
            break;
        case 0x02:
        case 0x02 | 0x80:
            printf("PCL");
            WriteMask = 0xFF;
            Destination = &Regs->PCL;
            break;
        case 0x03:
        case 0x03 | 0x80:
            printf("STATUS");
            WriteMask = 0x3F;
            Destination = &Regs->STATUS;
            break;
        case 0x04:
        case 0x04 | 0x80:
            printf("FSR");
            WriteMask = 0xFF;
            Destination = &Regs->FSR;
            break;
        case 0x05:
            printf("PORTA");
            WriteMask = 0x1F;
            Destination = &Regs->PORTA;
            break;
        case 0x85:
            printf("TRISA");
            WriteMask = 0x1F;
            Destination = &Regs->TRISA;
            break;
        case 0x06:
            printf("PORTB");
            WriteMask = 0xFF;
            Destination = &Regs->PORTB;
            break;
        case 0x86:
            printf("TRISB");
            WriteMask = 0xFF;
            Destination = &Regs->TRISB;
            break;
        case 0x08:
            printf("EEDATA");
            WriteMask = 0xFF;
            Destination = &Regs->EEDATA;
            break;
        case 0x88:
            printf("EECON1");
            WriteMask = 0x1F;
            Destination = &Regs->EECON1;
            break;
        case 0x09:
            printf("EEADR");
            WriteMask = 0xFF;
            Destination = &Regs->EEADR;
            break;
        case 0x89:
            return;
        case 0x0A:
        case 0x0A | 0x80:
            printf("PCLATH");
            WriteMask = 0x1E;
            Destination = &Regs->PCLATH;
            break;
        case 0x0B:
        case 0x0B | 0x80:
            printf("INTCON");
            WriteMask = 0xFF;
            Destination = &Regs->INTCON;
            break;
    }
    if (Destination != ((void *)0))
    {
        if ((RegFileAddr & 0x7F) == 0x03)
        {
            printf(": [");
            RegsPrintStatusRegister(*Destination);
            printf("] -> [");
            RegsPrintStatusRegister(Value & WriteMask);
            printf("]\n");
        }
        else
        {
            printf(": 0x%x -> 0x%x\n", *Destination, (Value & WriteMask));
        }
        *Destination &= ~WriteMask;
        *Destination |= (Value & WriteMask);
    }
    else
    {
        if (((RegFileAddr & 0x7F) >= 0x50) ||
            ((RegFileAddr & 0x7F) == 0x07))
        {
            return;
        }
        else if ((RegFileAddr & 0x7F) >= 0x0C)
        {
            RegFileAddr &= 0x7F;
        }
        RegsPrintRegisterName(RegFileAddr);
        printf(": %d -> %d\n", ((unsigned char *)Regs)[RegFileAddr], Value);
        ((unsigned char *)Regs)[RegFileAddr] = Value;
    }
}

variable_types: struct _REGISTER_FILE { unsigned char INDF; unsigned char TMR0; unsigned char PCL; unsigned char STATUS; unsigned char FSR; unsigned char PORTA; unsigned char PORTB; unsigned char Unused1; unsigned char EEDATA; unsigned char EEADR; unsigned char PCLATH; unsigned char INTCON; unsigned char SRAM[68]; unsigned char Unused2[48]; unsigned char Unused3; unsigned char OPTION_REG; unsigned char Unused4[3]; unsigned char TRISA; unsigned char TRISB; unsigned char Unused5; unsigned char EECON1; unsigned char EECON2; } *

variable_types:
Value
unsigned char

variable_types:
WriteMask
unsigned char

variable_types:
Destination
unsigned char *


RegsGetValue

decompiled_code:
char __fastcall RegsGetValue(_BYTE *a1, char a2)
{
char v2; // al
unsigned __int8 v3; // dl
unsigned __int8 v4; // al
_BYTE *v5; // rdi
char v6; // al
char result; // al

v2 = a2;
if ( (a2 & 0x7F) == 0 )
v2 = a1[4];
v3 = v2 | 0x80;
v4 = v2 & 0x7F;
if ( (a1[3] & 0x20) != 0 )
v4 = v3;
switch ( v4 )
{
case 1u:
v5 = a1 + 1;
v6 = -1;
goto LABEL_7;
case 2u:
case 0x82u:
v5 = a1 + 2;
v6 = -1;
goto LABEL_7;
case 3u:
case 0x83u:
v5 = a1 + 3;
v6 = 63;
goto LABEL_7;
case 4u:
case 0x84u:
v5 = a1 + 4;
v6 = -1;
goto LABEL_7;
case 5u:
v5 = a1 + 5;
v6 = 31;
goto LABEL_7;
case 6u:
v5 = a1 + 6;
v6 = -1;
goto LABEL_7;
case 8u:
v5 = a1 + 8;
v6 = -1;
goto LABEL_7;
case 9u:
v5 = a1 + 9;
v6 = -1;
goto LABEL_7;
case 0xAu:
case 0x8Au:
v5 = a1 + 10;
v6 = 0;
goto LABEL_7;
case 0xBu:
case 0x8Bu:
v5 = a1 + 11;
v6 = -1;
goto LABEL_7;
case 0x81u:
v5 = a1 + 129;
v6 = -1;
goto LABEL_7;
case 0x85u:
v5 = a1 + 133;
v6 = 31;
goto LABEL_7;
case 0x86u:
v5 = a1 + 134;
v6 = -1;
goto LABEL_7;
case 0x88u:
v5 = a1 + 136;
v6 = 31;
LABEL_7:
result = *v5 & v6;
break;
case 0x89u:
result = 0;
break;
default:
if ( (v4 & 0x7Fu) > 0x4F || (v4 & 0x7F) == 7 )
{
result = 0;
}
else
{
if ( (v4 & 0x7Fu) >= 0xC )
v4 &= 0x7Fu;
result = a1[v4];
}
break;
}
return result;
}

canonical_decompiled_code:
char __fastcall func4(_BYTE *a1, char a2)
{
char v2; // al
unsigned __int8 v3; // dl
unsigned __int8 v4; // al
_BYTE *v5; // rdi
char v6; // al
char result; // al

v2 = a2;
if ( (a2 & 0x7F) == 0 )
v2 = a1[4];
v3 = v2 | 0x80;
v4 = v2 & 0x7F;
if ( (a1[3] & 0x20) != 0 )
v4 = v3;
switch ( v4 )
{
case 1u:
v5 = a1 + 1;
v6 = -1;
goto LABEL_7;
case 2u:
case 0x82u:
v5 = a1 + 2;
v6 = -1;
goto LABEL_7;
case 3u:
case 0x83u:
v5 = a1 + 3;
v6 = 63;
goto LABEL_7;
case 4u:
case 0x84u:
v5 = a1 + 4;
v6 = -1;
goto LABEL_7;
case 5u:
v5 = a1 + 5;
v6 = 31;
goto LABEL_7;
case 6u:
v5 = a1 + 6;
v6 = -1;
goto LABEL_7;
case 8u:
v5 = a1 + 8;
v6 = -1;
goto LABEL_7;
case 9u:
v5 = a1 + 9;
v6 = -1;
goto LABEL_7;
case 0xAu:
case 0x8Au:
v5 = a1 + 10;
v6 = 0;
goto LABEL_7;
case 0xBu:
case 0x8Bu:
v5 = a1 + 11;
v6 = -1;
goto LABEL_7;
case 0x81u:
v5 = a1 + 129;
v6 = -1;
goto LABEL_7;
case 0x85u:
v5 = a1 + 133;
v6 = 31;
goto LABEL_7;
case 0x86u:
v5 = a1 + 134;
v6 = -1;
goto LABEL_7;
case 0x88u:
v5 = a1 + 136;
v6 = 31;
LABEL_7:
result = *v5 & v6;
break;
case 0x89u:
result = 0;
break;
default:
if ( (v4 & 0x7Fu) > 0x4F || (v4 & 0x7F) == 7 )
{
result = 0;
}
else
{
if ( (v4 & 0x7Fu) >= 0xC )
v4 &= 0x7Fu;
result = a1[v4];
}
break;
}
return result;
}

original_code:
char RegsGetValue(REGISTER_FILE *Regs, unsigned char RegFileAddr)
{
    unsigned char ReadMask;
    unsigned char *Source;
    if ((RegFileAddr & 0x7F) == 0)
    {
        RegFileAddr = Regs->FSR;
    }
    if ((Regs->STATUS & (1 << 5)) != 0)
    {
        RegFileAddr |= 0x80;
    }
    else
    {
        RegFileAddr &= ~0x80;
    }
    Source = ((void *)0);
    switch (RegFileAddr)
    {
        case 0x01:
            ReadMask = 0xFF;
            Source = &Regs->TMR0;
            break;
        case 0x81:
            ReadMask = 0xFF;
            Source = &Regs->OPTION_REG;
            break;
        case 0x02:
        case 0x02 | 0x80:
            ReadMask = 0xFF;
            Source = &Regs->PCL;
            break;
        case 0x03:
        case 0x03 | 0x80:
            ReadMask = 0x3F;
            Source = &Regs->STATUS;
            break;
        case 0x04:
        case 0x04 | 0x80:
            ReadMask = 0xFF;
            Source = &Regs->FSR;
            break;
        case 0x05:
            ReadMask = 0x1F;
            Source = &Regs->PORTA;
            break;
        case 0x85:
            ReadMask = 0x1F;
            Source = &Regs->TRISA;
            break;
        case 0x06:
            ReadMask = 0xFF;
            Source = &Regs->PORTB;
            break;
        case 0x86:
            ReadMask = 0xFF;
            Source = &Regs->TRISB;
            break;
        case 0x08:
            ReadMask = 0xFF;
            Source = &Regs->EEDATA;
            break;
        case 0x88:
            ReadMask = 0x1F;
            Source = &Regs->EECON1;
            break;
        case 0x09:
            ReadMask = 0xFF;
            Source = &Regs->EEADR;
            break;
        case 0x89:
            return 0;
        case 0x0A:
        case 0x0A | 0x80:
            ReadMask = 0x00;
            Source = &Regs->PCLATH;
            break;
        case 0x0B:
        case 0x0B | 0x80:
            ReadMask = 0xFF;
            Source = &Regs->INTCON;
            break;
    }
    if (Source != ((void *)0))
    {
        return (*Source & ReadMask);
    }
    else
    {
        if (((RegFileAddr & 0x7F) >= 0x50) ||
            ((RegFileAddr & 0x7F) == 0x07))
        {
            return 0;
        }
        else if ((RegFileAddr & 0x7F) >= 0x0C)
        {
            RegFileAddr &= 0x7F;
        }
        return ((unsigned char *)Regs)[RegFileAddr];
    }
}

canonical_original_code:
char RegsGetValue(struct _REGISTER_FILE *Regs, unsigned char RegFileAddr)
{
    unsigned char ReadMask;
    unsigned char *Source;
    if ((RegFileAddr & 0x7F) == 0)
    {
        RegFileAddr = Regs->FSR;
    }
    if ((Regs->STATUS & (1 << 5)) != 0)
    {
        RegFileAddr |= 0x80;
    }
    else
    {
        RegFileAddr &= ~0x80;
    }
    Source = ((void *)0);
    switch (RegFileAddr)
    {
        case 0x01:
            ReadMask = 0xFF;
            Source = &Regs->TMR0;
            break;
        case 0x81:
            ReadMask = 0xFF;
            Source = &Regs->OPTION_REG;
            break;
        case 0x02:
        case 0x02 | 0x80:
            ReadMask = 0xFF;
            Source = &Regs->PCL;
            break;
        case 0x03:
        case 0x03 | 0x80:
            ReadMask = 0x3F;
            Source = &Regs->STATUS;
            break;
        case 0x04:
        case 0x04 | 0x80:
            ReadMask = 0xFF;
            Source = &Regs->FSR;
            break;
        case 0x05:
            ReadMask = 0x1F;
            Source = &Regs->PORTA;
            break;
        case 0x85:
            ReadMask = 0x1F;
            Source = &Regs->TRISA;
            break;
        case 0x06:
            ReadMask = 0xFF;
            Source = &Regs->PORTB;
            break;
        case 0x86:
            ReadMask = 0xFF;
            Source = &Regs->TRISB;
            break;
        case 0x08:
            ReadMask = 0xFF;
            Source = &Regs->EEDATA;
            break;
        case 0x88:
            ReadMask = 0x1F;
            Source = &Regs->EECON1;
            break;
        case 0x09:
            ReadMask = 0xFF;
            Source = &Regs->EEADR;
            break;
        case 0x89:
            return 0;
        case 0x0A:
        case 0x0A | 0x80:
            ReadMask = 0x00;
            Source = &Regs->PCLATH;
            break;
        case 0x0B:
        case 0x0B | 0x80:
            ReadMask = 0xFF;
            Source = &Regs->INTCON;
            break;
    }
    if (Source != ((void *)0))
    {
        return (*Source & ReadMask);
    }
    else
    {
        if (((RegFileAddr & 0x7F) >= 0x50) ||
            ((RegFileAddr & 0x7F) == 0x07))
        {
            return 0;
        }
        else if ((RegFileAddr & 0x7F) >= 0x0C)
        {
            RegFileAddr &= 0x7F;
        }
        return ((unsigned char *)Regs)[RegFileAddr];
    }
}

variable_types:
ReadMask
unsigned char

variable_types:
Source
unsigned char *

return_type: char

user_defined_types: struct _REGISTER_FILE { unsigned char INDF; unsigned char TMR0; unsigned char PCL; unsigned char STATUS; unsigned char FSR; unsigned char PORTA; unsigned char PORTB; unsigned char Unused1; unsigned char EEDATA; unsigned char EEADR; unsigned char PCLATH; unsigned char INTCON; unsigned char SRAM[68]; unsigned char Unused2[48]; unsigned char Unused3; unsigned char OPTION_REG; unsigned char Unused4[3]; unsigned char TRISA; unsigned char TRISB; unsigned char Unused5; unsigned char EECON1; unsigned char EECON2; }


OpGenerateOpcode

decompiled_code:
__int16 __fastcall OpGenerateOpcode(char *s1, char a2, __int16 a3)
{
__int16 result; // ax
int v5; // edx

if ( !strcmp(s1, "ADDWF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 7;
}
else if ( !strcmp(s1, "ANDWF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 5;
}
else if ( !strcmp(s1, "CLRF") )
{
result = a2 & 0x7F | 0x180;
}
else
{
result = 256;
if ( strcmp(s1, "CLRW") )
{
if ( !strcmp(s1, "COMF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 9;
}
else if ( !strcmp(s1, "DECF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 3;
}
else if ( !strcmp(s1, "DECFSZ") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xB;
}
else if ( !strcmp(s1, "INCF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xA;
}
else if ( !strcmp(s1, "INCFSZ") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xF;
}
else if ( !strcmp(s1, "IORWF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 4;
}
else if ( !strcmp(s1, "MOVF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 8;
}
else if ( !strcmp(s1, "MOVWF") )
{
result = a2 & 0x7F;
LOBYTE(result) = result | 0x80;
}
else
{
v5 = strcmp(s1, "NOP");
result = 0;
if ( v5 )
{
if ( !strcmp(s1, "RLF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xD;
}
else if ( !strcmp(s1, "RRF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xC;
}
else if ( !strcmp(s1, "SUBWF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 2;
}
else if ( !strcmp(s1, "SWAPF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xE;
}
else if ( !strcmp(s1, "XORWF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 9;
}
else if ( !strcmp(s1, "BCF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x380) >> 8) | 0x10;
}
else if ( !strcmp(s1, "BSF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x380) >> 8) | 0x14;
}
else if ( !strcmp(s1, "BTFSC") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x380) >> 8) | 0x18;
}
else if ( !strcmp(s1, "BTFSS") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x380) >> 8) | 0x1C;
}
else if ( !strcmp(s1, "ADDLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 62;
}
else if ( !strcmp(s1, "ANDLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 57;
}
else if ( !strcmp(s1, "CALL") )
{
result = a2 & 0x7FF;
HIBYTE(result) |= 0x20u;
}
else if ( !strcmp(s1, "CLRWDT") )
{
result = 100;
}
else if ( !strcmp(s1, "GOTO") )
{
result = a2 & 0x7FF;
HIBYTE(result) |= 0x28u;
}
else if ( !strcmp(s1, "IORLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 56;
}
else if ( !strcmp(s1, "MOVLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 48;
}
else if ( !strcmp(s1, "RETFIE") )
{
result = 9;
}
else if ( !strcmp(s1, "RETLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 52;
}
else if ( !strcmp(s1, "RETURN") )
{
result = 8;
}
else if ( !strcmp(s1, "SLEEP") )
{
result = 99;
}
else if ( !strcmp(s1, "SUBLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 60;
}
else if ( !strcmp(s1, "XORLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 58;
}
else
{
result = -1;
}
}
}
}
}
return result;
}

canonical_decompiled_code:
__int16 __fastcall func0(char *s1, char a2, __int16 a3)
{
__int16 result; // ax
int v5; // edx

if ( !strcmp(s1, "ADDWF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 7;
}
else if ( !strcmp(s1, "ANDWF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 5;
}
else if ( !strcmp(s1, "CLRF") )
{
result = a2 & 0x7F | 0x180;
}
else
{
result = 256;
if ( strcmp(s1, "CLRW") )
{
if ( !strcmp(s1, "COMF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 9;
}
else if ( !strcmp(s1, "DECF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 3;
}
else if ( !strcmp(s1, "DECFSZ") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xB;
}
else if ( !strcmp(s1, "INCF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xA;
}
else if ( !strcmp(s1, "INCFSZ") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xF;
}
else if ( !strcmp(s1, "IORWF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 4;
}
else if ( !strcmp(s1, "MOVF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 8;
}
else if ( !strcmp(s1, "MOVWF") )
{
result = a2 & 0x7F;
LOBYTE(result) = result | 0x80;
}
else
{
v5 = strcmp(s1, "NOP");
result = 0;
if ( v5 )
{
if ( !strcmp(s1, "RLF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xD;
}
else if ( !strcmp(s1, "RRF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xC;
}
else if ( !strcmp(s1, "SUBWF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 2;
}
else if ( !strcmp(s1, "SWAPF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 0xE;
}
else if ( !strcmp(s1, "XORWF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x80) >> 8) | 9;
}
else if ( !strcmp(s1, "BCF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x380) >> 8) | 0x10;
}
else if ( !strcmp(s1, "BSF") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x380) >> 8) | 0x14;
}
else if ( !strcmp(s1, "BTFSC") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x380) >> 8) | 0x18;
}
else if ( !strcmp(s1, "BTFSS") )
{
LOBYTE(result) = a2 & 0x7F | ((_BYTE)a3 << 7);
HIBYTE(result) = ((unsigned __int16)((a3 << 7) & 0x380) >> 8) | 0x1C;
}
else if ( !strcmp(s1, "ADDLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 62;
}
else if ( !strcmp(s1, "ANDLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 57;
}
else if ( !strcmp(s1, "CALL") )
{
result = a2 & 0x7FF;
HIBYTE(result) |= 0x20u;
}
else if ( !strcmp(s1, "CLRWDT") )
{
result = 100;
}
else if ( !strcmp(s1, "GOTO") )
{
result = a2 & 0x7FF;
HIBYTE(result) |= 0x28u;
}
else if ( !strcmp(s1, "IORLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 56;
}
else if ( !strcmp(s1, "MOVLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 48;
}
else if ( !strcmp(s1, "RETFIE") )
{
result = 9;
}
else if ( !strcmp(s1, "RETLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 52;
}
else if ( !strcmp(s1, "RETURN") )
{
result = 8;
}
else if ( !strcmp(s1, "SLEEP") )
{
result = 99;
}
else if ( !strcmp(s1, "SUBLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 60;
}
else if ( !strcmp(s1, "XORLW") )
{
LOBYTE(result) = a2;
HIBYTE(result) = 58;
}
else
{
result = -1;
}
}
}
}
}
return result;
}

original_code:
unsigned short OpGenerateOpcode(char *opname, char operand1, char operand2)
{
    unsigned short opcode = 0xFFFF;
    if (!strcmp(opname, "ADDWF"))
    {
        opcode = 0x700;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "ANDWF"))
    {
        opcode = 0x500;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "CLRF"))
    {
        opcode = 0x180;
        opcode |= (operand1 & 0x7F);
    }
    else if (!strcmp(opname, "CLRW"))
    {
        opcode = 0x100;
    }
    else if (!strcmp(opname, "COMF"))
    {
        opcode = 0x900;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "DECF"))
    {
        opcode = 0x300;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "DECFSZ"))
    {
        opcode = 0xB00;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "INCF"))
    {
        opcode = 0xA00;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "INCFSZ"))
    {
        opcode = 0xF00;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "IORWF"))
    {
        opcode = 0x400;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "MOVF"))
    {
        opcode = 0x800;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "MOVWF"))
    {
        opcode = 0x080;
        opcode |= (operand1 & 0x7F);
    }
    else if (!strcmp(opname, "NOP"))
    {
        opcode = 0;
    }
    else if (!strcmp(opname, "RLF"))
    {
        opcode = 0xD00;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "RRF"))
    {
        opcode = 0xC00;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "SUBWF"))
    {
        opcode = 0x200;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "SWAPF"))
    {
        opcode = 0xE00;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "XORWF"))
    {
        opcode = 0x900;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x80;
    }
    else if (!strcmp(opname, "BCF"))
    {
        opcode = 0x1000;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x380;
    }
    else if (!strcmp(opname, "BSF"))
    {
        opcode = 0x1400;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x380;
    }
    else if (!strcmp(opname, "BTFSC"))
    {
        opcode = 0x1800;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x380;
    }
    else if (!strcmp(opname, "BTFSS"))
    {
        opcode = 0x1C00;
        opcode |= (operand1 & 0x7F);
        opcode |= (operand2 << 7) & 0x380;
    }
    else if (!strcmp(opname, "ADDLW"))
    {
        opcode = 0x3E00;
        opcode |= (operand1 & 0xFF);
    }
    else if (!strcmp(opname, "ANDLW"))
    {
        opcode = 0x3900;
        opcode |= (operand1 & 0xFF);
    }
    else if (!strcmp(opname, "CALL"))
    {
        opcode = 0x2000;
        opcode |= (operand1 & 0x7FF);
    }
    else if (!strcmp(opname, "CLRWDT"))
    {
        opcode = 0x64;
    }
    else if (!strcmp(opname, "GOTO"))
    {
        opcode = 0x2800;
        opcode |= (operand1 & 0x7FF);
    }
    else if (!strcmp(opname, "IORLW"))
    {
        opcode = 0x3800;
        opcode |= (operand1 & 0xFF);
    }
    else if (!strcmp(opname, "MOVLW"))
    {
        opcode = 0x3000;
        opcode |= (operand1 & 0xFF);
    }
    else if (!strcmp(opname, "RETFIE"))
    {
        opcode = 0x09;
    }
    else if (!strcmp(opname, "RETLW"))
    {
        opcode = 0x3400;
        opcode |= (operand1 & 0xFF);
    }
    else if (!strcmp(opname, "RETURN"))
    {
        opcode = 0x08;
    }
    else if (!strcmp(opname, "SLEEP"))
    {
        opcode = 0x63;
    }
    else if (!strcmp(opname, "SUBLW"))
    {
        opcode = 0x3C00;
        opcode |= (operand1 & 0xFF);
    }
    else if (!strcmp(opname, "XORLW"))
    {
        opcode = 0x3A00;
        opcode |= (operand1 & 0xFF);
    }
    return opcode;
}

variable_types:
opname
char *

variable_types:
opcode
unsigned short

return_type: unsigned short