NEC DSP UPD77016 Disassembler - Help? Anyone?! - Page 1
Forum section: electronics / general

author: pcbbc
author_rank: Newbie
timestamp: October 26, 2021, 02:31:43 pm
content: Hi All,Okay, I'm attempting to disassemble some code for a NEC UPD77115A.DatasheetInstruction Reference ManualI can't find a disassembler, so I'm writing my own. Here's the output I have so far...Code:0200: 2C002000 jmp 0x02400201: 00000000 nop0202: 00000000 nop0203: 00000000 nop0204: 00000000 nop0205: 26000000 iret0206: 00000000 nop0207: 00000000 nop0208: 00000000 nop0209: 26000000 iret020A: 00000000 nop020B: 00000000 nop020C: 00000000 nop020D: 26000000 iret020E: 00000000 nop020F: 00000000 nop0210: 00000000 nop0211: 26000000 iret0212: 00000000 nop0213: 00000000 nop0214: 00000000 nop0215: 26000000 iret0216: 00000000 nop0217: 00000000 nop0218: 00000000 nop0219: 26000000 iret021A: 00000000 nop021B: 00000000 nop021C: 2C036000 jmp 0x08DC021D: 26000000 iret021E: 00000000 nop021F: 00000000 nop0220: 2C032100 jmp 0x08620221: 26000000 iret0222: 00000000 nop0223: 00000000 nop0224: 2C031F00 jmp 0x08620225: 26000000 iret0226: 00000000 nop0227: 00000000 nop0228: 2C032D00 jmp 0x08820229: 26000000 iret022A: 00000000 nop022B: 00000000 nop022C: 2C034780 jmp 0x08BB022D: 26000000 iret022E: 00000000 nop022F: 00000000 nop0230: 2C00ED00 jmp 0x040A0231: 26000000 iret0232: 00000000 nop0233: 00000000 nop0234: 2C00FD80 jmp 0x042F0235: 26000000 iret0236: 00000000 nop0237: 00000000 nop0238: 2C034A00 jmp 0x08CC0239: 26000000 iret023A: 00000000 nop023B: 00000000 nop023C: 2C030900 jmp 0x084E023D: 26000000 iret023E: 00000000 nop023F: 00000000 nop0240: 61000000 clr(r0)0241: 38013007 r0l = 0x30070242: 48103805 X = r0h0243: 38010004 r0l = 0x00040244: 48103804 X = r0hSo, what looks like a fairly sensible 64 word vector area (see datasheet page 21/22), and the reset vector @ 0x0200 jumps to address 0x0240 where there's also some sensible looking initialisation code.However here's where I'm running into problems. The code clears r0 (40 bits), then sets thelow16 bits to immediate value 0x3007.Then we have instruction 0x48103805 which decodes to X =r0h, at least as far as I can tell from the Instruction Reference Manual.Surely that should be X =r0las we've justed loaded thelow16 bits?Even more so since we go on to load the 16 bit immediate value 0x0004 to r0l (thus overwriting the previous value without apparently using it).Similarly for the subsequent initialisation of address X.The confussion for me is in reading the instruction table in Fig A-4 (Load/Store Instruction Format 2/2) on page 128 of the Instruction Reference Manual.0x48103805 decodes as...010010b reg=000b suf=001b xy=0b 00b d=0b direct=0x3805But how to interpret the suf+d column? And what is the meaning of "d"? Direction???I has assumed rows of the table are for increassing suf vales 0..7 (as for example how reg bits are presumably encoded). So suf=001b decodes as *dp = regh.But that doesn't seem right, because as discussed above we might be expecting *dp = regl, which should perhaps be encoded as suf=000b.Similar problems exist for interpreting many other instruction formats, since there's no indication of the individual field bit codings.Have I missed something? Clues anyone? Things that would help...Better instruction reference manualExisting disassemblerExisting assemblerHoping there's someone who's woroked with this flavour of DSP chip in the past and can offer some insight.Cheers, Stuart.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: October 26, 2021, 08:33:28 pm
content: Just a guess: a register of this CPU consists of 3 parts (e, h, l), so each bit of 3-bitsufcould be a direct enable signal for one part (i.e. 001 - l, 010 - h, 100 - e, so eh would be 110 and full reg - 111). From the hw designer’s point - why encode something into sequential numbers if there are enough bits to be used directly?

author: pcbbc
author_rank: Newbie
timestamp: October 26, 2021, 11:23:25 pm
content: Quote from: abyrvalg on October 26, 2021, 08:33:28 pmGood suggestion, but the 3sufbits code need to code for all of the following...*dp = regl*dp = regh*dp = regeregl = *dpregh = *dprege = *dpregeh = *dpreg = *dpEven if you saydis for direction (so there are duplicates listed forregl,reghandrege) there's still the unidirectionalregehandregflavours to code for. So at least 5 codings required in total.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: October 27, 2021, 08:56:51 am
content: Yes,dclearly looks like direction. Check other transfer instructions (Inter-Register Transfer,Immediate Value Set) - this bit is shown with a fixed value there and the value matches direction.That 8-case table is labeledsuf+d, so it should look like this actually:d = 0d = 1*dp = reglregl = *dp*dp = reghregh = *dp*dp = regerege = *dp-regeh = *dp-reg = *dpAnd, if my "lane enable" guess is correct, first three rows will correspond to a single 1 bit insufeach (not sure about the order, but your example suggestslis lsb),regehrow will have two bits set (those forregeandregh- enabling both lanes), and theregrow will besuf=111 - enabling all 3 lanes.So the full table could look like this:sufd = 0d = 1001*dp = reglregl = *dp010*dp = reghregh = *dp100*dp = regerege = *dp110-regeh = *dp111-reg = *dp

author: pcbbc
author_rank: Newbie
timestamp: October 27, 2021, 01:42:24 pm
content: Of course, makes perfect sense. I should have got the full implication of what you meant from your first post. Thanks for taking the time to explain more fully.After I'd posted I'd already concluded that suf=010b most likely coresponded toregh. It should have twigged...Okay, having implemented this in the disassembler I find the code is usingallof the suf combinations as you presented in your table...sufd = 0d = 1001*dp = reglregl = *dp010*dp = reghregh = *dp100*dp = regerege = *dp110-regeh = *dp111-reg = *dp...and more importantlynoneof the blank ones. I think you've certainly cracked it.Unfortunately now there are similar problems with other instruction formats...Format A-2 page 124. 4 bits but only 14 intructions listed.Format A-3 page 125. 4 bits but only 8 instructions listed.It's interesting that format A-10 page 137 has a blank row, so they actually got that layout correct such that you could imply the coding by order! Here the low order bit of the condition code indicates the negation of the test, so cond=0001b would be NEVER (esentially a NOP), as it's the negation of the EVER with cond=0000b.Anyway, I feel I've already taken up enough of your time. I'll try and work through the remaining by looking for any orthogonality with the other instructions, which are actually used in the code, and if they make any sense (or not).

author: abyrvalg
author_rank: Frequent Contributor
timestamp: October 27, 2021, 04:50:55 pm
content: Great! I enjoy such riddles, post more samples if you need any helpNote that A-3 op table (that one with just 8 ops for 4 bits) looks similar to the second half of A-1's op table, the encoding could be the same.A-2 - try gathering statistics of real code to see which two combinations are never used. Perhaps the table is ordered correctly and you just need to find where to insert two blank rows there.BTW, are you developing a standalone tool or a plugin to some "big" disassembler (IDA Pro, Ghidra etc)? For any serious disasm having the power of one of those tools is a game changer. IDA could be a bit pricy depending on the project scale, but Ghidra is free.

author: pcbbc
author_rank: Newbie
timestamp: October 27, 2021, 11:27:16 pm
content: Thanks. Yes me too, although a processor instruction manual really shouldn’t have such riddles…I’ve a feeling marketing got their hands on the spec after tech wrote it and were like “All these blank lines in tables? Tush, tush! I can fix that so it looks real nice!”.Enjoyable, but as a friend of mine once said, “Enjoyable like banging your head against a brick wall”! That is to say, enjoyable when it stops (i.e. you solved the riddle)!Already ahead of you on that one. Yes, A3 doesn’t use any of the codes 0000b through 0111b. So all 8 in the “top” half. They do appear to be in order from what I can tell. A2 is missing 0000b, 1010b and 1011b codings. The code seems to do all its compares with r = r’ - r’’ and then checking using some conditional of r with zero. I’m assuming that LT is coded for with 0000b but just not used by the code I’m analysing, that 1010b and 1011b are unused, and that everything else is in order as presented.This code provides MP3 decode and an SD card interface for a car nav and entertainment system. Specifically the first generation of anAudi RNSE. The second generation unit got a faster more capable main CPU and onboarded these functions, thus doing away with the DSP.I already have a home developed emulator for the system (both generations), but for the first generation unit I’m unable to emulate MP3 playback or SD card access. Trying to reverse engineer what the main CPU is expecting back from the DSP chip host interface, without any knowledge of the DSP code, is beyond hard.Did contemplate writing a Ghidra plugin, but with only a few K words of code I think hand commenting is probably manageable. I think next step might be to emulate the DSP (actually 2 of them, one for each SD card slot) as a subsystem to the main emulator.Again I have to thank you for your insight and willingness to help. I’ll be sure to post back, if only as an update on progress.