1

I am trying to understand a piece of code, working on a C166 MCU. IDA correctly loads and displays the disassembly. Below is the code snippet I am trying to analyze. I don't understand the following instructions:

jmpr    cc_Z, loc_C112E8
jmpr    cc_Z, loc_C112E0
jmpr    cc_C, loc_C112A6

Here is the code of the function, I hope someone will shed a light when the jumps will be executed:


sub_C1129E:                             ; CODE XREF: sub_C07E4A+38↑P
                mov     [-r0], r8
                mov     r14, r12
                mov     r15, r13
                mov     r8, #0

loc_C112A6:                             ; CODE XREF: sub_C1129E+56↓j
                add     r12, #2C29h
                addc    r13, #0A74Dh
                xor     r12, #346h
                xor     r13, #4337h
                mov     r14, r12
                mov     r15, r13
                and     r14, #0
                and     r15, #8000h
                add     r12, r12
                addc    r13, r13
                or      r14, r15
                jmpr    cc_Z, loc_C112E8
                bset    r12.0
                mov     r14, r12
                mov     r15, r13
                and     r14, #1
                and     r15, #0
                shr     r12, #1
                bmov    r12.15, r13.0
                shr     r13, #1
                or      r14, r15
                jmpr    cc_Z, loc_C112E0
                bset    r13.15

loc_C112E0:                             ; CODE XREF: sub_C1129E+3E↑j
                xor     r12, #0C345h
                xor     r13, #985h

loc_C112E8:                             ; CODE XREF: sub_C1129E+28↑j
                xor     r12, #0D4E5h
                xor     r13, #0B2C3h
                add     r8, #1
                cmp     r8, #5
                jmpr    cc_C, loc_C112A6
                mov     r4, r12
                mov     r5, r13
                mov     r8, [r0+]
                rets
; End of function sub_C1129E

And here is my understanding of the algorithm converted to C code:

void sub_C1129E(short Param1, short Param2)
{
    short r12 = Param1;
    short r13 = Param2;
    short r14;
    r14 = r12;
    short r15 = r13;
    short r8 = 0;

loc_C112A6:                             // CODE XREF: sub_C1129E+56↓j
    r12 = (short)(r12 + 0x2C29);
    r13 = (short)(r13 + 0xA74D);//    addc    r13, #0A74Dh
    r12 = (short)(r12 ^ 0x346);//    xor r12, #346h
    r13 = (short)(r13 ^ 0x4337);//    xor     r13, #4337h
    r14 = r12;//    mov r14, r12
    r15 = r13;//    mov r15, r13
    r14 = (short)(r14 & 0);//    and r14, #0
    r15 = (short)(r15 & 0x8000);//    and     r15, #8000h
    r12 = (short)(r12 + r12);// add r12, r12
    r13 = (short)(r13 + r13);// addc r13, r13
    r14 = (short)(r14 | r15);//    or r14, r15

    // What to do here? TODO!!!    jmpr cc_Z, loc_C112E8

    r12 = (short)(r12 | 1);    // bset r12.0
    r14 = r12;//    mov r14, r12
    r15 = r13;//    mov r15, r13
    r14 = (short)(r14 & 1);//    and r14, #1
    r15 = (short)(r15 & 0);//    and     r15, #0
    r12 = (short)(r12 >> 1);//    shr r12, #1

    r12 = (short)(r12 & 0x7FFF | r13 << 15);// bmov    r12.15, r13.0

    r13 = (short)(r13 >> 1);//    shr r13, #1
    r14 = (short)(r14 | r15);//    or      r14, r15

    // What to do here? TODO!!!    jmpr    cc_Z, loc_C112E0

    r13 = (short)(r13 | 0x8000);// bset    r13.15

loc_C112E0:                             // CODE XREF: sub_C1129E+3E↑j
    r12 = (short)(r12 ^ 0xC345);
    r13 = (short)(r13 ^ 0x985);//    xor     r13, #985h

loc_C112E8:                             // CODE XREF: sub_C1129E+28↑j
    r12 = (short)(r12 ^ 0xD4E5);// xor r12, #0D4E5h
    r13 = (short)(r13 ^ 0xB2C3);// xor     r13, #0B2C3h
    r8 = (short)(r8 + 1);//add r8, #1
    if (r8 < 5)//    cmp     r8, #5
        goto loc_C112A6;// jmpr cc_C, loc_C112A6 -> NOT SURE IF THIS IS CORRECT...
    int r4 = r12;
    int r5 = r13;
}
3
  • 1
    Did you check the processor manual? What does it say about this instruction?
    – Igor Skochinsky
    Jul 14 at 21:52
  • 1
    You might try ghidra as a second reference. There is a C166 module on GitHub, and you'll get decompilation (quality depends on implementation, been a while since I've reviewed it, not sure exactly on its state)
    – mumbel
    Jul 17 at 18:55
  • My mistake is I didn't understand the "addc" instruction at first. After reading the manual a second time I found out the problems and fixed all of them. I must say IDA is doing a really great job and C166 is actually not so hard. Here are the fixes to the problematic parts of the code: code This is wrong: r12 = (short)(r12 + 0x2C29); r13 = (short)(r13 + 0xA74D);// addc r13, #0A74Dh This is correct: u32 = r12 + 0x2C29; if (u32 > 0xFFFF) u8Carry = 1; else u8Carry = 0; r12 = (unsigned short)(r12 + 0x2C29); r13 = (unsigned short)(r13 + 0xA74D + u8Carry); code
    – C0DER
    Jul 20 at 12:50

1 Answer 1

2

As far as I can see in the manual jmpr is jump relative, the first parameter is a condition, the second parameter is a label it should jump to if the condition is met.

Relativeness of the jump is not important for understanding the code, it refers to encoding of the instruction.

Description of the jmpr instruction in this document is on the page 91 of the manual, Description of the possible conditions is in table 5 on the page 38.

Conditions (specifically cc_Z and cc_C) are set by previously executed ALU operation (specifically or on the page 106 and cmp on the page 63 of the manual in your case).

1
  • In this case the "jmpr" instruction is used to test if r14 is equal to 0. In "C" code this translates to: if (r14 == 0x0000) goto loc_C112E8;
    – C0DER
    Jul 20 at 12:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.