4: $a instructions, pt. 2

(0 comments)

Today's aim is to RE the remaining $a-related opcodes. That is, boring but required stuff before we can get to looking at the microcode.

First, let's look at the pXX.2 code again:

mwk@nightmare ~/microcode/vp1/p1 $ envydis -m vp1 -w part-00.2
00000000: 6b0fc0af     mov $a1 $x63
00000000: 7e087f80     shr $a1 $c0 $a1 -0x10
00000000: 7e084080     shr $a1 $c0 $a1 0x10
00000000: 4fffffff     nop4
00000001: bf000007     nopb
00000001: efffffff     unkend
00000001: 65100000     mov $a2 0
00000001: 75100000     sethi $a2 0
00000002: 4df845c3     ??? [unknown: 4df845c3]
00000002: 4fffffff     nop4
00000002: e200043f     bra2 0x4 [unknown: 0000003f]
00000002: 4fffffff     nop4
00000003: 4fffffff     nop4
00000003: eaf80040     abra 0x40
00000003: 4fffffff     nop4
00000003: 4fffffff     nop4
00000004: bf000007   B nopb
00000004: efffffff   B unkend
00000004: efffffff   B unkend
00000004: efffffff   B unkend
00000005: efffffff     unkend
00000005: efffffff     unkend
00000005: efffffff     unkend
00000005: efffffff     unkend
00000006: efffffff     unkend
00000006: fff8dead     exit 0xdead
00000006: efffffff     unkend
00000006: efffffff     unkend
00000007: efffffff     unkend
00000007: efffffff     unkend
00000007: efffffff     unkend
00000007: efffffff     unkend
00000008: efffffff     unkend
00000008: efffffff     unkend
00000008: efffffff     unkend
00000008: efffffff     unkend
00000009: efffffff     unkend
00000009: efffffff     unkend

That looks much better than it was on on the first try, but we still have unknown opcodes. I'm going to guess unkend is really just another form of nop and can be safely ignored. The 0x4d opcode is clearly a $a compare, while 0xe2 is a branch if not equal.

So the next opcode class we should look at is 0x[45]*. Let's look at the stats for them:

0x41   1439    1091
0x42   4233    3156
0x45      3       3
0x48    147     123
0x4c   4999    3653
0x4d   1878    1217
0x4f  10747    4331     nop?
0x5e     50       8

0x4c it is. 0x4cdeadbe gives bd5b7c30. With $a26 set to 0, it gives deadbe16. With $a22 set to 0, it gives deadbe1a. Yay, finally the "proper" add opcode. A similar test for opcode 0x4d immediately reveals it as the sub opcode, which is just right for a compare.

That covers opcode bits 9-31 and 0-2. However, in the above sample, we can see that bits 3-8 are also set to something interesting - 111000. Let's see the add/sub opcodes in other microcode samples.

00000000: 4c0005c7     add $a0 $a0 $a2 [unknown: 000001c0]
00000000: 4c0031c7     add $a0 $a0 $a24 [unknown: 000001c0]
00000000: 4c003dc7     add $a0 $a0 $a30 [unknown: 000001c0]
00000000: 4c02a1c7     add $a0 $a10 $a16 [unknown: 000001c0]
[...]
0000000b: 4c273fc7     add $a4 $a28 0 [unknown: 000001c0]
0000000b: 4c294007     add $a5 $a5 $a0
0000000b: 4c29400f     add $a5 $a5 $a0 [unknown: 00000008]
0000000b: 4c294027     add $a5 $a5 $a0 [unknown: 00000020]
0000000c: 4c2943c7     add $a5 $a5 $a1 [unknown: 000001c0]
[...]
00000014: 4c3f3fc7     add $a7 $a28 0 [unknown: 000001c0]
00000014: 4c3fe02f     add $a7 0 $a16 [unknown: 00000028]
00000014: 4c3fe42f     add $a7 0 $a18 [unknown: 00000028]
00000014: 4c3fe82f     add $a7 0 $a20 [unknown: 00000028]
00000015: 4c3fec2f     add $a7 0 $a22 [unknown: 00000028]
00000015: 4c3ff02f     add $a7 0 $a24 [unknown: 00000028]
00000015: 4c3fffc7     add $a7 0 0 [unknown: 000001c0]
[...]
00000054: 4c9cf5c7     add $a19 $a19 $a26 [unknown: 000001c0]
00000054: 4c9cf947     add $a19 $a19 $a28 [unknown: 00000140]
00000054: 4c9cf9c7     add $a19 $a19 $a28 [unknown: 000001c0]
[...]
000000b6: 4d2be7c7     sub $a5 $a15 $a19 [unknown: 000001c0]
000000b6: 4d310dc7     sub $a6 $a4 $a6 [unknown: 000001c0]
000000b6: 4d318027     sub $a6 $a6 $a0 [unknown: 00000020]
000000b6: 4d318fc7     sub $a6 $a6 $a7 [unknown: 000001c0]
000000b7: 4d3195c7     sub $a6 $a6 $a10 [unknown: 000001c0]
[...]
000000b6: 4d2be7c7     sub $a5 $a15 $a19 [unknown: 000001c0]
000000b6: 4d310dc7     sub $a6 $a4 $a6 [unknown: 000001c0]
000000b6: 4d318027     sub $a6 $a6 $a0 [unknown: 00000020]
000000b6: 4d318fc7     sub $a6 $a6 $a7 [unknown: 000001c0]
000000b7: 4d3195c7     sub $a6 $a6 $a10 [unknown: 000001c0]
000000b7: 4d31c027     sub $a6 $a7 $a0 [unknown: 00000020]
000000b7: 4d31c02f     sub $a6 $a7 $a0 [unknown: 00000028]

And so on. The overwhelming majority of opcodes have these bits set to 111000, which is probably a "standard" add/sub. A handful has them set to 000000, 000001, 000101, 000100, or 101000. None of the instructions with non-111000 values have $c output in use, so these bits must somehow affect the main result. Could be carry input, though it seems there are too many bits for only that. Let's do a quick test...

00000000+00000000 bits 00: 00000000 flags 00008002
00000000+00000000 bits 01: 00000000 flags 00008002
00000000+00000000 bits 02: 00000000 flags 00008002
00000000+00000000 bits 03: 00000000 flags 00008002
00000000+00000000 bits 04: deadbe03 flags 000080e5
00000000+00000000 bits 05: 00000000 flags 00008002
00000000+00000000 bits 06: 00000000 flags 00008002
00000000+00000000 bits 07: 00000000 flags 00008002
00000000+00000000 bits 08: 00000000 flags 00008002
00000000+00000000 bits 09: 00000000 flags 00008002
00000000+00000000 bits 0a: 00000000 flags 00008002
00000000+00000000 bits 0b: 00000000 flags 00008002
00000000+00000000 bits 0c: 00000000 flags 00008002
00000000+00000000 bits 0d: 00000000 flags 00008002
00000000+00000000 bits 0e: 00000000 flags 00008002
00000000+00000000 bits 0f: 00000000 flags 00008002
00000000+00000000 bits 10: 00000000 flags 00008002
00000000+00000000 bits 11: 00000000 flags 00008002
00000000+00000000 bits 12: 00000000 flags 00008002
00000000+00000000 bits 13: 00000000 flags 00008002
00000000+00000000 bits 14: 00000000 flags 00008002
00000000+00000000 bits 15: 00000000 flags 00008002
00000000+00000000 bits 16: 00000000 flags 00008002
00000000+00000000 bits 17: 00000000 flags 00008002
00000000+00000000 bits 18: 00000000 flags 00008002
00000000+00000000 bits 19: 00000000 flags 00008002
00000000+00000000 bits 1a: 00000000 flags 00008002
00000000+00000000 bits 1b: 00000000 flags 00008002
00000000+00000000 bits 1c: 00000000 flags 00008002
00000000+00000000 bits 1d: 00000000 flags 00008002
00000000+00000000 bits 1e: 00000000 flags 00008002
00000000+00000000 bits 1f: 00000000 flags 00008002
00000000+00000000 bits 20: 00000000 flags 00008002
00000000+00000000 bits 21: 00000000 flags 00008002
00000000+00000000 bits 22: 00000000 flags 00008002
00000000+00000000 bits 23: 00000000 flags 00008002
00000000+00000000 bits 24: 00000000 flags 00008002
00000000+00000000 bits 25: 00000000 flags 00008002
00000000+00000000 bits 26: 00000000 flags 00008002
00000000+00000000 bits 27: 00000000 flags 00008002
00000000+00000000 bits 28: 00000000 flags 00008002
00000000+00000000 bits 29: 00000000 flags 00008002
00000000+00000000 bits 2a: 00000000 flags 00008002
00000000+00000000 bits 2b: 00000000 flags 00008002
00000000+00000000 bits 2c: 00000000 flags 00008002
00000000+00000000 bits 2d: 00000000 flags 00008002
00000000+00000000 bits 2e: 00000000 flags 00008002
00000000+00000000 bits 2f: 00000000 flags 00008002
00000000+00000000 bits 30: 00000000 flags 00008002
00000000+00000000 bits 31: 00000000 flags 00008002
00000000+00000000 bits 32: 00000000 flags 00008002
00000000+00000000 bits 33: 00000000 flags 00008002
00000000+00000000 bits 34: 00000000 flags 00008002
00000000+00000000 bits 35: 00000000 flags 00008002
00000000+00000000 bits 36: 00000000 flags 00008002
00000000+00000000 bits 37: 00000000 flags 00008002
00000000+00000000 bits 38: 00000000 flags 00008002
00000000+00000000 bits 39: 00000000 flags 00008002
00000000+00000000 bits 3a: 00000000 flags 00008002
00000000+00000000 bits 3b: 00000000 flags 00008002
00000000+00000000 bits 3c: deadbe03 flags 000080e5
00000000+00000000 bits 3d: deadbe03 flags 000080e5
00000000+00000000 bits 3e: deadbe03 flags 000080e5
00000000+00000000 bits 3f: deadbe03 flags 000080e5

I... am not entirely sure if I want anything to do with this instruction anymore.

So it's using one of the other $a regs as a source, even though they're not explicitely specified in the usual opcode bitfields. Sigh. Let's try to see which ones - I'll put 1 << X in $rX, for X > 2.

00000000+00000000 bits 00: 00000000 flags 00008002
00000000+00000000 bits 01: 00000000 flags 00008002
00000000+00000000 bits 02: 00000000 flags 00008002
00000000+00000000 bits 03: 00000000 flags 00008002
00000000+00000000 bits 04: 00000008 flags 00008000
00000000+00000000 bits 05: 00000000 flags 00008002
[...]
00000000+00000000 bits 3a: 00000000 flags 00008002
00000000+00000000 bits 3b: 00000000 flags 00008002
00000000+00000000 bits 3c: 00000008 flags 00008000
00000000+00000000 bits 3d: 00000008 flags 00008000
00000000+00000000 bits 3e: 00000008 flags 00008000
00000000+00000000 bits 3f: 00000008 flags 00008000

$a3 is crossing over for no obvious reasons... what if I change the operands from $a0, $a1, $a2 to $a16, $a17, $a18?

00000000+00000000 bits 00: 00000000 flags 00008002
00000000+00000000 bits 01: 00000000 flags 00008002
00000000+00000000 bits 02: 00000000 flags 00008002
00000000+00000000 bits 03: 00000000 flags 00008002
00000000+00000000 bits 04: 00080000 flags 00008044
00000000+00000000 bits 05: 00000000 flags 00008002
00000000+00000000 bits 06: 00000000 flags 00008002
00000000+00000000 bits 07: 00000000 flags 00008002
[...]
00000000+00000000 bits 38: 00000000 flags 00008002
00000000+00000000 bits 39: 00000000 flags 00008002
00000000+00000000 bits 3a: 00000000 flags 00008002
00000000+00000000 bits 3b: 00000000 flags 00008002
00000000+00000000 bits 3c: 00080000 flags 00008044
00000000+00000000 bits 3d: 00080000 flags 00008044
00000000+00000000 bits 3e: 00080000 flags 00008044
00000000+00000000 bits 3f: 00080000 flags 00008044

$a16, $a17, $a2?

00000000+00000000 bits 00: 00000000 flags 00008002
00000000+00000000 bits 01: 00000000 flags 00008002
00000000+00000000 bits 02: 00000000 flags 00008002
00000000+00000000 bits 03: 00000000 flags 00008002
00000000+00000000 bits 04: 00000008 flags 00008000
00000000+00000000 bits 05: 00000000 flags 00008002
[...]
00000000+00000000 bits 3a: 00000000 flags 00008002
00000000+00000000 bits 3b: 00000000 flags 00008002
00000000+00000000 bits 3c: 00000008 flags 00008000
00000000+00000000 bits 3d: 00000008 flags 00008000
00000000+00000000 bits 3e: 00000008 flags 00008000
00000000+00000000 bits 3f: 00000008 flags 00008000

$a16, $a17, $a3?

00000000+00000000 bits 00: 00000000 flags 00008002
00000000+00000000 bits 01: 00000000 flags 00008002
00000000+00000000 bits 02: 00000000 flags 00008002
00000000+00000000 bits 03: 00000000 flags 00008002
00000000+00000000 bits 04: 00000004 flags 00008000
00000000+00000000 bits 05: 00000000 flags 00008002
[...]
00000000+00000000 bits 3a: 00000000 flags 00008002
00000000+00000000 bits 3b: 00000000 flags 00008002
00000000+00000000 bits 3c: 00000004 flags 00008000
00000000+00000000 bits 3d: 00000004 flags 00008000
00000000+00000000 bits 3e: 00000004 flags 00008000
00000000+00000000 bits 3f: 00000004 flags 00008000

$a16, $a17, $a1?

00000000+00000000 bits 00: 00000000 flags 00008002
00000000+00000000 bits 01: 00000000 flags 00008002
00000000+00000000 bits 02: 00000000 flags 00008002
00000000+00000000 bits 03: 00000000 flags 00008002
00000000+00000000 bits 04: 00000001 flags 00008000
00000000+00000000 bits 05: 00000000 flags 00008002
[...]
00000000+00000000 bits 3a: 00000000 flags 00008002
00000000+00000000 bits 3b: 00000000 flags 00008002
00000000+00000000 bits 3c: 00000001 flags 00008000
00000000+00000000 bits 3d: 00000001 flags 00008000
00000000+00000000 bits 3e: 00000001 flags 00008000
00000000+00000000 bits 3f: 00000001 flags 00008000

So that'd be $a register #(opcode bits 9-13 XOR 1). Sigh. How about other values?

00000000+00000001 bits 00: 00000001 flags 00008000
00000000+00000001 bits 01: 00000001 flags 00008000
00000000+00000001 bits 02: 00000001 flags 00008000
00000000+00000001 bits 03: 00000001 flags 00008000
00000000+00000001 bits 04: 00000001 flags 00008000
00000000+00000001 bits 05: 00000001 flags 00008000
00000000+00000001 bits 06: 00000001 flags 00008000
00000000+00000001 bits 07: 00000001 flags 00008000
00000000+00000001 bits 08: 00000001 flags 00008000
00000000+00000001 bits 09: 00000001 flags 00008000
[...]
00000000+00000001 bits 38: 00000001 flags 00008000
00000000+00000001 bits 39: 00000001 flags 00008000
00000000+00000001 bits 3a: 00000001 flags 00008000
00000000+00000001 bits 3b: 00000001 flags 00008000
00000000+00000001 bits 3c: 00000008 flags 00008000
00000000+00000001 bits 3d: 00000008 flags 00008000
00000000+00000001 bits 3e: 00000008 flags 00008000
00000000+00000001 bits 3f: 00000008 flags 00008000

Different flag-based behavior, but it's fairly clear that the extra register replaces second operand in some circumstances...

00000000+ffffffff bits 01: ffffffff flags 000080fd
00000000+ffffffff bits 02: ffffffff flags 000080fd
00000000+ffffffff bits 03: ffffffff flags 000080fd
00000000+ffffffff bits 04: ffffffff flags 000080fd
00000000+ffffffff bits 05: ffffffff flags 000080fd
00000000+ffffffff bits 06: ffffffff flags 000080fd
00000000+ffffffff bits 07: ffffffff flags 000080fd
00000000+ffffffff bits 08: 00000008 flags 00008000
00000000+ffffffff bits 09: ffffffff flags 000080fd
00000000+ffffffff bits 0a: ffffffff flags 000080fd
00000000+ffffffff bits 0b: ffffffff flags 000080fd
00000000+ffffffff bits 0c: 00000008 flags 00008000
00000000+ffffffff bits 0d: ffffffff flags 000080fd
00000000+ffffffff bits 0e: ffffffff flags 000080fd
00000000+ffffffff bits 0f: ffffffff flags 000080fd
00000000+ffffffff bits 10: 00000000 flags 00008002
00000000+ffffffff bits 11: ffffffff flags 000080fd
00000000+ffffffff bits 12: ffffffff flags 000080fd
00000000+ffffffff bits 13: ffffffff flags 000080fd
00000000+ffffffff bits 14: 00000008 flags 00008000
00000000+ffffffff bits 15: ffffffff flags 000080fd
00000000+ffffffff bits 16: ffffffff flags 000080fd
00000000+ffffffff bits 17: ffffffff flags 000080fd
00000000+ffffffff bits 18: 00000008 flags 00008000
00000000+ffffffff bits 19: ffffffff flags 000080fd
00000000+ffffffff bits 1a: ffffffff flags 000080fd
00000000+ffffffff bits 1b: ffffffff flags 000080fd
00000000+ffffffff bits 1c: 00000008 flags 00008000
00000000+ffffffff bits 1d: ffffffff flags 000080fd
00000000+ffffffff bits 1e: ffffffff flags 000080fd
00000000+ffffffff bits 1f: ffffffff flags 000080fd
00000000+ffffffff bits 20: ffffffff flags 000080fd
00000000+ffffffff bits 21: ffffffff flags 000080fd
00000000+ffffffff bits 22: ffffffff flags 000080fd
00000000+ffffffff bits 23: ffffffff flags 000080fd
00000000+ffffffff bits 24: ffffffff flags 000080fd
00000000+ffffffff bits 25: ffffffff flags 000080fd
00000000+ffffffff bits 26: ffffffff flags 000080fd
00000000+ffffffff bits 27: ffffffff flags 000080fd
00000000+ffffffff bits 28: ffffffff flags 000080fd
00000000+ffffffff bits 29: ffffffff flags 000080fd
00000000+ffffffff bits 2a: ffffffff flags 000080fd
00000000+ffffffff bits 2b: ffffffff flags 000080fd
00000000+ffffffff bits 2c: ffffffff flags 000080fd
00000000+ffffffff bits 2d: ffffffff flags 000080fd
00000000+ffffffff bits 2e: ffffffff flags 000080fd
00000000+ffffffff bits 2f: ffffffff flags 000080fd
00000000+ffffffff bits 30: ffffffff flags 000080fd
00000000+ffffffff bits 31: ffffffff flags 000080fd
00000000+ffffffff bits 32: ffffffff flags 000080fd
00000000+ffffffff bits 33: ffffffff flags 000080fd
00000000+ffffffff bits 34: ffffffff flags 000080fd
00000000+ffffffff bits 35: ffffffff flags 000080fd
00000000+ffffffff bits 36: ffffffff flags 000080fd
00000000+ffffffff bits 37: ffffffff flags 000080fd
00000000+ffffffff bits 38: ffffffff flags 000080fd
00000000+ffffffff bits 39: ffffffff flags 000080fd
00000000+ffffffff bits 3a: ffffffff flags 000080fd
00000000+ffffffff bits 3b: ffffffff flags 000080fd
00000000+ffffffff bits 3c: 00000008 flags 00008000
00000000+ffffffff bits 3d: 00000008 flags 00008000
00000000+ffffffff bits 3e: 00000008 flags 00008000
00000000+ffffffff bits 3f: 00000008 flags 00008000

... this is getting out of hand ...

ffffffff+00000000 bits 00: 00000007 flags 00008008
ffffffff+00000000 bits 01: ffffffff flags 000080f5
ffffffff+00000000 bits 02: ffffffff flags 000080f5
ffffffff+00000000 bits 03: ffffffff flags 000080f5
ffffffff+00000000 bits 04: ffffffff flags 000080f5
ffffffff+00000000 bits 05: ffffffff flags 000080f5
ffffffff+00000000 bits 06: ffffffff flags 000080f5
ffffffff+00000000 bits 07: ffffffff flags 000080f5
ffffffff+00000000 bits 08: 00000007 flags 00008008
ffffffff+00000000 bits 09: ffffffff flags 000080f5
ffffffff+00000000 bits 0a: ffffffff flags 000080f5
ffffffff+00000000 bits 0b: ffffffff flags 000080f5
ffffffff+00000000 bits 0c: ffffffff flags 000080f5
ffffffff+00000000 bits 0d: ffffffff flags 000080f5
ffffffff+00000000 bits 0e: ffffffff flags 000080f5
ffffffff+00000000 bits 0f: ffffffff flags 000080f5
ffffffff+00000000 bits 10: fffffffe flags 000080f5
ffffffff+00000000 bits 11: ffffffff flags 000080f5
ffffffff+00000000 bits 12: ffffffff flags 000080f5
ffffffff+00000000 bits 13: ffffffff flags 000080f5
ffffffff+00000000 bits 14: 00000007 flags 00008008
ffffffff+00000000 bits 15: ffffffff flags 000080f5
ffffffff+00000000 bits 16: ffffffff flags 000080f5
ffffffff+00000000 bits 17: ffffffff flags 000080f5
ffffffff+00000000 bits 18: 00000007 flags 00008008
ffffffff+00000000 bits 19: ffffffff flags 000080f5
ffffffff+00000000 bits 1a: ffffffff flags 000080f5
ffffffff+00000000 bits 1b: ffffffff flags 000080f5
ffffffff+00000000 bits 1c: 00000007 flags 00008008
ffffffff+00000000 bits 1d: ffffffff flags 000080f5
ffffffff+00000000 bits 1e: ffffffff flags 000080f5
ffffffff+00000000 bits 1f: ffffffff flags 000080f5
ffffffff+00000000 bits 20: ffffffff flags 000080f5
ffffffff+00000000 bits 21: ffffffff flags 000080f5
ffffffff+00000000 bits 22: ffffffff flags 000080f5
ffffffff+00000000 bits 23: ffffffff flags 000080f5
ffffffff+00000000 bits 24: ffffffff flags 000080f5
ffffffff+00000000 bits 25: ffffffff flags 000080f5
ffffffff+00000000 bits 26: ffffffff flags 000080f5
ffffffff+00000000 bits 27: ffffffff flags 000080f5
ffffffff+00000000 bits 28: ffffffff flags 000080f5
ffffffff+00000000 bits 29: ffffffff flags 000080f5
ffffffff+00000000 bits 2a: ffffffff flags 000080f5
ffffffff+00000000 bits 2b: ffffffff flags 000080f5
ffffffff+00000000 bits 2c: ffffffff flags 000080f5
ffffffff+00000000 bits 2d: ffffffff flags 000080f5
ffffffff+00000000 bits 2e: ffffffff flags 000080f5
ffffffff+00000000 bits 2f: ffffffff flags 000080f5
ffffffff+00000000 bits 30: ffffffff flags 000080f5
ffffffff+00000000 bits 31: ffffffff flags 000080f5
ffffffff+00000000 bits 32: ffffffff flags 000080f5
ffffffff+00000000 bits 33: ffffffff flags 000080f5
ffffffff+00000000 bits 34: ffffffff flags 000080f5
ffffffff+00000000 bits 35: ffffffff flags 000080f5
ffffffff+00000000 bits 36: ffffffff flags 000080f5
ffffffff+00000000 bits 37: ffffffff flags 000080f5
ffffffff+00000000 bits 38: ffffffff flags 000080f5
ffffffff+00000000 bits 39: ffffffff flags 000080f5
ffffffff+00000000 bits 3a: ffffffff flags 000080f5
ffffffff+00000000 bits 3b: ffffffff flags 000080f5
ffffffff+00000000 bits 3c: 00000007 flags 00008008
ffffffff+00000000 bits 3d: 00000007 flags 00008008
ffffffff+00000000 bits 3e: 00000007 flags 00008008
ffffffff+00000000 bits 3f: 00000007 flags 00008008

Now fffffffe appears out of blue! Ok, this is just too fucked up to continue right now. All we really need to know at this point is that bits 111000 result in a normal sane add/sub. We'll figure out these crazy bits later. Ah well, just when I started thinking it's going too easy...

But, since these are the *sane* add/sub opcodes, and the sub is used as a compare instruction, they'll hopefully have some sane $c behavior. Let's try it for add.

fffffffe+fffffffe bits 38: fffffffc flags 000080f5
fffffffe+ffffffff bits 38: fffffffd flags 000080f5
fffffffe+00000000 bits 38: fffffffe flags 000080f5
fffffffe+00000001 bits 38: ffffffff flags 000080f5
fffffffe+00000002 bits 38: 00000000 flags 0000800a
ffffffff+fffffffe bits 38: fffffffd flags 000080f5
ffffffff+ffffffff bits 38: fffffffe flags 000080f5
ffffffff+00000000 bits 38: ffffffff flags 000080f5
ffffffff+00000001 bits 38: 00000000 flags 0000800a
ffffffff+00000002 bits 38: 00000001 flags 00008008
00000000+fffffffe bits 38: fffffffe flags 000080fd
00000000+ffffffff bits 38: ffffffff flags 000080fd
00000000+00000000 bits 38: 00000000 flags 00008002
00000000+00000001 bits 38: 00000001 flags 00008000
00000000+00000002 bits 38: 00000002 flags 00008000
00000001+fffffffe bits 38: ffffffff flags 000080fd
00000001+ffffffff bits 38: 00000000 flags 00008002
00000001+00000000 bits 38: 00000001 flags 00008000
00000001+00000001 bits 38: 00000002 flags 00008000
00000001+00000002 bits 38: 00000003 flags 00008000
00000002+fffffffe bits 38: 00000000 flags 00008002
00000002+ffffffff bits 38: 00000001 flags 00008000
00000002+00000000 bits 38: 00000002 flags 00008000
00000002+00000001 bits 38: 00000003 flags 00008000
00000002+00000002 bits 38: 00000004 flags 00008000

Umm. that doesn't exactly match the usual carry/overflow flags... Zero and sign flags look relatively sane though.

7ffffffe+fffffffe bits 38: 7ffffffc flags 000080f4
7ffffffe+ffffffff bits 38: 7ffffffd flags 000080f4
7ffffffe+00000000 bits 38: 7ffffffe flags 000080f4
7ffffffe+00000001 bits 38: 7fffffff flags 000080f4
7ffffffe+00000002 bits 38: 80000000 flags 00008009
7fffffff+fffffffe bits 38: 7ffffffd flags 000080f4
7fffffff+ffffffff bits 38: 7ffffffe flags 000080f4
7fffffff+00000000 bits 38: 7fffffff flags 000080f4
7fffffff+00000001 bits 38: 80000000 flags 00008009
7fffffff+00000002 bits 38: 80000001 flags 00008009
80000000+fffffffe bits 38: 7ffffffe flags 000080fc
80000000+ffffffff bits 38: 7fffffff flags 000080fc
80000000+00000000 bits 38: 80000000 flags 00008001
80000000+00000001 bits 38: 80000001 flags 00008001
80000000+00000002 bits 38: 80000002 flags 00008001
80000001+fffffffe bits 38: 7fffffff flags 000080fc
80000001+ffffffff bits 38: 80000000 flags 00008001
80000001+00000000 bits 38: 80000001 flags 00008001
80000001+00000001 bits 38: 80000002 flags 00008001
80000001+00000002 bits 38: 80000003 flags 00008001
80000002+fffffffe bits 38: 80000000 flags 00008001
80000002+ffffffff bits 38: 80000001 flags 00008001
80000002+00000000 bits 38: 80000002 flags 00008001
80000002+00000001 bits 38: 80000003 flags 00008001
80000002+00000002 bits 38: 80000004 flags 00008001
fffffffe+7ffffffe bits 38: 7ffffffc flags 000080f4
fffffffe+7fffffff bits 38: 7ffffffd flags 000080f4
fffffffe+80000000 bits 38: 7ffffffe flags 000080f4
fffffffe+80000001 bits 38: 7fffffff flags 000080f4
fffffffe+80000002 bits 38: 80000000 flags 00008009
ffffffff+7ffffffe bits 38: 7ffffffd flags 000080f4
ffffffff+7fffffff bits 38: 7ffffffe flags 000080f4
ffffffff+80000000 bits 38: 7fffffff flags 000080f4
ffffffff+80000001 bits 38: 80000000 flags 00008009
ffffffff+80000002 bits 38: 80000001 flags 00008009
00000000+7ffffffe bits 38: 7ffffffe flags 000080fc
00000000+7fffffff bits 38: 7fffffff flags 000080fc
00000000+80000000 bits 38: 80000000 flags 00008001
00000000+80000001 bits 38: 80000001 flags 00008001
00000000+80000002 bits 38: 80000002 flags 00008001
00000001+7ffffffe bits 38: 7fffffff flags 000080fc
00000001+7fffffff bits 38: 80000000 flags 00008001
00000001+80000000 bits 38: 80000001 flags 00008001
00000001+80000001 bits 38: 80000002 flags 00008001
00000001+80000002 bits 38: 80000003 flags 00008001
00000002+7ffffffe bits 38: 80000000 flags 00008001
00000002+7fffffff bits 38: 80000001 flags 00008001
00000002+80000000 bits 38: 80000002 flags 00008001
00000002+80000001 bits 38: 80000003 flags 00008001
00000002+80000002 bits 38: 80000004 flags 00008001

Bit 3 is not commutative. I hate it already.

7ffffffe+7ffffffe bits 38: fffffffc flags 000080f5
7ffffffe+7fffffff bits 38: fffffffd flags 000080f5
7ffffffe+80000000 bits 38: fffffffe flags 000080f5
7ffffffe+80000001 bits 38: ffffffff flags 000080f5
7ffffffe+80000002 bits 38: 00000000 flags 0000800a
7fffffff+7ffffffe bits 38: fffffffd flags 000080f5
7fffffff+7fffffff bits 38: fffffffe flags 000080f5
7fffffff+80000000 bits 38: ffffffff flags 000080f5
7fffffff+80000001 bits 38: 00000000 flags 0000800a
7fffffff+80000002 bits 38: 00000001 flags 00008008
80000000+7ffffffe bits 38: fffffffe flags 000080fd
80000000+7fffffff bits 38: ffffffff flags 000080fd
80000000+80000000 bits 38: 00000000 flags 00008002
80000000+80000001 bits 38: 00000001 flags 00008000
80000000+80000002 bits 38: 00000002 flags 00008000
80000001+7ffffffe bits 38: ffffffff flags 000080fd
80000001+7fffffff bits 38: 00000000 flags 00008002
80000001+80000000 bits 38: 00000001 flags 00008000
80000001+80000001 bits 38: 00000002 flags 00008000
80000001+80000002 bits 38: 00000003 flags 00008000
80000002+7ffffffe bits 38: 00000000 flags 00008002
80000002+7fffffff bits 38: 00000001 flags 00008000
80000002+80000000 bits 38: 00000002 flags 00008000
80000002+80000001 bits 38: 00000003 flags 00008000
80000002+80000002 bits 38: 00000004 flags 00008000

Back when we REd the shift instruction, we noticed that some flags are tied to bits around bit 20 or so. Maybe it's a good idea to look at them?

80020000+80000000 bits 38: 00020000 flags 00008000
80040000+80000000 bits 38: 00040000 flags 00008080
80080000+80000000 bits 38: 00080000 flags 00008044
80100000+80000000 bits 38: 00100000 flags 00008010
80200000+80000000 bits 38: 00200000 flags 00008020
80400000+80000000 bits 38: 00400000 flags 00008000

Now ain't that oddly familiar...

80000000+80040000 bits 38: 00040000 flags 00008080
80000000+80080000 bits 38: 00080000 flags 00008044
80000000+80100000 bits 38: 00100000 flags 00008018
80000000+80200000 bits 38: 00200000 flags 00008020

Here comes some assymetry.

80020000+80020000 bits 38: 00040000 flags 00008080
80040000+80040000 bits 38: 00080000 flags 00008044
80080000+80080000 bits 38: 00100000 flags 00008018
80100000+80100000 bits 38: 00200000 flags 00008028
80200000+80200000 bits 38: 00400000 flags 00008000

Ah, I get it now.

  • bit 0: sign flag, bit 31 of result (for some reason doesn't work for bitwise ops)
  • bit 1: zero flag, 1 if result == 0
  • bit 2: bit 19 of the result
  • bit 3: bit 20 different between destination and source 1
  • bit 4: bit 20 of the result
  • bit 5: bit 21 of the result
  • bit 6: bit 19 of the result
  • bit 7: bit 18 of the result

Yeah, seems to match with all data gathered in this and previous episodes. Still no idea why they did something so fucked up.

Ok, let's go back to the unknown bits. One obvious hypothesis is that they read something from $c. So let's try 0+0 with various unknown bits with $c* set to 0x8000:

00000000+00000000 bits 00: 00000000 flags 00008002
00000000+00000000 bits 01: 00000000 flags 00008002
[...]
00000000+00000000 bits 38: 00000000 flags 00008002
00000000+00000000 bits 39: 00000000 flags 00008002
00000000+00000000 bits 3a: 00000000 flags 00008002
00000000+00000000 bits 3b: 00000000 flags 00008002
00000000+00000000 bits 3c: 00000008 flags 00008000
00000000+00000000 bits 3d: 00000008 flags 00008000
00000000+00000000 bits 3e: 00000008 flags 00008000
00000000+00000000 bits 3f: 00000008 flags 00008000

With $c0 set to 0x8002, $c1-$c3 set to 0x8000:

00000000+00000000 bits 00: 00000000 flags 00008002
00000000+00000000 bits 01: 00000000 flags 00008002
00000000+00000000 bits 02: 00000000 flags 00008002
00000000+00000000 bits 03: 00000000 flags 00008002
00000000+00000000 bits 04: 00000008 flags 00008000
00000000+00000000 bits 05: 00000000 flags 00008002
00000000+00000000 bits 06: 00000000 flags 00008002
[...]
00000000+00000000 bits 3b: 00000000 flags 00008002
00000000+00000000 bits 3c: 00000008 flags 00008000
00000000+00000000 bits 3d: 00000008 flags 00008000
00000000+00000000 bits 3e: 00000008 flags 00008000
00000000+00000000 bits 3f: 00000008 flags 00008000

With $c3 set to 0x8002, $c0-$c2 set to 0x8000:

00000000+00000000 bits 00: 00000000 flags 00008002
00000000+00000000 bits 01: 00000000 flags 00008002
00000000+00000000 bits 02: 00000000 flags 00008002
00000000+00000000 bits 03: 00000000 flags 00008002
00000000+00000000 bits 04: 00000000 flags 00008002
00000000+00000000 bits 05: 00000000 flags 00008002
00000000+00000000 bits 06: 00000000 flags 00008002
00000000+00000000 bits 07: 00000008 flags 00008000
00000000+00000000 bits 08: 00000000 flags 00008002
00000000+00000000 bits 09: 00000000 flags 00008002
[...]
00000000+00000000 bits 3a: 00000000 flags 00008002
00000000+00000000 bits 3b: 00000000 flags 00008002
00000000+00000000 bits 3c: 00000008 flags 00008000
00000000+00000000 bits 3d: 00000008 flags 00008000
00000000+00000000 bits 3e: 00000008 flags 00008000
00000000+00000000 bits 3f: 00000008 flags 00008000

Bits 3-4 must select the $c register. Looks like 0x4c is $a[DST] = $a[SRC1] + (pred ? $a[SRC2 ^ 1] : $a[SRC2]), with pred being a bit of index (opcode bits 5-8) of $c[opcode bits 3-4]. We can further conclude from the usual add opcode that $c bit 14 is always 0. It is also likely that bit 15 is always 1. Let's just verify that select works as expected, by setting $c2 to 0x80fd:

00000000+00000000 bits 00: 00000000 flags 00008002
00000000+00000000 bits 01: 00000000 flags 00008002
00000000+00000000 bits 02: 00000008 flags 00008000
00000000+00000000 bits 03: 00000000 flags 00008002
00000000+00000000 bits 04: 00000000 flags 00008002
00000000+00000000 bits 05: 00000000 flags 00008002
00000000+00000000 bits 06: 00000000 flags 00008002
00000000+00000000 bits 07: 00000000 flags 00008002
00000000+00000000 bits 08: 00000000 flags 00008002
00000000+00000000 bits 09: 00000000 flags 00008002
00000000+00000000 bits 0a: 00000008 flags 00008000
00000000+00000000 bits 0b: 00000000 flags 00008002
00000000+00000000 bits 0c: 00000000 flags 00008002
00000000+00000000 bits 0d: 00000000 flags 00008002
00000000+00000000 bits 0e: 00000008 flags 00008000
00000000+00000000 bits 0f: 00000000 flags 00008002
00000000+00000000 bits 10: 00000000 flags 00008002
00000000+00000000 bits 11: 00000000 flags 00008002
00000000+00000000 bits 12: 00000000 flags 00008002
00000000+00000000 bits 13: 00000000 flags 00008002
00000000+00000000 bits 14: 00000000 flags 00008002
00000000+00000000 bits 15: 00000000 flags 00008002
00000000+00000000 bits 16: 00000008 flags 00008000
00000000+00000000 bits 17: 00000000 flags 00008002
00000000+00000000 bits 18: 00000000 flags 00008002
00000000+00000000 bits 19: 00000000 flags 00008002
00000000+00000000 bits 1a: 00000008 flags 00008000
00000000+00000000 bits 1b: 00000000 flags 00008002
00000000+00000000 bits 1c: 00000000 flags 00008002
00000000+00000000 bits 1d: 00000000 flags 00008002
00000000+00000000 bits 1e: 00000008 flags 00008000
00000000+00000000 bits 1f: 00000000 flags 00008002
00000000+00000000 bits 20: 00000000 flags 00008002
00000000+00000000 bits 21: 00000000 flags 00008002
00000000+00000000 bits 22: 00000000 flags 00008002
00000000+00000000 bits 23: 00000000 flags 00008002
00000000+00000000 bits 24: 00000000 flags 00008002
00000000+00000000 bits 25: 00000000 flags 00008002
00000000+00000000 bits 26: 00000000 flags 00008002
00000000+00000000 bits 27: 00000000 flags 00008002
00000000+00000000 bits 28: 00000000 flags 00008002
00000000+00000000 bits 29: 00000000 flags 00008002
00000000+00000000 bits 2a: 00000000 flags 00008002
00000000+00000000 bits 2b: 00000000 flags 00008002
00000000+00000000 bits 2c: 00000000 flags 00008002
00000000+00000000 bits 2d: 00000000 flags 00008002
00000000+00000000 bits 2e: 00000000 flags 00008002
00000000+00000000 bits 2f: 00000000 flags 00008002
00000000+00000000 bits 30: 00000000 flags 00008002
00000000+00000000 bits 31: 00000000 flags 00008002
00000000+00000000 bits 32: 00000000 flags 00008002
00000000+00000000 bits 33: 00000000 flags 00008002
00000000+00000000 bits 34: 00000000 flags 00008002
00000000+00000000 bits 35: 00000000 flags 00008002
00000000+00000000 bits 36: 00000000 flags 00008002
00000000+00000000 bits 37: 00000000 flags 00008002
00000000+00000000 bits 38: 00000000 flags 00008002
00000000+00000000 bits 39: 00000000 flags 00008002
00000000+00000000 bits 3a: 00000000 flags 00008002
00000000+00000000 bits 3b: 00000000 flags 00008002
00000000+00000000 bits 3c: 00000008 flags 00008000
00000000+00000000 bits 3d: 00000008 flags 00008000
00000000+00000000 bits 3e: 00000008 flags 00008000
00000000+00000000 bits 3f: 00000008 flags 00008000

Umm, unexpected difference on bits 0x12, which would correspond to bit 4.

00000123+00000456 bits 00: 00000579 flags 00008000
00000123+00000456 bits 01: 00000579 flags 00008000
00000123+00000456 bits 02: 0000012b flags 00008000
00000123+00000456 bits 03: 00000579 flags 00008000
00000123+00000456 bits 04: 00000579 flags 00008000
00000123+00000456 bits 05: 00000579 flags 00008000
00000123+00000456 bits 06: 00000579 flags 00008000
00000123+00000456 bits 07: 00000579 flags 00008000
00000123+00000456 bits 08: 00000579 flags 00008000
00000123+00000456 bits 09: 00000579 flags 00008000
00000123+00000456 bits 0a: 0000012b flags 00008000
00000123+00000456 bits 0b: 00000579 flags 00008000
00000123+00000456 bits 0c: 00000579 flags 00008000
00000123+00000456 bits 0d: 00000579 flags 00008000
00000123+00000456 bits 0e: 0000012b flags 00008000
00000123+00000456 bits 0f: 00000579 flags 00008000
00000123+00000456 bits 10: 00000579 flags 00008000
00000123+00000456 bits 11: 00000579 flags 00008000
00000123+00000456 bits 12: 00000246 flags 00008000
00000123+00000456 bits 13: 00000579 flags 00008000
00000123+00000456 bits 14: 00000579 flags 00008000
00000123+00000456 bits 15: 00000579 flags 00008000
00000123+00000456 bits 16: 0000012b flags 00008000
00000123+00000456 bits 17: 00000579 flags 00008000
00000123+00000456 bits 18: 00000579 flags 00008000
00000123+00000456 bits 19: 00000579 flags 00008000
00000123+00000456 bits 1a: 0000012b flags 00008000
00000123+00000456 bits 1b: 00000579 flags 00008000
00000123+00000456 bits 1c: 00000579 flags 00008000
00000123+00000456 bits 1d: 00000579 flags 00008000
00000123+00000456 bits 1e: 0000012b flags 00008000
00000123+00000456 bits 1f: 00000579 flags 00008000
00000123+00000456 bits 20: 00000579 flags 00008000
00000123+00000456 bits 21: 00000579 flags 00008000
00000123+00000456 bits 22: 00000579 flags 00008000
00000123+00000456 bits 23: 00000579 flags 00008000
00000123+00000456 bits 24: 00000579 flags 00008000
00000123+00000456 bits 25: 00000579 flags 00008000
00000123+00000456 bits 26: 00000579 flags 00008000
00000123+00000456 bits 27: 00000579 flags 00008000
00000123+00000456 bits 28: 00000579 flags 00008000
00000123+00000456 bits 29: 00000579 flags 00008000
00000123+00000456 bits 2a: 00000579 flags 00008000
00000123+00000456 bits 2b: 00000579 flags 00008000
00000123+00000456 bits 2c: 00000579 flags 00008000
00000123+00000456 bits 2d: 00000579 flags 00008000
00000123+00000456 bits 2e: 00000579 flags 00008000
00000123+00000456 bits 2f: 00000579 flags 00008000
00000123+00000456 bits 30: 00000579 flags 00008000
00000123+00000456 bits 31: 00000579 flags 00008000
00000123+00000456 bits 32: 00000579 flags 00008000
00000123+00000456 bits 33: 00000579 flags 00008000
00000123+00000456 bits 34: 00000579 flags 00008000
00000123+00000456 bits 35: 00000579 flags 00008000
00000123+00000456 bits 36: 00000579 flags 00008000
00000123+00000456 bits 37: 00000579 flags 00008000
00000123+00000456 bits 38: 00000579 flags 00008000
00000123+00000456 bits 39: 00000579 flags 00008000
00000123+00000456 bits 3a: 00000579 flags 00008000
00000123+00000456 bits 3b: 00000579 flags 00008000
00000123+00000456 bits 3c: 0000012b flags 00008000
00000123+00000456 bits 3d: 0000012b flags 00008000
00000123+00000456 bits 3e: 0000012b flags 00008000
00000123+00000456 bits 3f: 0000012b flags 00008000

Uh. So a flag value of 1 on bit 4 gives SRC1 + SRC1, while on other bits it gives SRC1 + (SRC2^1)?

I *really* hope it's going to make sense later. For now, let's just try the same with sub.

00000123-00000456 bits 00: fffffccd flags 000080fd
00000123-00000456 bits 01: fffffccd flags 000080fd
00000123-00000456 bits 02: 0000011b flags 00008000
00000123-00000456 bits 03: fffffccd flags 000080fd
00000123-00000456 bits 04: fffffccd flags 000080fd
00000123-00000456 bits 05: fffffccd flags 000080fd
00000123-00000456 bits 06: fffffccd flags 000080fd
00000123-00000456 bits 07: fffffccd flags 000080fd
00000123-00000456 bits 08: fffffccd flags 000080fd
00000123-00000456 bits 09: fffffccd flags 000080fd
00000123-00000456 bits 0a: 0000011b flags 00008000
00000123-00000456 bits 0b: fffffccd flags 000080fd
00000123-00000456 bits 0c: fffffccd flags 000080fd
00000123-00000456 bits 0d: fffffccd flags 000080fd
00000123-00000456 bits 0e: 0000011b flags 00008000
00000123-00000456 bits 0f: fffffccd flags 000080fd
00000123-00000456 bits 10: fffffccd flags 000080fd
00000123-00000456 bits 11: fffffccd flags 000080fd
00000123-00000456 bits 12: 00000000 flags 00008002
00000123-00000456 bits 13: fffffccd flags 000080fd
00000123-00000456 bits 14: fffffccd flags 000080fd
00000123-00000456 bits 15: fffffccd flags 000080fd
00000123-00000456 bits 16: 0000011b flags 00008000
00000123-00000456 bits 17: fffffccd flags 000080fd
00000123-00000456 bits 18: fffffccd flags 000080fd
00000123-00000456 bits 19: fffffccd flags 000080fd
00000123-00000456 bits 1a: 0000011b flags 00008000
00000123-00000456 bits 1b: fffffccd flags 000080fd
00000123-00000456 bits 1c: fffffccd flags 000080fd
00000123-00000456 bits 1d: fffffccd flags 000080fd
00000123-00000456 bits 1e: 0000011b flags 00008000
00000123-00000456 bits 1f: fffffccd flags 000080fd
00000123-00000456 bits 20: fffffccd flags 000080fd
00000123-00000456 bits 21: fffffccd flags 000080fd
00000123-00000456 bits 22: fffffccd flags 000080fd
00000123-00000456 bits 23: fffffccd flags 000080fd
00000123-00000456 bits 24: fffffccd flags 000080fd
00000123-00000456 bits 25: fffffccd flags 000080fd
00000123-00000456 bits 26: fffffccd flags 000080fd
00000123-00000456 bits 27: fffffccd flags 000080fd
00000123-00000456 bits 28: fffffccd flags 000080fd
00000123-00000456 bits 29: fffffccd flags 000080fd
00000123-00000456 bits 2a: fffffccd flags 000080fd
00000123-00000456 bits 2b: fffffccd flags 000080fd
00000123-00000456 bits 2c: fffffccd flags 000080fd
00000123-00000456 bits 2d: fffffccd flags 000080fd
00000123-00000456 bits 2e: fffffccd flags 000080fd
00000123-00000456 bits 2f: fffffccd flags 000080fd
00000123-00000456 bits 30: fffffccd flags 000080fd
00000123-00000456 bits 31: fffffccd flags 000080fd
00000123-00000456 bits 32: fffffccd flags 000080fd
00000123-00000456 bits 33: fffffccd flags 000080fd
00000123-00000456 bits 34: fffffccd flags 000080fd
00000123-00000456 bits 35: fffffccd flags 000080fd
00000123-00000456 bits 36: fffffccd flags 000080fd
00000123-00000456 bits 37: fffffccd flags 000080fd
00000123-00000456 bits 38: fffffccd flags 000080fd
00000123-00000456 bits 39: fffffccd flags 000080fd
00000123-00000456 bits 3a: fffffccd flags 000080fd
00000123-00000456 bits 3b: fffffccd flags 000080fd
00000123-00000456 bits 3c: 0000011b flags 00008000
00000123-00000456 bits 3d: 0000011b flags 00008000
00000123-00000456 bits 3e: 0000011b flags 00008000
00000123-00000456 bits 3f: 0000011b flags 00008000

Eh, good enough.

One thing we can notice now is that opcodes 0x4c (add two registers) and 0x6c (add register with immediate) differ only by 1 bit. This may be an indication of a nice pattern. Let's check if opcode 0x6d is an immediate sub.

Ok, a few tests verify that it is. So let's apply it the other way, how about 0x42 being and of two regs?

cccccccc op aaaaaaaa bits 00: 00000000 flags 00008002
cccccccc op aaaaaaaa bits 01: 11111111 flags 00008010
cccccccc op aaaaaaaa bits 02: 22222222 flags 00008020
cccccccc op aaaaaaaa bits 03: 33333333 flags 00008030
cccccccc op aaaaaaaa bits 04: 44444444 flags 00008080
cccccccc op aaaaaaaa bits 05: 55555555 flags 00008090
cccccccc op aaaaaaaa bits 06: 66666666 flags 000080a0
cccccccc op aaaaaaaa bits 07: 77777777 flags 000080b0
cccccccc op aaaaaaaa bits 08: 88888888 flags 00008044
cccccccc op aaaaaaaa bits 09: 99999999 flags 00008054
cccccccc op aaaaaaaa bits 0a: aaaaaaaa flags 00008064
cccccccc op aaaaaaaa bits 0b: bbbbbbbb flags 00008074
cccccccc op aaaaaaaa bits 0c: cccccccc flags 000080c4
cccccccc op aaaaaaaa bits 0d: dddddddd flags 000080d4
cccccccc op aaaaaaaa bits 0e: eeeeeeee flags 000080e4
cccccccc op aaaaaaaa bits 0f: ffffffff flags 000080f4
cccccccc op aaaaaaaa bits 10: 00000000 flags 00008002
cccccccc op aaaaaaaa bits 11: 11111111 flags 00008010
cccccccc op aaaaaaaa bits 12: 22222222 flags 00008020
cccccccc op aaaaaaaa bits 13: 33333333 flags 00008030
cccccccc op aaaaaaaa bits 14: 44444444 flags 00008080
cccccccc op aaaaaaaa bits 15: 55555555 flags 00008090
[... repeats ...]

Not exactly... looks like 0x42 is an arbitrary logic operation, with the operation determined by bits 3-6. The operation selection is pretty standard:

  • bit 3: result when bits in both operands are 0
  • bit 4: result when bit in first operand is 0, bit in second operand is 1
  • bit 5: result when bit in first operand is 1, bit in second operand is 0
  • bit 6: result when bits in both operands are 1

The next instruction on our list is 0x41. Let's see.

cccccccc op aaaaaaaa bits 00: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 01: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 02: fffe6660 flags 000080fd
cccccccc op aaaaaaaa bits 03: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 04: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 05: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 06: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 07: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 08: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 09: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 0a: fffe6660 flags 000080fd
cccccccc op aaaaaaaa bits 0b: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 0c: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 0d: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 0e: fffe6660 flags 000080fd
cccccccc op aaaaaaaa bits 0f: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 10: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 11: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 12: 0a3dc290 flags 000080fc
cccccccc op aaaaaaaa bits 13: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 14: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 15: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 16: fffe6660 flags 000080fd
cccccccc op aaaaaaaa bits 17: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 18: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 19: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 1a: fffe6660 flags 000080fd
cccccccc op aaaaaaaa bits 1b: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 1c: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 1d: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 1e: fffe6660 flags 000080fd
cccccccc op aaaaaaaa bits 1f: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 20: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 21: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 22: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 23: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 24: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 25: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 26: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 27: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 28: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 29: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 2a: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 2b: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 2c: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 2d: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 2e: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 2f: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 30: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 31: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 32: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 33: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 34: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 35: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 36: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 37: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 38: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 39: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 3a: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 3b: 11117778 flags 00008018
cccccccc op aaaaaaaa bits 3c: fffe6660 flags 000080fd
cccccccc op aaaaaaaa bits 3d: fffe6660 flags 000080fd
cccccccc op aaaaaaaa bits 3e: fffe6660 flags 000080fd
cccccccc op aaaaaaaa bits 3f: fffe6660 flags 000080fd

Ah, seems to have the same src2/src2^1 selection behavior as add/sub. So what is it?

Out of common operations, mul is a near match: 0xcccccccc * 0xaaaaaaaa == 0x8888888777777778. But, it's common to have reduced effective operand size for mul. Let's try 16-bit:

 0xcccc * 0xaaaa == 0x88877778

Not quite. How about sign-extension?

 0xffffcccc * 0xffffaaaa == 0xffff777611117778

Good. We further confirm this guess by noting that 0xffffcccc * 0xffffcccc is 0xffff99980a3dc290, and 0xffffcccc * 8 is 0x7fffe6660.

Maybe there's an unsigned mul too? 0x40 looks like a good candidate.

cccccccc op aaaaaaaa bits 00: 00010000 flags 00008000
cccccccc op aaaaaaaa bits 01: 00010000 flags 00008000
[...]
cccccccc op aaaaaaaa bits 3e: 00010000 flags 00008000
cccccccc op aaaaaaaa bits 3f: 00010000 flags 00008000

Ah well. Was worth a shot. And how about 0x61 being a mul with immediate?

cccccccc*0: 00000000 flags 00008002
cccccccc*1: ffffcccc flags 000080fd
cccccccc*2: ffff9998 flags 000080fd
cccccccc*3: ffff6664 flags 000080fd
cccccccc*4: ffff3330 flags 000080fd

Good. Time for 0x48. A good guess for it would be the min instruction.

fffffffe min fffffffe bits 38: fffffffe flags 000080f5
fffffffe min ffffffff bits 38: fffffffe flags 000080f5
fffffffe min 00000000 bits 38: fffffffe flags 000080f5
fffffffe min 00000001 bits 38: fffffffe flags 000080f5
fffffffe min 00000002 bits 38: fffffffe flags 000080f5
ffffffff min fffffffe bits 38: fffffffe flags 000080f5
ffffffff min ffffffff bits 38: ffffffff flags 000080f5
ffffffff min 00000000 bits 38: ffffffff flags 000080f5
ffffffff min 00000001 bits 38: ffffffff flags 000080f5
ffffffff min 00000002 bits 38: ffffffff flags 000080f5
00000000 min fffffffe bits 38: fffffffe flags 000080fd
00000000 min ffffffff bits 38: ffffffff flags 000080fd
00000000 min 00000000 bits 38: 00000000 flags 00008002
00000000 min 00000001 bits 38: 00000000 flags 00008002
00000000 min 00000002 bits 38: 00000000 flags 00008002
00000001 min fffffffe bits 38: fffffffe flags 000080fd
00000001 min ffffffff bits 38: ffffffff flags 000080fd
00000001 min 00000000 bits 38: 00000000 flags 00008002
00000001 min 00000001 bits 38: 00000001 flags 00008000
00000001 min 00000002 bits 38: 00000001 flags 00008000
00000002 min fffffffe bits 38: fffffffe flags 000080fd
00000002 min ffffffff bits 38: ffffffff flags 000080fd
00000002 min 00000000 bits 38: 00000000 flags 00008002
00000002 min 00000001 bits 38: 00000001 flags 00008000
00000002 min 00000002 bits 38: 00000002 flags 00008000

Yup. And with different bits:

cccccccc min aaaaaaaa bits 00: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 01: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 02: cccccccc flags 000080c5
cccccccc min aaaaaaaa bits 03: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 04: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 05: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 06: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 07: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 08: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 09: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 0a: cccccccc flags 000080c5
cccccccc min aaaaaaaa bits 0b: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 0c: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 0d: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 0e: cccccccc flags 000080c5
cccccccc min aaaaaaaa bits 0f: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 10: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 11: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 12: cccccccc flags 000080c5
cccccccc min aaaaaaaa bits 13: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 14: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 15: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 16: cccccccc flags 000080c5
cccccccc min aaaaaaaa bits 17: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 18: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 19: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 1a: cccccccc flags 000080c5
cccccccc min aaaaaaaa bits 1b: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 1c: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 1d: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 1e: cccccccc flags 000080c5
cccccccc min aaaaaaaa bits 1f: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 20: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 21: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 22: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 23: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 24: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 25: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 26: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 27: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 28: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 29: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 2a: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 2b: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 2c: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 2d: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 2e: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 2f: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 30: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 31: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 32: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 33: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 34: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 35: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 36: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 37: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 38: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 39: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 3a: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 3b: aaaaaaaa flags 00008065
cccccccc min aaaaaaaa bits 3c: cccccccc flags 000080c5
cccccccc min aaaaaaaa bits 3d: cccccccc flags 000080c5
cccccccc min aaaaaaaa bits 3e: cccccccc flags 000080c5
cccccccc min aaaaaaaa bits 3f: cccccccc flags 000080c5

So, select behavior again. This means that 0x49 is likely to be max.

fffffffe max fffffffe bits 38: fffffffe flags 000080f5
fffffffe max ffffffff bits 38: ffffffff flags 000080f5
fffffffe max 00000000 bits 38: 00000000 flags 0000800a
fffffffe max 00000001 bits 38: 00000001 flags 00008008
fffffffe max 00000002 bits 38: 00000002 flags 00008008
ffffffff max fffffffe bits 38: ffffffff flags 000080f5
ffffffff max ffffffff bits 38: ffffffff flags 000080f5
ffffffff max 00000000 bits 38: 00000000 flags 0000800a
ffffffff max 00000001 bits 38: 00000001 flags 00008008
ffffffff max 00000002 bits 38: 00000002 flags 00008008
00000000 max fffffffe bits 38: 00000000 flags 00008002
00000000 max ffffffff bits 38: 00000000 flags 00008002
00000000 max 00000000 bits 38: 00000000 flags 00008002
00000000 max 00000001 bits 38: 00000001 flags 00008000
00000000 max 00000002 bits 38: 00000002 flags 00008000
00000001 max fffffffe bits 38: 00000001 flags 00008000
00000001 max ffffffff bits 38: 00000001 flags 00008000
00000001 max 00000000 bits 38: 00000001 flags 00008000
00000001 max 00000001 bits 38: 00000001 flags 00008000
00000001 max 00000002 bits 38: 00000002 flags 00008000
00000002 max fffffffe bits 38: 00000002 flags 00008000
00000002 max ffffffff bits 38: 00000002 flags 00008000
00000002 max 00000000 bits 38: 00000002 flags 00008000
00000002 max 00000001 bits 38: 00000002 flags 00008000
00000002 max 00000002 bits 38: 00000002 flags 00008000

So it is. Time for 0x5e. We can already guess that it's an unsigned shift right.

fffffffe >> fffffffe bits 38: fffffff8 flags 000080f5
fffffffe >> ffffffff bits 38: fffffffc flags 000080f5
fffffffe >> 00000000 bits 38: fffffffe flags 000080f5
fffffffe >> 00000001 bits 38: 7fffffff flags 000080f4
fffffffe >> 00000002 bits 38: 3fffffff flags 000080f4
ffffffff >> fffffffe bits 38: fffffffc flags 000080f5
ffffffff >> ffffffff bits 38: fffffffe flags 000080f5
ffffffff >> 00000000 bits 38: ffffffff flags 000080f5
ffffffff >> 00000001 bits 38: 7fffffff flags 000080f4
ffffffff >> 00000002 bits 38: 3fffffff flags 000080f4
00000000 >> fffffffe bits 38: 00000000 flags 00008002
00000000 >> ffffffff bits 38: 00000000 flags 00008002
00000000 >> 00000000 bits 38: 00000000 flags 00008002
00000000 >> 00000001 bits 38: 00000000 flags 00008002
00000000 >> 00000002 bits 38: 00000000 flags 00008002
00000001 >> fffffffe bits 38: 00000004 flags 00008000
00000001 >> ffffffff bits 38: 00000002 flags 00008000
00000001 >> 00000000 bits 38: 00000001 flags 00008000
00000001 >> 00000001 bits 38: 00000000 flags 00008002
00000001 >> 00000002 bits 38: 00000000 flags 00008002
00000002 >> fffffffe bits 38: 00000008 flags 00008000
00000002 >> ffffffff bits 38: 00000004 flags 00008000
00000002 >> 00000000 bits 38: 00000002 flags 00008000
00000002 >> 00000001 bits 38: 00000001 flags 00008000
00000002 >> 00000002 bits 38: 00000000 flags 00008002

We confirm select behavior in the same way. Also, 0x4e could be the signed shift. Let's see:

fffffffe >> fffffffe bits 38: fffffff8 flags 000080f5
fffffffe >> ffffffff bits 38: fffffffc flags 000080f5
fffffffe >> 00000000 bits 38: fffffffe flags 000080f5
fffffffe >> 00000001 bits 38: ffffffff flags 000080f5
fffffffe >> 00000002 bits 38: ffffffff flags 000080f5
ffffffff >> fffffffe bits 38: fffffffc flags 000080f5
ffffffff >> ffffffff bits 38: fffffffe flags 000080f5
ffffffff >> 00000000 bits 38: ffffffff flags 000080f5
ffffffff >> 00000001 bits 38: ffffffff flags 000080f5
ffffffff >> 00000002 bits 38: ffffffff flags 000080f5
00000000 >> fffffffe bits 38: 00000000 flags 00008002
00000000 >> ffffffff bits 38: 00000000 flags 00008002
00000000 >> 00000000 bits 38: 00000000 flags 00008002
00000000 >> 00000001 bits 38: 00000000 flags 00008002
00000000 >> 00000002 bits 38: 00000000 flags 00008002
00000001 >> fffffffe bits 38: 00000004 flags 00008000
00000001 >> ffffffff bits 38: 00000002 flags 00008000
00000001 >> 00000000 bits 38: 00000001 flags 00008000
00000001 >> 00000001 bits 38: 00000000 flags 00008002
00000001 >> 00000002 bits 38: 00000000 flags 00008002
00000002 >> fffffffe bits 38: 00000008 flags 00008000
00000002 >> ffffffff bits 38: 00000004 flags 00008000
00000002 >> 00000000 bits 38: 00000002 flags 00008000
00000002 >> 00000001 bits 38: 00000001 flags 00008000
00000002 >> 00000002 bits 38: 00000000 flags 00008002

Fair enough. That leaves us with 0x45. Maybe it's a mov?

ffffffff op fffffffe bits 00: 00010000 flags 00008000
ffffffff op ffffffff bits 00: 00010000 flags 00008000
ffffffff op 00000000 bits 00: 00010000 flags 00008000
ffffffff op 00000001 bits 00: 00010000 flags 00008000
ffffffff op 00000002 bits 00: 00010000 flags 00008000
ffffffff op fffffffe bits 00: 00010000 flags 00008000
ffffffff op ffffffff bits 00: 00010000 flags 00008000
ffffffff op 00000000 bits 00: 00010000 flags 00008000
ffffffff op 00000001 bits 00: 00010000 flags 00008000
ffffffff op 00000002 bits 00: 00010000 flags 00008000
00000000 op fffffffe bits 00: 00010000 flags 00008000
00000000 op ffffffff bits 00: 00010000 flags 00008000
00000000 op 00000000 bits 00: 00010000 flags 00008000
00000000 op 00000001 bits 00: 00010000 flags 00008000
00000000 op 00000002 bits 00: 00010000 flags 00008000
00000000 op fffffffe bits 00: 00010000 flags 00008000
00000000 op ffffffff bits 00: 00010000 flags 00008000
00000000 op 00000000 bits 00: 00010000 flags 00008000
00000000 op 00000001 bits 00: 00010000 flags 00008000
00000000 op 00000002 bits 00: 00010000 flags 00008000
00000000 op fffffffe bits 00: 00010000 flags 00008000
00000000 op ffffffff bits 00: 00010000 flags 00008000
00000000 op 00000000 bits 00: 00010000 flags 00008000
00000000 op 00000001 bits 00: 00010000 flags 00008000
00000000 op 00000002 bits 00: 00010000 flags 00008000

Crap, it didn't even modify the destination register... however, it seems to have modified the source 1 register!

Well, after some testing, the only functionality of this instruction that I noticed is the source operand 1 is shifted right [with sign extension] by 4 bits and written back to source operand 1. The code uses it in a strange way, however:

00000000: 4538fff8     ??? $a7 $c0 $a3 $a30 [unknown: 05000018]
00000000: 4538fff8     ??? $a7 $c0 $a3 $a30 [unknown: 05000018]
00000000: 453cfff8     ??? $a7 $c0 $a19 $a30 [unknown: 05000018]

I suppose there's something more to it. We'll leave it for later.

0x41   1439    1091     mul $a [$c] $a (slct)
0x42   4233    3156     logop $a [$c] $a $a
0x45      3       3     ???
0x48    147     123     min $a [$c] $a (slct)
0x49      -       -     max $a [$c] $a (slct)
0x4c   4999    3653     add $a [$c] $a (slct)
0x4d   1878    1217     sub $a [$c] $a (slct)
0x4e      -       -     shr $a [$c] $a (slct)
0x4f  10747    4331     nop?
0x5e     50       8     sar $a [$c] $a (slct)
0x61      -       -     mul $a [$c] $a simm11
0x62   3390    2610     and $a [$c] $a simm11
0x63     48      10     xor $a [$c] $a simm11
0x64    348     266     or $a [$c] $a simm11
0x65   7634    4929     mov $a simm19
0x68    390     288     min $a [$c] $a simm11
0x69    236     192     max $a [$c] $a simm11
0x6a   3359    2640     mov $a to another register file
0x6b   3203    2516     mov $a from another register file
0x6c   3045    2424     add $a [$c] $a simm11
0x6d      -       -     sub $a [$c] $a simm11
0x6e   8013    6040     sar $a [$c] $a simm11
0x75   3323    2415     sethi $a imm16
0x7e    534     450     shr $a [$c] $a simm11

Elapsed time: 7h

Currently unrated

Comments

There are currently no comments

New Comment

required

required (not published)

optional

required