///////////////////////////////////////////////////////////////////////////////
ROM functions used:
0x8000    dsp reset
0x8078    wait for CMBH & 0x8000
0x807e    wait for DMBH & 0x8000
0x808b    dump DRAM/IRAM to mainmem
0x80b5    boot new ucode
0x80bc    boot new ucode without ACC clearing by ROM

For the rest, this ucode is just calling the last few instructions
from huge functions in irom - some kind of obfuscation
Perhaps someone thought the irom would never be dumped? ;p

Similarly, drom is used pretty extensively as a source of what is intended to
be "mystery" numbers. Usually a word will be fetched, and masked to create a
simple value. No problem! :)

0x81f4
    mulxac'mv   $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M
    asr16'ir    $ACC1 : $AR1
    srri        @$AR3, $AC1.M
    clr's       $ACC0 : @$AR3, $AC1.L
0x8458
    mulxac'mv   $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M
    asr16       $ACC1
    srri        @$AR3, $AC1.M
    clr's       $ACC0 : @$AR3, $AC1.L
0x8723
    xorr        $AC1.M, $AX1.H
    srrd        @$AR2, $AC1.M
0x8809
    orr'sn      $AC1.M, $AX0.H : @$AR2, $AC1.L
    srri        @$AR2, $AC1.M
0x88e5
    orr'l       $AC0.M, $AX0.H : $AC1.M, @$AR2
    lrrd        $AC1.L, @$AR2
    add'dr      $ACC0, $ACC1 : $AR1
    srri        @$AR2, $AC0.M
    srr         @$AR2, $AC0.L

struct sec_params_t
{
    u32 key;         // from gba
    u32 unk1;        // normally 2
    u32 unk2;        // normally 2
    u32 length;      // size of data transferred to gba
    u32 dest_addr;   // addr to store result in mram
    u32 pad[3];
}

// exception vector
0000 0000      nop
0001 0000      nop
0002 0000      nop
0003 0000      nop
0004 0000      nop
0005 0000      nop
0006 0000      nop
0007 0000      nop
0008 0000      nop
0009 0000      nop
000a 0000      nop
000b 0000      nop
000c 0000      nop
000d 0021      halt
000e 02ff      rti
000f 0021      halt

// entry point
void 0010_main()
{
0010 1306      sbset       #0x06
0011 1203      sbclr       #0x03
0012 1204      sbclr       #0x04
0013 1305      sbset       #0x05
0014 0092 00ff lri         $CR, #0x00ff
0016 0088 ffff lri         $WR0, #0xffff
0018 0089 ffff lri         $WR1, #0xffff
001a 008a ffff lri         $WR2, #0xffff
001c 008b ffff lri         $WR3, #0xffff
001e 8f00      set40
001f 8b00      m0
0020 8c00      clr15
0021 02bf 807e call        0x807e            // loop until dsp->cpu mailbox is empty
0023 16fc dcd1 si          @DMBH, #0xdcd1
0025 16fd 0000 si          @DMBL, #0x0000    // sendmail 0xdcd10000
0027 16fb 0001 si          @DIRQ, #0x0001

// wait for cpu mail == 0xabbaxxxx
0029 02bf 8078 call        0x8078            // wait for cpu mail
002b 24ff      lrs         $AC0.L, @CMBL
002c 0280 abba cmpi        $AC0.M, #0xabba
002e 0294 0029 jnz         0x0029

// wait for cpu mail
0030 8e00      set16
0031 02bf 8078 call        0x8078

0033 20ff      lrs         $AX0.L, @CMBL
0034 0240 0fff andi        $AC0.M, #0x0fff
0036 1f5e      mrr         $AX0.H, $AC0.M
0037 009b 0000 lri         $AX1.H, #0x0000   // DSP-dram addr
0039 0099 0020 lri         $AX1.L, #0x0020   // length (20 bytes = 10 words, word 9 and 10 are addr where result should DMA'd to in main mem)
003b 0087 0000 lri         $IX3, #0x0000     // there will be no ucode/iram upload
003d 0080 0041 lri         $AR0, #0x0041     // return addr after dram upload
003f 029f 80bc jmp         0x80bc            // DRAM upload !!
// $AX0.H-$AX0.L - CPU(PPC) addr = mail & 0x0fffffff
// upload data from mainmem do dsp dram and jump to 0x41 after that

0041 02bf 008c call        008c_BigCrazyFunction()
0043 02bf 807e call        0x807e            // loop until dsp->cpu mailbox is empty

0045 16fc dcd1 si          @DMBH, #0xdcd1
0047 16fd 0003 si          @DMBL, #0x0003    // sendmail 0xdcd10003 (aka... calc is over, result is in main mem now)
0049 16fb 0001 si          @DIRQ, #0x0001
004b 8f00      set40

004c 02bf 8078 call        0x8078
004e 0280 cdd1 cmpi        $AC0.M, #0xcdd1
0050 0294 004c jnz         0x004c

0052 26ff      lrs         $AC0.M, @CMBL
0053 0280 0001 cmpi        $AC0.M, #0x0001
0055 0295 005e jz          0x005e            // if cpu->dsp mail was 0xcdd10001 -> 005e_PrepareBootUcode()

0057 0280 0002 cmpi        $AC0.M, #0x0002
0059 0295 8000 jz          0x8000            // if cpu->dsp mail was 0xcdd10002 -> dsp reset ( jmp to irom(0x8000))

005b 029f 004c jmp         0x004c            // wait for next mail from cpu
005d 0021      halt
}

void 005e_PrepareBootUcode()
{
005e 8e00      set16
005f 02bf 8078 call        0x8078
0061 24ff      lrs         $AC0.L, @CMBL     // ???
0062 02bf 8078 call        0x8078
0064 24ff      lrs         $AC0.L, @CMBL     // ???
0065 02bf 8078 call        0x8078
0067 24ff      lrs         $AC0.L, @CMBL     // ???
0068 02bf 8078 call        0x8078
006a 00c5 ffff lr          $IX1, @CMBL
006c 0240 0fff andi        $AC0.M, #0x0fff
006e 1c9e      mrr         $IX0, $AC0.M      // mram addr for iram
006f 02bf 8078 call        0x8078
0071 00c7 ffff lr          $IX3, @CMBL       // iram upload length. upload skipped if 0
0073 02bf 8078 call        0x8078
0075 00c6 ffff lr          $IX2, @CMBL       // iram dest
0077 02bf 8078 call        0x8078
0079 00c0 ffff lr          $AR0, @CMBL       // startpc / return addr
007b 02bf 8078 call        0x8078
007d 20ff      lrs         $AX0.L, @CMBL
007e 0240 0fff andi        $AC0.M, #0x0fff
0080 1f5e      mrr         $AX0.H, $AC0.M    // mram addr for dram
0081 02bf 8078 call        0x8078
0083 21ff      lrs         $AX1.L, @CMBL     // dram upload length. upload skipped if 0
0084 02bf 8078 call        0x8078
0086 23ff      lrs         $AX1.H, @CMBL     // dram dest
0087 1205      sbclr       #0x05
0088 1206      sbclr       #0x06
0089 029f 80b5 jmp         80b5_BootUcode()
008b 0021      halt
}

// does some crazy stuff with data at dram @0x3/0x5/0x6/0x7 with help of some values from drom :)
// result is @0x22,@0x23 and written back to main memory to dmem-0x08:dmem-0x09
void 008c_BigCrazyFunction()
{
// 008c 8100      clr         $ACC0
// 008d 0081 0010 lri         $AR1, #0x0010
// 008f 1020      loopi       #0x20
//     0090 1b3e      srri        @$AR1, $AC0.M
    memset(0x10, 0, 0x20 * sizeof(dsp_word));

// 0091 00df 1456 lr          $AC1.M, @0x1456            // drom 102f
// 0093 0340 ffd0 andi        $AC1.M, #0xffd0            // -> 0x1000
// 0095 8417      clrp'mv     : $AX1.L, $AC1.M           // clrp, ax1.l = 0x1000
    IMPORTANT: "confusing" section relies on prod being cleared, and ax1.l == 0x1000

// 0096 0080 0000 lri         $AR0, #0x0000
// 0098 0086 0000 lri         $IX2, #0x0000
// 009a 0082 001f lri         $AR2, #0x001f
// 009c 00de 15f6 lr          $AC0.M, @0x15f6            // drom 7f65
// 009e 1408      lsl         $ACC0, #8                  // -> 0x7f_6500
// 009f 00df 1766 lr          $AC1.M, @0x1766            // drom 0273
// 00a1 0340 00ff andi        $AC1.M, #0x00ff            // -> 0x73
// 00a3 1f5f      mrr         $AX0.H, $AC1.M             // ax0.h = 0x73
// 00a4 02bf 88e5 call        0x88e5                     // ar2 = 0x1f, ar1 = 0x30
//     orr'l       $AC0.M, $AX0.H : $AC1.M, @$AR2        // acc0 = 0x7f_6573, ac1.m = 0, ar2 = 0x20
//     lrrd        $AC1.L, @$AR2                         // ac1.l = 0, ar2 = 0x1f
//     add'dr      $ACC0, $ACC1 : $AR1
//     srri        @$AR2, $AC0.M                         // *0x1f = 0x6573, ar2 = 0x20
//     srr         @$AR2, $AC0.L                         // *0x20 = 0
// 00a6 1f1c      mrr         $AX0.L, $AC0.L             // ax0.l = 0
// 00a7 811e      clr'mv      $ACC0 : $AX1.H, $AC0.M     // acc0 = 0, ax1.h = 0x6573
// 00a8 191e      lrri        $AC0.M, @$AR0              // ac0.m = sec_params.key[0], ar1 = 1
// 00a9 1478      lsr         $ACC0, #-8                 // acc0 0x00_00.._..00
// 00aa 1ffc      mrr         $AC1.M, $AC0.L             // ac1.m = sec_params.key[0] & 0x00ff
// 00ab 1f5e      mrr         $AX0.H, $AC0.M             // ax0.h = sec_params.key[0] >> 8
// 00ac 02bf 8809 call        0x8809
//     orr'sn      $AC1.M, $AX0.H : @$AR2, $AC1.L        // ac1.m |= ax0.h ..tricky tricky :D
//     srri        @$AR2, $AC1.M                         // *0x20 = bswap(sec_params.key[0]), ar2 = 0x21
// 00ae 02bf 8723 call        0x8723
//     xorr        $AC1.M, $AX1.H                        // ac1.m = sec_params.key[0] ^ 0x6573
//     srrd        @$AR2, $AC1.M                         // *0x21 = bswap(sec_params.key[0]) ^ 0x6573, ar2 = 0x20
    // Initialize 0x21
    *0x1f = 0x6573
    *0x20 = bswap(sec_params.key[0])
    *0x21 = bswap(sec_params.key[0]) ^ 0x6573

// 00b0 0006      dar         $AR2                       // ar2 = 0x1f
// 00b1 8106      clr'dr      $ACC0 : $AR2               // acc0 = 0, ar2 = 0x1e
// 00b2 00de 166c lr          $AC0.M, @0x166c            // drom 06f2
// 00b4 1404      lsl         $ACC0, #4
// 00b5 0240 ff00 andi        $AC0.M, #0xff00            // -> 0x6f00
// 00b7 00df 1231 lr          $AC1.M, @0x1231            // drom 64fc
// 00b9 1578      lsr         $ACC1, #-8
// 00ba 0340 00ff andi        $AC1.M, #0x00ff            // -> 0x64
// 00bc 1f5f      mrr         $AX0.H, $AC1.M             // ax0.h = 0x64
// 00bd 02bf 88e5 call        0x88e5
//     orr'l       $AC0.M, $AX0.H : $AC1.M, @$AR2        // ac0.m = 0x6f64, ac1.m = 0, ar2 = 0x1f
//     lrrd        $AC1.L, @$AR2                         // ac1.l = 0x6573, ar2 = 0x1e
//     add'dr      $ACC0, $ACC1 : $AR1                   // acc0 = 0x00_6f64_6573
//     srri        @$AR2, $AC0.M                         // *0x1e = 0x6f64, ar2 = 0x1f
//     srr         @$AR2, $AC0.L                         // *0x1f = 0x6573
// 00bf 1f1c      mrr         $AX0.L, $AC0.L
// 00c0 811e      clr'mv      $ACC0 : $AX1.H, $AC0.M     // acc0 = 0, ax1.h = 0x6f64
// 00c1 191e      lrri        $AC0.M, @$AR0              // ac0.m = sec_params.key[1]
// 00c2 1478      lsr         $ACC0, #-8                 // acc0 = 0x00_00.._..00
// 00c3 1ffc      mrr         $AC1.M, $AC0.L             // ac1.m = sec_params.key[1] & 0xff
// 00c4 1f5e      mrr         $AX0.H, $AC0.M             // ax0.h = sec_params.key[1] >> 8
// 00c5 02bf 8809 call        0x8809
//     orr'sn      $AC1.M, $AX0.H : @$AR2, $AC1.L        // ac1.m |= ax0.h
//     srri        @$AR2, $AC1.M                         // *0x1f = bswap(sec_params.key[1]), ar2 = 0x20
// 00c7 02bf 8723 call        0x8723
//     xorr        $AC1.M, $AX1.H
//     srrd        @$AR2, $AC1.M                         // *0x20 = bswap(sec_params.key[1]) ^ 0x6f64
    // Initialize 0x20
    *0x1e = 0x6f64
    *0x1f = bswap(sec_params.key[1])
    *0x20 = bswap(sec_params.key[1]) ^ 0x6f64

    // Initialize 0x11
// 00c9 8100      clr         $ACC0
// 00ca 8900      clr         $ACC1
// 00cb 00d1 0005 lr          $AC1.H, @0x0005
// 00cd 9900      asr16       $ACC1                      // s16 unk2 = (s8)(sec_params.unk2[1])
// 00ce 8200      cmp
// 00cf 0295 00e5 jz          0x00e5
// 00d1 0291 00f3 jl          0x00f3
if (unk2 < 0) {
    // 00d3 0082 0010 lri         $AR2, #0x0010
    // 00d5 0086 0001 lri         $IX2, #0x0001          // 'sn will inc ar2 by 1
    // 00d7 00d0 171b lr          $AC0.H, @0x171b        // drom ff03
    // 00d9 9100      asr16       $ACC0                  // -> 0x00_0003_0000
    // 00da 7d00      neg         $ACC1
    // 00db 4d00      add         $ACC1, $ACC0
    // 00dc 1501      lsl         $ACC1, #1
    // 00dd 1f5f      mrr         $AX0.H, $AC1.M         // ax0.h = ((~unk2 + 3) << 1) & 0xffff
    // 00de 00df 0003 lr          $AC1.M, @0x0003        // sec_params.unk1[1]
    // 00e0 1504      lsl         $ACC1, #4
    // 00e1 02bf 8809 call        0x8809
    //     orr'sn      $AC1.M, $AX0.H : @$AR2, $AC1.L    // ac1.m = (((~unk2 + 3) << 1) & 0xffff) | (sec_params.unk1[1] << 4), ar2 = 0x11
    //     srri        @$AR2, $AC1.M
    // 00e3 029f 0102 jmp         0x0102
	    *0x11 = (((~unk2 + 3) << 1) | (sec_params.unk1[1] << 4)) & 0xffff

} else if (unk2 == 0) {
    // unk2 is unused
    // 00e5 0082 0011 lri         $AR2, #0x0011
    // 00e7 00df 0003 lr          $AC1.M, @0x0003        // sec_params.unk1[1]
    // 00e9 1501      lsl         $ACC1, #1
    // 00ea 1f5f      mrr         $AX0.H, $AC1.M         // ax0.h = sec_params.unk1[1] << 1
    // 00eb 00de 1043 lr          $AC0.M, @0x1043        // drom 0076
    // 00ed 0240 fff0 andi        $AC0.M, #0xfff0        // -> 0x70
    // 00ef 02bf 88e5 call        0x88e5
    //     orr'l       $AC0.M, $AX0.H : $AC1.M, @$AR2    // ac0.m = (sec_params.unk1[1] << 1) | 0x70, ac1.m = 0, ar2 = 0x12
    //     lrrd        $AC1.L, @$AR2                     // ar2 = 0x11
    //     add'dr      $ACC0, $ACC1 : $AR1               // acc1 must be 0
    //     srri        @$AR2, $AC0.M                     // *0x11 = (sec_params.unk1[1] << 1) | 0x70, ar2 = 0x12
    //     srr         @$AR2, $AC0.L                     // *0x12 = 0    // just a side effect, it's already 0 anyways
    // 00f1 029f 0102 jmp         0x0102
	    *0x11 = ((sec_params.unk1[1] << 1) | 0x70) & 0xffff

} else if (unk2 > 0) {
    // 00f3 0082 0010 lri         $AR2, #0x0010
    // 00f5 0086 0001 lri         $IX2, #0x0001          // 'sn will inc ar2 by 1
    // 00f7 00d0 1285 lr          $AC0.H, @0x1285        // drom 5aff (0xffff because of .h)
    // 00f9 9100      asr16       $ACC0                  // -> 0xff_ffff_0000 = -1
    // 00fa 4d00      add         $ACC1, $ACC0           // ac1.m = unk2 - 1
    // 00fb 1501      lsl         $ACC1, #1              // ac1.m <<= 1 ..in the normal case, this makes it 2 again...
    // 00fc 00de 0003 lr          $AC0.M, @0x0003        // sec_params.unk1[1]
    // 00fe 1404      lsl         $ACC0, #4
    // 00ff 1f5e      mrr         $AX0.H, $AC0.M         // ax0.h = sec_params.unk1[1] << 4
    // 0100 02bf 8809 call        0x8809
    //     orr'sn      $AC1.M, $AX0.H : @$AR2, $AC1.L    // ac1.m = ((unk2 - 1) << 1) | (sec_params.unk1[1] << 4), ar2 = 0x11
    //     srri        @$AR2, $AC1.M
	    *0x11 = (((unk2 - 1) << 1) | (sec_params.unk1[1] << 4)) & 0xffff
}

// This just clears acc1
// 0102 0083 0013 lri         $AR3, #0x0013
// 0104 1b7e      srri        @$AR3, $AC0.M              // *0x13 = intermediate from above -> unused
// 0105 8923      clr's       $ACC1 : @$AR3, $AC0.L      // acc1 = 0, *0x14 = intermediate from above -> unused

// The "confusion"
// 0106 0083 0013 lri         $AR3, #0x0013
// 0108 00df 0007 lr          $AC1.M, @0x0007            // ac1.m = sec_params.length[1]
// 010a 00de 11b8 lr          $AC0.M, @0x11b8            // drom 007f
// 010c 0240 fff0 andi        $AC0.M, #0xfff0            // -> 0x70
// 010e 1f5e      mrr         $AX0.H, $AC0.M             // ax0.h = 0x70
// 010f 02bf 81f4 call        0x81f4
//     mulxac'mv   $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M// prod = 0x70 * 0x1000 : .m1 = 7
//     asr16'ir    $ACC1 : $AR1                          // ac1.l = sec_params.length[1], the rest of acc1 must be 0
//     srri        @$AR3, $AC1.M                         // *0x13 = 0, ar3 = 0x14
//     clr's       $ACC0 : @$AR3, $AC1.L                 // acc0 = 0, *0x14 = sec_params.length[1], ar3 = 0x15
//
// 0111 f100      lsl16       $ACC1                      // ac1.m = sec_params.length[1]
// 0112 02bf 8458 call        0x8458                     // this is the same routine, just adds 7 and stores to different location
//     mulxac'mv   $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M// acc1 += 7    // last prod has 7 in the mid
//     asr16       $ACC1                                 // ac1.l = sec_params.length[1] + 7
//     srri        @$AR3, $AC1.M                         // *0x15 = 0, ar3 = 0x16
//     clr's       $ACC0 : @$AR3, $AC1.L                 // *0x16 = sec_params.length[1] + 7
    *0x13 = 0
    *0x14 = sec_params.length[1]
    *0x15 = 0
    *0x16 = sec_params.length[1] + 7

// 0114 8f00      set40                                  // SIGN EXTENSION IN EFFECT!!
// 0115 0082 0015 lri         $AR2, #0x0015
// 0117 00de 0006 lr          $AC0.M, @0x0006            // ac0.m = sec_params.length[0] ..always 0?    // sign extended
// 0119 00da 165b lr          $AX0.H, @0x165b            // drom 0000
// 011b 02bf 88e5 call        0x88e5
//     orr'l       $AC0.M, $AX0.H : $AC1.M, @$AR2        // ac0.m = sec_params.length[0], effectively clears acc1 (*0x15 == 0), ar2 = 0x16
//     lrrd        $AC1.L, @$AR2                         // ac1.l = sec_params.length[1] + 7, ar2 = 0x15
//     add'dr      $ACC0, $ACC1 : $AR1                   // ac0.m = sec_params.length[0], ac0.l = sec_params.length[1] + 7
//     srri        @$AR2, $AC0.M                         // *0x15 = sec_params.length[0], ar2 = 0x16
//     srr         @$AR2, $AC0.L                         // *0x16 = sec_params.length[1] + 7
// 011d 14fd      asr         $ACC0, #-3
// 011e 1403      lsl         $ACC0, #3                  // ((acc0 + 7) & ~7) (round up)        // consider .length rounded from here on out
// 011f 1b5e      srri        @$AR2, $AC0.M              // *0x16 = sec_params.length[0], ar2 = 0x17
// 0120 1b5c      srri        @$AR2, $AC0.L              // *0x17 = sec_params.length[1], ar2 = 0x18
// 0121 0082 0016 lri         $AR2, #0x0016
// 0123 00de 1723 lr          $AC0.M, @0x1723            // drom ffe0    // obviously sign extended
// 0125 14f4      asr         $ACC0, #-12                // -> 0xff_ffff_fe00 = -1, -0x200
// 0126 00da 166b lr          $AX0.H, @0x166b            // drom 0000
// 0128 02bf 88e5 call        0x88e5
//     orr'l       $AC0.M, $AX0.H : $AC1.M, @$AR2        // ac1.m = sec_params.length[0]        // sign extended
//     lrrd        $AC1.L, @$AR2                         // ac1.l = sec_params.length[1]
//     add'dr      $ACC0, $ACC1 : $AR1                   // acc0 = sec_params.length - 0x200    // this is a proper signed operation :)
//     srri        @$AR2, $AC0.M                         // *0x16 = sec_params.length - 0x200 HIGH
//     srr         @$AR2, $AC0.L                         // *0x17 = sec_params.length - 0x200 LOW
    // The above block just does 40bit subtraction...so annoying :p
    *0x15 = sec_params.length[0]
    *0x16 = sec_params.length - 0x200 HIGH
    *0x17 = sec_params.length - 0x200 LOW

// 012a b100      tst         $ACC0
// 012b 0290 012e jge         0x012e
// 012d 8100      clr         $ACC0
if (acc0 < 0) acc0 = 0

// At this point, ACC0 = max40bit(0, sec_params.length - 0x200)

// 012e 14fd      asr         $ACC0, #-3                 // taken into account at 013f
// 012f 8e00      set16                                  // back to sanity

// voodoo
0130 00df 1491 lr          $AC1.M, @0x1491               // drom 6a0f
0132 0340 d0f0 andi        $AC1.M, #0xd0f0               // -> 0x4000
0134 1cbf      mrr         $IX1, $AC1.M                  // ix1 = 0x4000
0135 00df 1468 lr          $AC1.M, @0x1468               // drom f808
0137 00d1 11fc lr          $AC1.H, @0x11fc               // drom 0003
0139 157c      lsr         $ACC1, #-4                    // -> 0x00_3f80_8000
013a 1cdf      mrr         $IX2, $AC1.M                  // ix2 = 0x3f80
013b 00d1 11b8 lr          $AC1.H, @0x11b8               // drom 007f
013d 9900      asr16       $ACC1                         // -> 0x00_007f_3f80
013e 1418      lsl         $ACC0, #24
013f 1478      lsr         $ACC0, #-8                    // (((ACC0 >> 3) << 24) >> 8)
same as ((ACC0 >> 3) << 16) & 0x00_ffff_0000 -> ac0.m = (u16)((sec_params.length - 0x200) >> 3)
u16 size = (u16)((sec_params.length - 0x200) >> 3)
0140 1f5e      mrr         $AX0.H, $AC0.M                // ax0.h = size
0141 1ffe      mrr         $AC1.M, $AC0.M                // ac1.m = size
0142 1f65      mrr         $AX1.H, $IX1                  // ax1.h = 0x4000
0143 3600      andr        $AC0.M, $AX1.H                // ac0.m = size & 0x4000
0144 1402      lsl         $ACC0, #2                     // acc0 <<= 2                // t = (0x00_size_0000 & 0x00_4000_ffff) << 2
0145 1f66      mrr         $AX1.H, $IX2                  // ax1.h = 0x3f80
0146 3700      andr        $AC1.M, $AX1.H                // ac1.m = size & 0x3f80
0147 1501      lsl         $ACC1, #1                     // acc1 <<= 1                // u = (0x00_size_3f80 & 0x00_3f80_ffff) << 1
0148 4c00      add         $ACC0, $ACC1                  // acc0 += acc1              // t += u
0149 1518      lsl         $ACC1, #24
014a 9900      asr16       $ACC1                         // signed cast (s16)ac1.l (ends up in ac1.m)
014b 3500      andr        $AC1.M, $AX0.H                // ac1.m = (s16)u & size
014c 4c00      add         $ACC0, $ACC1                  // acc0 += acc1              // t += (s16)u & size
014d 00df 0012 lr          $AC1.M, @0x0012
014f 3f00      orc         $AC1.M, $AC0.M                // ac1.m = acc0 | 0x00_ffff_0000
0150 00ff 0012 sr          @0x0012, $AC1.M               // *0x12 = ac1.m
0152 1470      lsr         $ACC0, #-16                   //                           // t >>= 16        unsigned
0153 00df 0011 lr          $AC1.M, @0x0011
0155 3f00      orc         $AC1.M, $AC0.M
0156 00ff 0011 sr          @0x0011, $AC1.M               // *0x11 |= previous ac0.h, now at ac0.m <- so ac0.m = unsigned ac0.h
0158 1fa5      mrr         $AC1.L, $IX1                  // ac1.l = 0x4000
0159 1501      lsl         $ACC1, #1                     // ac1.l = 0x8000
015a 1fe6      mrr         $AC1.M, $IX2                  // ac1.m = 0x3f80 0x00_3f80_8000
015b f100      lsl16       $ACC1                         // ((acc1 << 16) >> 8) << 16
015c 15f8      asr         $ACC1, #-8
015d f500      lsr16       $ACC1                         // acc1 = 0x00_00ff_8080
015e 1f5f      mrr         $AX0.H, $AC1.M                // ax0.h = 0xff
015f 1f7d      mrr         $AX1.H, $AC1.L                // ax1.h = 0x8080
0160 8100      clr         $ACC0
0161 00de 0011 lr          $AC0.M, @0x0011
0163 3400      andr        $AC0.M, $AX0.H                // ac0.m = *0x11 & 0xff
0164 8900      clr         $ACC1                         // so it was all to setup ax0.h and ax1.h...
0165 00df 0012 lr          $AC1.M, @0x0012
0167 3500      andr        $AC1.M, $AX0.H                // ac1.m = *0x12 & 0xff
0168 4c00      add         $ACC0, $ACC1
0169 00df 0012 lr          $AC1.M, @0x0012
016b 1578      lsr         $ACC1, #-8
016c 4c00      add         $ACC0, $ACC1                  // acc0 = ((*0x11 & 0xff) << 16) + ((*0x12 & 0xff) << 16) + (*0x12 << 8)
016d 8900      clr         $ACC1
016e 1ffe      mrr         $AC1.M, $AC0.M
016f 1508      lsl         $ACC1, #8
0170 3b00      orr         $AC1.M, $AX1.H                // ac1.m = (ac0.m << 8) | 0x8080
0171 00de 0011 lr          $AC0.M, @0x0011
0173 3e00      orc         $AC0.M, $AC1.M                // final11 = *0x11 | (ac0.m << 8) | 0x8080
0174 00df 0012 lr          $AC1.M, @0x0012
0176 3b00      orr         $AC1.M, $AX1.H
0177 1cbf      mrr         $IX1, $AC1.M                  // final12 = *0x12 | 0x8080

// write the final values @22 and @23
// 0178 00da 15f1 lr          $AX0.H, @0x15f1            // drom 0200
// 017a 3500      andr        $AC1.M, $AX0.H
// 017b 0295 0192 jz          0x0192
if (final12 & 0x200 != 0) {

    // 017d 00df 10e2 lr          $AC1.M, @0x10e2        // drom 376f
    // 017f 1508      lsl         $ACC1, #8              // -> 0x37_6f00
    // 0180 1f5f      mrr         $AX0.H, $AC1.M
    // 0181 00df 103b lr          $AC1.M, @0x103b        // drom 0065
    // 0183 7900      decm        $AC1.M                 // -> 0x64
    // 0184 3900      orr         $AC1.M, $AX0.H
    // 0185 3080      xorc        $AC0.M, $AC1.M
    // 0186 00fe 0022 sr          @0x0022, $AC0.M        // *0x22 = final11 ^ 0x6f64
    // 0188 00dc 1229 lr          $AC0.L, @0x1229        // drom 657c
    // 018a 00dd 11f8 lr          $AC1.L, @0x11f8        // drom 0009
    // 018c 5c00      sub         $ACC0, $ACC1
    // 018d f000      lsl16       $ACC0
    // 018e 1fe5      mrr         $AC1.M, $IX1
    // 018f 3080      xorc        $AC0.M, $AC1.M         // *0x23 = final12 ^ 0x6573
    // 0190 029f 01a5 jmp         0x01a5
    *0x22 = final11 ^ 0x6f64
    *0x23 = final12 ^ 0x6573

} else {
    // 0192 00df 10ca lr          $AC1.M, @0x10ca        // drom 3461
    // 0194 1508      lsl         $ACC1, #8              // -> 0x34_6100
    // 0195 1f5f      mrr         $AX0.H, $AC1.M
    // 0196 00df 1043 lr          $AC1.M, @0x1043        // drom 0076
    // 0198 7500      incm        $AC1.M                 // -> 0x77
    // 0199 3900      orr         $AC1.M, $AX0.H
    // 019a 3080      xorc        $AC0.M, $AC1.M
    // 019b 00fe 0022 sr          @0x0022, $AC0.M        // *0x22 = final11 ^ 0x6177
    // 019d 00dc 1259 lr          $AC0.L, @0x1259        // drom 6143
    // 019f 00dd 16fe lr          $AC1.L, @0x16fe        // drom 0008
    // 01a1 4c00      add         $ACC0, $ACC1
    // 01a2 f000      lsl16       $ACC0
    // 01a3 1fe5      mrr         $AC1.M, $IX1
    // 01a4 3080      xorc        $AC0.M, $AC1.M         // *0x23 = final12 ^ 0x614b
    *0x22 = final11 ^ 0x6177
    *0x23 = final12 ^ 0x614b
}
// 01a5 00fe 0023 sr          @0x0023, $AC0.M            // taken care of above

// this is where result is written to main memory
// dsp mem 0x20-0x23 (8 bytes) are written back - only values @22 and @23 were modified, so result is 32bit
01a7 00da 0008 lr          $AX0.H, @0x0008               // sec_params.dest_addr[0]
01a9 00d8 0009 lr          $AX0.L, @0x0009               // sec_params.dest_addr[1]
01ab 009b 0020 lri         $AX1.H, #0x0020               // dsp addr
01ad 0099 0008 lri         $AX1.L, #0x0008               // length
01af 0087 0000 lri         $IX3, #0x0000                 // there will be no iram dma
01b1 02bf 808b call        0x808b                        // do it!

01b3 02df      ret
}

01b4 0000      nop
01b5 0000      nop
01b6 0000      nop
01b7 0000      nop
01b8 0000      nop
01b9 0000      nop
01ba 0000      nop
01bb 0000      nop
01bc 0000      nop
01bd 0000      nop
01be 0000      nop
01bf 0000      nop