Author Topic: EEVblog #1144 - Padauk Programmer Reverse Engineering  (Read 21522 times)

0 Members and 5 Guests are viewing this topic.

Offline EEVblog

  • Administrator
  • *****
  • Posts: 27441
  • Country: au
    • EEVblog
EEVblog #1144 - Padauk Programmer Reverse Engineering
« on: November 05, 2018, 11:34:00 am »
David looks at the pins on the Padauk PMS150 programmer for potential reverse engineering.

TLDR; It doesn't look easy to reverse engineer this protocol, it's messy with lots of voltage levels, as Padauk said it would be.
Just buy the programmer for now!
There is also a Flash/EEPROM re-programmable version of the chip, the PFS154C.

« Last Edit: November 05, 2018, 11:37:18 am by EEVblog »
 
The following users thanked this post: Inverted18650

Offline BrianHG

  • Super Contributor
  • ***
  • Posts: 2729
  • Country: ca
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #1 on: November 05, 2018, 12:02:01 pm »
Looks like the first generation PIC16C54 programming levels, with fewer active IOs.  The old PICs used to use half the IOs to be programmed with wacko voltage transients and some analog levels thrown in as well.
__________
BrianHG.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 5148
  • Country: us
    • Personal site
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #2 on: November 05, 2018, 12:16:54 pm »
Voltage levels on I/Os are probably not important, they are just matching the supply voltage, but it would probably work fine as long as you cross the threshold.

Just use a logic analyzer to grab their logical level. Clamp it with diodes if needed, although I suspect that simple current limiting resistors will be sufficient.
« Last Edit: November 05, 2018, 12:19:45 pm by ataradov »
Alex
 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #3 on: November 05, 2018, 01:53:26 pm »
Regarding the different voltage levels: Old EPROMs required this, too. For example some algorithms verified if it was programmed correctly at 6V and 4V. So might be that the highest voltage phase is the programming phase, and two other low voltage phases are verify, and maybe a normal voltage phase for reading the ID etc.
So Long, and Thanks for All the Fish
 

Offline Smokey

  • Super Contributor
  • ***
  • Posts: 1528
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #4 on: November 05, 2018, 04:33:43 pm »
Is anyone else a little confused by this?

Did I miss part of the video or something or did you not tell us how long the total programming time is? 
ms, seconds, tens of seconds?  That's kind of important to get an idea of the amount of data capture required.

Also did you intentionally grab the least capable data acquisition device possible?  We all know that lab is jam packed with high end gear that almost never gets used.  I'm pretty sure there are at least a couple multi-thousand-dollar deep memory 4 channel MSOs with real level triggering on the digital channels that should be more than capable.  I'm also pretty sure you can take the couple 4channel Keysight scopes sitting around, time correlate all the analog channels between scopes, and dump all that to a PC for a full time deep memory data dump.

It's one thing if you want to do some simple Arduino project video for beginners and don't want to scare viewers off by using test equipment they probably won't have.  It's another thing to do a real engineering project like reversing an uC programming procedure with only toy test equipment and then sound surprised when it didn't all just work out and you couldn't get all the data you needed.
 
The following users thanked this post: amyk

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #5 on: November 05, 2018, 05:34:02 pm »
In a Youtube comment David said the big scopes are still all in boxes, because of their move.
So Long, and Thanks for All the Fish
 

Offline Smokey

  • Super Contributor
  • ***
  • Posts: 1528
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #6 on: November 05, 2018, 06:17:14 pm »
In a Youtube comment David said the big scopes are still all in boxes, because of their move.

Ahhh.  Well that explains some things. 
It would be nice to put a big huge disclaimer at the beginning of the video that you actually know the equipment you are using is not the right tool for the job and will probably never have the capabilities to succeed and that you are really just playing.

Question:
Do you guys typically read the youtube comments?  Mark me as a "no".
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 2794
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #7 on: November 05, 2018, 07:35:11 pm »
I think you can probably decide that the pins not present on the SOT-6 package (PA0 (7) and PA7 (2)) are not particularly relevant to the programming spec...  (the programmer may check their presence to determine chip type, but if they were needed for the actual programming, there wouldn't be any way to program the SOT-6 version.)
 

Online HKJ

  • Frequent Contributor
  • **
  • Posts: 751
  • Country: dk
    • Tests
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #8 on: November 05, 2018, 08:08:25 pm »
I would look for the actual data protocol first, then the voltage levels and I doubt the chip will remember any state after a power cycle.

The first operation is probably reading some sort of chip identification.
Programming may be split into program memory and one or more configuration memories.
At least data memory needs an address and one or more data bytes for each programming pulse (Address may be auto increment).
Verification can be for each byte/block programmed or another run when finished.
Some programming algorithms consist of short pulses with a verification between each, when data match a couple more pulses are done to secure the data.


If this sort of protocol can be determined, it will probably be easier to see what voltage levels are used for each operation.
 

Offline ali_asadzadeh

  • Frequent Contributor
  • **
  • Posts: 655
  • Country: ir
    • ASiD Designer
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #9 on: November 05, 2018, 10:44:22 pm »
Maybe their strategy is to sell programmers :-\ :-\! :-\ Maybe they are copying the analog devices blackfin lines, selling the Dev tools and programmers so high that they would kill the product itself eventually, ask them so share the info! like rigol shard their way of hacking their scope to sell even more!!!! 
You can order parts from www.ASiDesigner.com
we are a wire-based company
 

Offline rjp

  • Regular Contributor
  • *
  • Posts: 87
  • Country: au
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #10 on: November 05, 2018, 11:38:25 pm »

There is also a Flash/EEPROM re-programmable version of the chip, the PFS154C.
 

https://lcsc.com/product-detail/Others_PADAUK-Tech-PFS154-S16_C317613.html

thats a ripoff, 11c each in small quantities!
 

Offline Whales

  • Frequent Contributor
  • **
  • Posts: 707
  • Country: au
    • Halestrom
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #11 on: November 06, 2018, 02:01:34 am »
The padauk IDE, is AFAIK, the only way to create binaries for this platform.

Does this IDE let you access the output binaries yourself?  Or are they sent to the programmer directly without giving you access?  Comparing these binaries to the data waveforms would be useful.  You could observe if data is being shift-clocked in with the need for extra cycles (or similar).

If not, then finding out how the programming protocol works is only a tiny bit of the puzzle  :-/O 
« Last Edit: November 06, 2018, 02:03:06 am by Whales »
 

Offline modrobert

  • Regular Contributor
  • *
  • Posts: 53
  • Country: th
    • your console hacking resource
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #12 on: November 06, 2018, 03:35:06 am »
Perhaps the programmer uses session encryption to the micro based on a unique serial number (read only) in the micro, to mitigate knockoffs (or "midnight batches" in approved factories) being produced.

Look for differences in initial handshake between different micros in the same batch.

 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #13 on: November 06, 2018, 03:43:28 am »
The padauk IDE, is AFAIK, the only way to create binaries for this platform.

Does this IDE let you access the output binaries yourself?  Or are they sent to the programmer directly without giving you access?  Comparing these binaries to the data waveforms would be useful.  You could observe if data is being shift-clocked in with the need for extra cycles (or similar).

If not, then finding out how the programming protocol works is only a tiny bit of the puzzle  :-/O

I guess you can use strings in the IDE, and they probably don't encrypt this, otherwise the microcontroller would be too complex. But even without strings, you can use inline assembler ("nop" etc.). Even if you don't know the encoding of the opcodes (but I guess you could look at the programming file), you could use 3 x command A, 4 x command B, and 5 x command C, and then search for a 3 x, 4 x, 5 x pattern. With this you could even reverse engineer the opcode encoding.
So Long, and Thanks for All the Fish
 

Online glarsson

  • Frequent Contributor
  • **
  • Posts: 765
  • Country: se
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #14 on: November 06, 2018, 04:55:19 am »
Perhaps the programmer uses session encryption to the micro based on a unique serial number (read only) in the micro, to mitigate knockoffs (or "midnight batches" in approved factories) being produced.
This is a 3¢ micro controller. To cheap to serialize during manufacturing.
Also, is there any economy in cloning a 3¢ part?
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #15 on: November 06, 2018, 04:56:31 am »
Hi,

I had a quick look with IDA on the IDE generating the PDK output file after compilation.

The PDK file consists of a 256 byte header containing a 32 byte initialization "key" @0x000000E0

After the header is written the compiled binary is obfuscated (the algorithm used can not be called encryption ;-) using the initialization key from header @0x000000E0 and some magic values like "12345678h" and "55AA" and a lot of 16 bit XORs. It reads 32 byte chunks from the binary and obfuscates them in 4 loops, 2 bytes a at once in 4 statements.

It will not take me long to re-create the en/decrypt for this section, just some days I guess.

Small teaser:

I used the default program for 154C and inserted:

A = 'T';
A = 'E';
A = 'S';
A = 'T';

in the FPPA0 function right after the comment "// Insert Initial Code"

The IDE creates a memory segment of the unencrypted compiled binary @0x7EA90000
The binary section was 4kByte in total initialized with static values (seems they fill up the complete memory region the MCU can hold).

This is what I found somewhere in the memory section after compilation:

542F
452F
532F
542F

(54 = T, 45 = E, 53 = S )

-> first opcode we can learn from this is (seems to be a little endian design):

MOV A,<imm>   ->  <imm> 2F


In case somebody wants to play with IDA, the function to write "encrypted" files with header is located @0x0041B0DE


JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 
The following users thanked this post: ali_asadzadeh, thm_w, olewales, drussell, TNorthover

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #16 on: November 06, 2018, 08:14:35 am »
Some more opcodes... maybe somebody recognizes them (looks like 14 bits are used per opcode, but it not seems to be a PIC)

00 00 : NOP
67 00 : PCADD A
70 00 : WDRESET
72 00 : PUSHAF
73 00 : POPAF
75 00 : RESET
76 00 : STOPSYS
77 00 : STOPEXE
78 00 : ENGINT
79 00 : DISGINT
7A 00 : RET

9[ I ] 01 : MOV PA,A //IO
D[ I ]01 : MOV A,PA //IO

[PTR]1 03 : IDXM A,PTR
[PTR]0 03 : IDXM PTR,A

[M] 0B : MOV [MEM],A
[M] 0F : MOV A,[MEM]

[M] 13 : XCH M

IM 2F : MOV A,IMM

POS 30 : GOTO POS //POS is on WORDS
POS 38 : CALL POS   //POS is on WORDS

FF 3F : ? ? ? used as filler, maybe invalid opcode

----
I defined a function on top of "Project.C and you can just write assembler inside

void fun(void)
{
  MOV A,'T'
label1:
  MOV A,'E'
  GOTO label1
  //...

  //RET is inserted automatically from miniC
}

The function is placed in compiler output memory directly at start. Just 4 bytes in front of it which looks like this:
00 00  //NOP ?
09 30 //GOTO ...

They seem to come from "Project1.PRE" from the ".JMP FPPA0" directive

----

Have fun,

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 
The following users thanked this post: ali_asadzadeh

Online FERCSA

  • Contributor
  • Posts: 26
  • Country: hu
    • www.fercsa.com
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #17 on: November 06, 2018, 10:19:22 am »
Looks like it's a FPPA, Field Programmable Processor Array.

Here is some useful links:
http://fellong.blogspot.com/2007/07/fppa_14.html
http://www.hy-star.com.tw/tech/MCU/mcu.html
Don't ask. I'm the same guy who gave you ultra fast internet in the '00s..
#FERCSA
 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #18 on: November 06, 2018, 03:26:03 pm »
The FFPA is their MCS11 chip, with 8 cores. Unfortunately I can't find it anywhere to buy. This would be a very interesting chip, similar to the Parallax Propeller, just a bit smaller, and presumably cheaper. The PMS150 has only one core.

But the more I think about it, I guess they developed it on their own and it is not a PIC clone or a clone of any other microcontroller. They couldn't have used the original die anyway, because PICs need 4 cycles and more per instruction, and the Padauk instruction set claims to need only one cycle for most instructions. And while very similar to the PIC instruction set, they have a few more instructions than PIC, especially their MCS11 flagship, like the wait instruction, which stops the CPU until an IO pin changes, which makes perfect sense for 8 cores, because it makes it easier to write fast bitbanging code for protocols like SPI in one dedicated core for the communication. But it is odd that they do such obfuscating, as if they want to hide something.

Maybe all their chips use the same die, and the other 7 cores are just disabled by software in the lower end chips? This would be a good reason for them not to publish the programming protocol :)
So Long, and Thanks for All the Fish
 

Online free_electron

  • Super Contributor
  • ***
  • Posts: 6988
  • Country: us
    • SiliconValleyGarage
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #19 on: November 07, 2018, 02:08:55 am »
This multilevel voltage programming is classic for PROM style devices.
This chip may very well be a true prom ( fuse or charge based ) and not a windowless eprom.

The reason for the multilevel voltages is to prevent accidental in-the-field corruption of the prom due to someone wiggling the pins in the wrong sequence.

They have analog comparators on the io pins used for programming ( simple window comparator made from 2 op-amps and a resistive divider. The op-amps aren't even real op-amps .. more like 4 transistors each, kind of how you make a schmitttrigger structure )

You can initialize and probably 'read' while within normal voltage on VCC. Meaning , below programming voltage. But you can't destroy anything.

Once programming voltage is applied other comparators come into play. These work between VCC and VPP (Programming voltage). One level is used for one function , another level for another function.

for example (hypothetical)
- send command to prepare for programming inside the VCC levels.
- turn on vpp
- set 6 volts on control pin : reset programming shifter
- set 7 volts : enable shifter
- now using the other pin : clock in data
- set 12 volts : burn
- set 9 volts : read back bits into shifter
- set 8 volts : turn shifter around ( the digital pin is now an output and you can read back the bits )

so these voltage all mean something : they control the on-chip programming logic.

This reminds me of the mechanism used to control trim bits in many devices. The advantage is that these voltages never will be applied int he fiedl and the entire 'programming' block is disabled.

the 'programmer' is nothing more than a simple shift register.
The fact that you pass from 5 volts VCC to 7 means you transitioned through 6 and thus caused a reset !!!

Then reverse engineering this be mindful of that.. if you see more than 1 level change : they have transitioned through a state !.

They could also use a multilevel self clocking mechanism.
 rise to 8 means  clock in a 0 . drop to 6 means clock in a 1. rising or dropping back to 7 means : advance counter a tick....

so the sequence
Code: [Select]

7878786768676867
 0 0 01 101 101
if the voltage transitions directly form 6 to 8 or 8 to 6 there is an implied '7' meaning : clock !  be weary of these things.
The on-board electronics is kept to a minimum in  area.... to make the chip cheap.

Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 
The following users thanked this post: thm_w

Online glarsson

  • Frequent Contributor
  • **
  • Posts: 765
  • Country: se
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #20 on: November 07, 2018, 02:16:47 am »
IF this device is a fusible link PROM device then it probably requires well controlled slopes on the programming pulse. Too fast rise time and the metal splashes over the silicon. Too slow damages the silicon due to localized heating or the bit will not program correctly.

Are fusible link PROMs manufactured today?
 

Offline TK

  • Frequent Contributor
  • **
  • Posts: 791
  • Country: us
  • I am a Systems Analyst who plays with Electronics
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #21 on: November 07, 2018, 02:31:03 am »
Padauk is not making any money selling the programmer, so why don't ask them for the programming protocol?  Adding support for  universal programmers like TL866 can help sell tons of 3cent microcontrollers.
 

Online PA0PBZ

  • Super Contributor
  • ***
  • Posts: 3800
  • Country: nl
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #22 on: November 07, 2018, 02:31:27 am »
It looks to me that a lot could be learned from the original programmer, like how the pins are controlled?
Keyboard error: Press F1 to continue.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 5148
  • Country: us
    • Personal site
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #23 on: November 07, 2018, 03:25:55 am »
Padauk is not making any money selling the programmer, so why don't ask them for the programming protocol?
The have been asked and they refused to provide any information.
Alex
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 1353
  • Country: fr
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #24 on: November 07, 2018, 06:11:09 am »
It's unclear to me what incentive they would have to publicly release the programming protocol though. It usually ends up being more hassle than benefits for a tech company. And here I don't think that the kind of customers interested in devising their own tools are the ones who would buy their MCUs by the millions. So...

 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 5148
  • Country: us
    • Personal site
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #25 on: November 07, 2018, 06:19:09 am »
It usually ends up being more hassle than benefits for a tech company.
Tell that to Espressif. They were hiding stuff at first too, and then they quickly realized the power of the passionate community.
Alex
 

Online drussell

  • Super Contributor
  • ***
  • Posts: 1017
  • Country: ca
  • Hardcore Geek
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #26 on: November 07, 2018, 07:31:17 am »
Adding support for  universal programmers like TL866 can help sell tons of 3cent microcontrollers.

No, it won't.  People don't one-off program things like this except in development and prototyping.  These are the kind of chip that you order by the thousands, pre-programmed with whatever code you need for your application.  99.9999% of these chips sold need to be programmed at high speed, in bulk, not one-offs in some desktop programmer, that simply makes no sense.
 

Online drussell

  • Super Contributor
  • ***
  • Posts: 1017
  • Country: ca
  • Hardcore Geek
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #27 on: November 07, 2018, 07:34:42 am »
It's unclear to me what incentive they would have to publicly release the programming protocol though. It usually ends up being more hassle than benefits for a tech company. And here I don't think that the kind of customers interested in devising their own tools are the ones who would buy their MCUs by the millions. So...

Well, the people that buy them in the millions are going to get them mass-programmed, which the manufacturer or distributor will be set up with the equipment to do for you.  If you were using millions and wanted to program them in-house for some bizarre reason, they would still help you by either supplying the equipment or the engineering data to do that but that's very different than programming one-offs in a desktop programmer.
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #28 on: November 07, 2018, 10:16:08 am »
Hi,

For those curious people I wrote a little deobfuscator for PDK files (the compiled binary you get from IDE).

It's a command line utility called depdk which requires 2 parameters: inputfile and outputfile.

Example: ./depdk input.pdk output.bin

The header from the PDK file is thrown away and just the real (deobfuscated) binary data (which is written to the MCU) is written to the output file.

Compilation with gcc -o depdk depdk.c

Or use the attached compiled executable for Windows.

Have fun,

JS  8)

depdk.c

#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main( int argc, const char * argv [] )
{
  if( 3 != argc ) {
    printf("usage: %s inputfile outputfile\n\n", argv[0]);
    return 0;
  }

  FILE* fin = fopen( argv[1], "rb");
  if( !fin ) { printf("Could not open %s for reading.\n", argv[1]); return -1; }

  FILE* fout = fopen( argv[2], "wb");
  if( !fin ) { printf("Could not open %s for writing.\n", argv[2]); return -1; }

  uint8_t hdrdata[0x100];
  if( sizeof(hdrdata) != fread( hdrdata, 1, sizeof(hdrdata), fin ) ) {
    printf("Error reading input file\n");
    return -1;
  }

  uint32_t version = *((uint32_t*)&hdrdata[0x08]);
  uint32_t datalen = *((uint32_t*)&hdrdata[0x20]);

  uint32_t extrahdr = *((uint16_t*)&hdrdata[0x26]) +
                      *((uint16_t*)&hdrdata[0x28]) +
                      *((uint16_t*)&hdrdata[0x2C]) +
                      *((uint16_t*)&hdrdata[0xD0]);
  if( version>=0x1c )
    extrahdr += *((uint8_t*)&hdrdata[0x49]);

  fseek( fin, extrahdr, SEEK_CUR );

  uint16_t key[0x10];
  memcpy( key, &hdrdata[0xE0], sizeof(key) );

  uint16_t kxorw7C92 = key[3]^key[14];
  uint16_t kxorw7E8A = key[7]^key[15];

  if( (version>=0x15) && (version<=0x17) ) {
    kxorw7C92 ^= 0x1234; kxorw7E8A ^= 0x5678;
  }

  uint16_t keyindex = 0;

  for( uint32_t fullpos=0; fullpos<datalen; fullpos+=32 ) {
    uint16_t data[0x20];
    if( sizeof(data) != fread( data, 1, sizeof(data), fin ) )
      break;

    uint32_t dataptr = 0;
    for( uint32_t j=0; j<4; j++ ) {
      uint16_t tmp_xor_key1;
      uint16_t tmp_xor_key2;

      keyindex += kxorw7C92;
      tmp_xor_key1 = data[dataptr];
      data[dataptr] += key[keyindex&0xF];
      dataptr++;
      key[fullpos&0xF] ^= tmp_xor_key1;

      keyindex += tmp_xor_key1;
      tmp_xor_key2 = data[dataptr];
      data[dataptr] = (data[dataptr] + kxorw7E8A ) ^ key[keyindex&0xF];
      dataptr++;
      key[kxorw7E8A&0xF] ^= kxorw7C92;

      keyindex ^= tmp_xor_key2;
      kxorw7C92 = data[dataptr];
      data[dataptr] += key[keyindex&0xF];
      dataptr++;
      key[kxorw7E8A&0xF] ^= 0x55AA;

      keyindex = (keyindex + kxorw7C92)>>1;
      kxorw7E8A = data[dataptr];
      data[dataptr] = (data[dataptr] - tmp_xor_key1) ^ key[keyindex&0xF];
      dataptr++;

      keyindex += kxorw7E8A;
      tmp_xor_key1 = data[dataptr];
      data[dataptr] ^= key[keyindex&0xF];
      dataptr++;
      key[kxorw7C92&0xF] += kxorw7E8A;

      keyindex ^= tmp_xor_key1;
      tmp_xor_key2 = data[dataptr];
      data[dataptr] = (data[dataptr] ^ kxorw7E8A) ^ key[keyindex&0xF];
      dataptr++;
      key[tmp_xor_key2&0xF] ^= tmp_xor_key1;

      keyindex ^= tmp_xor_key2;
      kxorw7C92 = data[dataptr];
      data[dataptr] += key[keyindex&0xF];
      dataptr++;
      key[tmp_xor_key1&0xF] += tmp_xor_key2;

      keyindex += kxorw7C92;
      kxorw7E8A = data[dataptr];
      data[dataptr] = (data[dataptr] + tmp_xor_key1) ^ key[keyindex&0xF];
      dataptr++;

      key[2] ^= tmp_xor_key1;
      key[4] += tmp_xor_key2;
      key[6] += kxorw7E8A;
      key[8] -= kxorw7C92;
      key[1] ^= key[15];
      key[3] ^= key[14];
      key[5] ^= key[13];
      keyindex += j;
    }

    if( sizeof(data) != fwrite( data, 1, sizeof(data), fout ) ) {
      printf("Error writing output file\n");
      return -1;
    }
  }

  fclose(fin);
  fclose(fout);

  return 0;
}

« Last Edit: November 17, 2018, 10:10:28 am by js_12345678_55AA »
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 
The following users thanked this post: oPossum, chicken, thm_w, drussell, TNorthover

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #29 on: November 07, 2018, 10:53:47 am »
Just some useful info for understanding the MCU family and how to program it:

http://svn2.assembla.com/svn/mcu/

The examples using older processor types with 8 cores but most of it should be "understandbale"

JS
« Last Edit: November 07, 2018, 10:56:21 am by js_12345678_55AA »
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 
The following users thanked this post: iak

Offline SeoulBigChris

  • Contributor
  • Posts: 25
  • Country: kr
  • "Unencumbered by the thought process"
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #30 on: November 07, 2018, 01:27:30 pm »
It's unclear to me what incentive they would have to publicly release the programming protocol though. It usually ends up being more hassle than benefits for a tech company. And here I don't think that the kind of customers interested in devising their own tools are the ones who would buy their MCUs by the millions. So...

Disclaimer: I’ve never run a semiconductor company.

My reaction is the opposite, when I see policies like this. As far as I know, Paduk is in the business of selling semiconductors, not programmers. I contend that it’s more hassle to maintain a closed programming protocol. This forces you into the chip programmer business, taking your attention away from your core competency. Releasing the protocol so the various chip programmer companies and hobbyists can support your ICs should reduce their hassle, not increase it.

I have a similar take on providing a custom and apparently closed compiler. Do they have aspirations of becoming a compiler company as well?

I suppose it’s possible that the insides of their chips are so revolutionary and proprietary, that opening up these protocols would be akin to revealing their trade secrets. But I think that’s unlikely in this case.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 5148
  • Country: us
    • Personal site
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #31 on: November 07, 2018, 01:31:45 pm »
With western companies there is a pretty benign explanation for why they don't release even the most trivial things - releasing something implies you will provide support. For whatever reason a concept of releasing things "as is" is not accepted.

But I doubt this is a problem for Padauk. Chinese companies have a habit of releasing a product and not providing any obvious support to the general public. And I like it - it lets us have products that we otherwise would not see, even if they are not well documented.
Alex
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 1353
  • Country: fr
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #32 on: November 07, 2018, 02:19:29 pm »
With western companies there is a pretty benign explanation for why they don't release even the most trivial things - releasing something implies you will provide support. For whatever reason a concept of releasing things "as is" is not accepted.

Yes, thus my "more hassle than benefits" point above.
Even if it's made clear you won't provide direct support, you're bound to one way or another. You will inevitably run into customers that will ask for tech support and make you waste significant time until they end up admitting they use unsupported tools.

But I doubt this is a problem for Padauk. Chinese companies have a habit of releasing a product and not providing any obvious support to the general public. And I like it - it lets us have products that we otherwise would not see, even if they are not well documented.

Possibly, but again why would they? That would still take some time to gather the bits and pieces in a consumable form for third parties, and possibly bother with uploading updates on a regular basis, etc. They may not even have a proper internal documentation themselves (that would be bad, but yes, that really happens!)

And I doubt they are interested in customers that will buy for a few bucks of their ICs.  ;D I also doubt that, maybe contrary to Espressif that have different products and targets, a large community of small companies or even amateur users would really help their business.
 :-//
 

Online Bud

  • Super Contributor
  • ***
  • Posts: 2913
  • Country: ca
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #33 on: November 07, 2018, 05:02:35 pm »
The video was painful to watch. Too many cuts.
 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #34 on: November 11, 2018, 05:21:36 pm »
I contacted Padauk, will get a programmer and an ICE (unfortunately you need a different ICE than the one you can use for the PMS150C) for their new PMC884 chip with 8 cores and samples of the chip. Joe from Padauk sent me a datasheet for it. It is a bit strange why they don't publish it on their webpage: He says because it can be too difficult to program, maybe they don't want too many support requests. Anyway, he says the datasheet is not confidential and I'm allowed to show it to others for review:

http://www.frank-buss.de/tmp/pmc884.pdf

It is not really a multi-core chip, more like a mult-thread chip, because e.g. if you enable 2 cores and run it at 8 MHz, each core will run effectively at 4 MHz, round-robin. But still very useful for things like bitbanging on one core and application logic on another core, without the overhead of interrupts or complicated programming.
So Long, and Thanks for All the Fish
 

Offline Hypernova

  • Supporter
  • ****
  • Posts: 654
  • Country: tw
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #35 on: November 12, 2018, 01:47:50 am »
he says the datasheet is not confidential and I'm allowed to show it to others for review

Funny as the red watermark on every page reads "PADAUK confidential document"
 

Offline Sjaak

  • Contributor
  • Posts: 8
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #36 on: November 12, 2018, 03:52:55 am »
How about disassembling the programmer? Not expecting a regular mcu in there that can be read back but can give some clues howmany voltage levels there are, and even some silkscreen markings that provide info about signalnames.
 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #37 on: November 12, 2018, 04:40:10 pm »
Funny as the red watermark on every page reads "PADAUK confidential document"

Maybe it was confidential at some point, but it really doesn't make sense to hide it. This hardware thread concept looks very useful to simplify application development, without much drawbacks for power consumption or issues with real parallel cores, like synchronization and race conditions etc.
So Long, and Thanks for All the Fish
 

Offline Hypernova

  • Supporter
  • ****
  • Posts: 654
  • Country: tw
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #38 on: November 13, 2018, 01:44:36 am »
Funny as the red watermark on every page reads "PADAUK confidential document"

Maybe it was confidential at some point, but it really doesn't make sense to hide it. This hardware thread concept looks very useful to simplify application development, without much drawbacks for power consumption or issues with real parallel cores, like synchronization and race conditions etc.

What they made is a Barrel Processor which is a pretty old concept, so not sure what they have to hide. I have a real dislike for companies that take the confidential-by-default route.
 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #39 on: November 13, 2018, 07:15:50 am »
This is interesting, I didn't know the barrel processor concept.

The datasheet for the PMC884 says at one position it is patent pending, and at another position it is patented. I couldn't find an existing patent, only this:

https://patents.google.com/patent/US20050166170

Has the same name (FPPA), but looks like something completely different. But with the barrel processor I wonder if this counts as prior art and they can't patent it.

Meanwhile Joe told me the price for the PMC884: it is US$0.40 in larger quantities (but less than 100k). Don't know if this makes sense, because you could get 13 of the cheap 3 cent PMS150C for this price :) But might be still useful if you need it small in one IC.
So Long, and Thanks for All the Fish
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #40 on: November 15, 2018, 02:34:33 am »
I found some strings in "USB_Driver" folder inside of "Writer.PDK" (can be deobfuscated with small modified depdk).

Looks like the programmer uses 5V, 7.5V for VDD and 8V, 12V for VP (programing)

<<<  IC O.K. >>>
F/W Ver : 1.23 
DC Power Fail. 
DC Low Power.   
DC High Power. 
H/W VDD keep Hi.
H/W VD 5V fail.
H/W VDD 7V5 fail
H/W VDD 5V fail.
H/W VP 8V fail.
H/W VP 12V fail.


Maybe this helps interpreting the captured data.
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline atc1441

  • Newbie
  • Posts: 1
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #41 on: November 15, 2018, 05:36:19 am »
Hi, i think i found one Padauk chip in the wild.

It is in one of these STC Auto Programmer USB-TTL but i am not 100% shure eBay auction: #202070246074


As you see in the attachment the pinout is the same it is the tsop8 chip the other one is an CH340 Clone
« Last Edit: November 15, 2018, 06:27:09 am by atc1441 »
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #42 on: November 17, 2018, 03:41:58 am »
Hi, I spent some time (actually a lot more than I wanted) to find out and write down all known instructions for the small type (1 core) processors (1 core processors start with a "1" like PMC154. PMC2... has 2 cores and PDK8... has 8 cores ).

The 1 core processors (the cheap ones ;-) ) do have a compact (14-bit) instruction set. The multi core processors seem to have a 16-bit instruction set.
Note: 14/16 bit instructions does not mean it is a 14/16 bit processor. They are all tiny 8 bit processors. Just the length of one instruction is 14/16 bit.

Here is a direct link:

https://free-pdk.github.io/PADAUK_FPPA_14_bit_instruction_set.html  :) :) :)


I also created a github project. Everybody is invited to contribute:

https://github.com/free-pdk

It just started with a single "documentation" repository. Next might be a disassembler and a simulator.


Have fun,

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 
The following users thanked this post: oPossum, chicken

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #43 on: November 17, 2018, 03:55:58 am »
That's really nice, you can add me if you like, my github name: FrankBuss
I could try to implement a FPGA emulation for it. This would allow realtime simulation in hardware (except for the ADCs) of the chip with all peripherals.
So Long, and Thanks for All the Fish
 

Online rhodges

  • Contributor
  • Posts: 48
  • Country: us
  • Available for embedded projects.
    • My STM8 libraries
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #44 on: November 17, 2018, 04:00:15 am »
Quote
Here is a direct link:
https://free-pdk.github.io/PADAUK_FPPA_14_bit_instruction_set.html  :) :) :)
Nice work! It looks like you might have all the important instructions decoded. Maybe it would be useful to have a program to parse the compiler output every time and alert if a "new" instruction comes out. After a while, we could be pretty confident about the instruction coding.

Thanks! I recently decided to move from PIC to STM8 for personal projects, but you are tempting me to rotate my brain 90 degrees to go back to PIC thinking...
Currently developing STM8. Past includes 6809, Z80, 8086, PIC, MIPS, PNX1302, and some 8748 and 6805.
 

Offline chicken

  • Regular Contributor
  • *
  • Posts: 216
  • Country: us
  • Rusty Coder
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #45 on: November 17, 2018, 04:10:34 am »
I'm tempted to add support for this architecture to radare2. https://github.com/radare/radare2
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #46 on: November 17, 2018, 04:27:17 am »
It looks like you might have all the important instructions decoded. Maybe it would be useful to have a program to parse the compiler output every time and alert if a "new" instruction comes out. After a while, we could be pretty confident about the instruction coding.

Actually I used the data sheets of all PMC/PMS1xx processors and typed in every possible instruction in the IDE and monitored the compiler output. So for sure the compiler will not generate more / unknown instructions from our code.

The holes are most likely unused spaces or instructions which they planned to implement but did not work out correctly. For instance AND IO,A / AND A,IO / OR IA,A / OR A,IO  are somehow missing and would fit perfectly in the "0x0100...0x017F" hole.

One way to try the "undocumented" instructions is to manually create the binary, inject these instructions and observe the result (like it was done decades ago for 6502).
Since OTP would be a bit painful for this I already ordered the FLASH based PFS154 (now waiting for it to arrive).

On the other hand, if the normal compiler does not create them, also a disassembler does not need to know them. Invalid instructions are a common thing which even exist on modern CPUs like ARM and Intel.
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #47 on: November 17, 2018, 04:49:38 am »
Hi thank you for your work thus far.

@ js_12345678_55AA: Could you post the modifications you made to deobfuscate the PDKs in the USB_Driver directory?

Also: in the USB_Driver/USB directory there seems to be the firmware for the programmer (in obfuscated form):

P5SP_BOOT_UPDATER.fw
P5SP_G1.fw
P5SP_G2.fw
P5SP_TESTER.fw

from Dave's video the P5SP files could be for an STM32F072V8T6
and from the strings in the FPPA_IDE.EXE it seems to know how to upload them to the programmer
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #48 on: November 17, 2018, 07:22:00 am »
From the strings in FPPA_IDE.exe you can also gather voltage information from their test program of the programmer (P5SP_tester.fw):

0x63421c 70 69 Please remove all IC, and check VDD,\nVPP(PA5), PA0 / 3 / 4 / 7 is 0 V
0x634264 30 29 Please check VPP (PA5) = 4.6V
0x634284 31 30 Please check VPP (PA5) = 11.3V
0x6342a4 24 23 Please check VDD = 5.5V
0x6342bc 24 23 Please check VDD = 7.5V
0x6342d4 24 23 Please check VDD = 3.3V

and a list of instructions:

0x62dac0 16 15 MOV__A__IO_LIST
0x62dad0 16 15 MOV__IO_LIST__A
0x62dae0 16 15 XOR__A__IO_LIST
0x62daf0 16 15 XOR__IO_LIST__A
0x62db00 14 13 MOV__A__CONST
0x62db10 17 16 MOV__A__RAM_BYTE
0x62db24 17 16 MOV__RAM_BYTE__A
0x62db38 18 17 NMOV__A__RAM_BYTE
0x62db4c 18 17 NMOV__RAM_BYTE__A
0x62db60 18 17 IDXM__A__RAM_WORD
0x62db74 18 17 IDXM__RAM_WORD__A
0x62db88 17 16 LDTABL__RAM_WORD
0x62db9c 17 16 LDTABH__RAM_WORD
0x62dbb0 16 15 PUSHW__RAM_WORD
0x62dbc0 15 14 POPW__RAM_WORD
0x62dbd0 11 10 PUSHW__PCX
0x62dbdc 10 9 POPW__PCX
0x62dbe8 7 6 PUSHAF
0x62dbf0 6 5 POPAF
0x62dbf8 17 16 AND__A__RAM_BYTE
0x62dc0c 17 16 AND__RAM_BYTE__A
0x62dc20 14 13 AND__A__CONST
0x62dc30 16 15 OR__A__RAM_BYTE
0x62dc40 16 15 OR__RAM_BYTE__A
0x62dc50 13 12 OR__A__CONST
0x62dc60 17 16 XOR__A__RAM_BYTE
0x62dc74 17 16 XOR__RAM_BYTE__A
0x62dc88 14 13 XOR__A__CONST
0x62dc98 7 6 NOT__A
0x62dca0 14 13 NOT__RAM_BYTE
0x62dcb0 8 7 NEGC__A
0x62dcb8 7 6 NEG__A
0x62dcc0 15 14 NEGC__RAM_BYTE
0x62dcd0 14 13 NEG__RAM_BYTE
0x62dce0 16 15 CLEAR__RAM_BYTE
0x62dcf0 14 13 XCH__RAM_BYTE
0x62dd00 8 7 SWAP__A
0x62dd08 15 14 SWAP__RAM_BYTE
0x62dd18 6 5 SR__A
0x62dd20 13 12 SR__RAM_BYTE
0x62dd30 6 5 SL__A
0x62dd38 13 12 SL__RAM_BYTE
0x62dd48 7 6 SRC__A
0x62dd50 14 13 SRC__RAM_BYTE
0x62dd60 7 6 SLC__A
0x62dd68 14 13 SLC__RAM_BYTE
0x62dd78 18 17 NADD__A__RAM_BYTE
0x62dd8c 18 17 NADD__RAM_BYTE__A
0x62dda0 8 7 ADDC__A
0x62dda8 15 14 ADDC__RAM_BYTE
0x62ddb8 18 17 ADDC__A__RAM_BYTE
0x62ddcc 18 17 ADDC__RAM_BYTE__A
0x62dde0 8 7 SUBC__A
0x62dde8 15 14 SUBC__RAM_BYTE
0x62ddf8 18 17 SUBC__A__RAM_BYTE
0x62de0c 18 17 SUBC__RAM_BYTE__A
0x62de20 17 16 ADD__A__RAM_BYTE
0x62de34 17 16 ADD__RAM_BYTE__A
0x62de48 14 13 ADD__A__CONST
0x62de58 17 16 SUB__A__RAM_BYTE
0x62de6c 17 16 SUB__RAM_BYTE__A
0x62de80 14 13 SUB__A__CONST
0x62de90 14 13 INC__RAM_BYTE
0x62dea0 14 13 DEC__RAM_BYTE
0x62deb0 15 14 IZSN__RAM_BYTE
0x62dec0 8 7 IZSN__A
0x62dec8 15 14 DZSN__RAM_BYTE
0x62ded8 8 7 DZSN__A
0x62dee0 15 14 COMP__A__CONST
0x62def0 18 17 COMP__A__RAM_BYTE
0x62df04 18 17 COMP__RAM_BYTE__A
0x62df18 13 12 DELAY__CONST
0x62df28 16 15 DELAY__RAM_BYTE
0x62df38 9 8 DELAY__A
0x62df44 9 8 T0SN__CF
0x62df50 9 8 T1SN__CF
0x62df5c 9 8 T0SN__ZF
0x62df68 9 8 T1SN__ZF
0x62df74 9 8 SET0__CF
0x62df80 9 8 SET1__CF
0x62df8c 9 8 SET0__ZF
0x62df98 9 8 SET1__ZF
0x62dfa4 8 7 TOG__ZF
0x62dfac 8 7 TOG__CF
0x62dfb4 17 16 T0SN__IOBIT_LIST
0x62dfc8 17 16 T1SN__IOBIT_LIST
0x62dfdc 17 16 SET0__IOBIT_LIST
0x62dff0 17 16 SET1__IOBIT_LIST
0x62e004 16 15 TOG__IOBIT_LIST
0x62e014 18 17 SWAPC__IOBIT_LIST
0x62e028 18 17 WAIT0__IOBIT_LIST
0x62e03c 18 17 WAIT1__IOBIT_LIST
0x62e050 14 13 T0SN__RAM_BIT
0x62e060 14 13 T1SN__RAM_BIT
0x62e070 14 13 SET0__RAM_BIT
0x62e080 14 13 SET1__RAM_BIT
0x62e090 19 18 CEQSN__A__RAM_BYTE
0x62e0a4 16 15 CEQSN__A__CONST
0x62e0b4 20 19 CNEQSN__A__RAM_BYTE
0x62e0c8 17 16 CNEQSN__A__CONST
0x62e0dc 14 13 GOTO__ADR_ABS
0x62e0ec 14 13 GOTO__ADR_OFS
0x62e0fc 16 15 IGOTO__RAM_WORD
0x62e10c 14 13 CALL__ADR_ABS
0x62e11c 14 13 CALL__ADR_OFS
0x62e12c 16 15 ICALL__RAM_WORD
0x62e13c 15 14 LGOTO__ADR_ABS
0x62e14c 15 14 LCALL__ADR_ABS
0x62e160 5 4 RETI
0x62e168 11 10 RET__CONST
0x62e174 14 13 PMODE__P_MODE
0x62e184 8 7 STOPSYS
0x62e18c 8 7 STOPEXE
0x62e194 16 15 LDT16__RAM_WORD
0x62e1a4 16 15 STT16__RAM_WORD
0x62e1b4 7 6 ENGINT
0x62e1bc 8 7 DISGINT
0x62e1c4 8 7 WDRESET
0x62e1cc 6 5 RESET
0x62e1dc 9 8 PCADD__A

There are also quite a few compiler directives, but they are all over the place
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #49 on: November 17, 2018, 08:20:47 am »
The instruction list above seems to be a generic one, describing all theoretically available instructions.
The actually available instructions for a specific chip are given by the specific inc file in the INC_PDK directory and the symbol file (defined in the inc file and located in the Symbol directory)
(There is a lot of additional data in that file, maybe they also define what address modes can be used and which instruction can also use flags or io's as operands etc.)

example:
PMS150C (44 Instructions)
INSTRUCTION
CALL
GOTO
ADD
SUB
CEQSN
AND
OR
XOR
MOV
T0SN
T1SN
SET0
SET1
ADDC
SUBC
IZSN
DZSN
INC
DEC
CLEAR
XCH
NOT
NEG
SRC
SLC
RET
IDXM
STT16
LDT16
WDRESET
PUSHAF
POPAF
RESET
STOPSYS
STOPEXE
ENGINT
DISGINT
RETI
PCADD
SWAP
TRAP
NOP
LDSPTL
LDSPTH

PFS154 (52 Instructions)
INSTRUCTION
CALL
GOTO
ADD
SUB
CEQSN
CNEQSN
AND
OR
XOR
MOV
T0SN
T1SN
SET0
SET1
ADDC
SUBC
IZSN
DZSN
INC
DEC
CLEAR
XCH
NOT
NEG
SRC
SLC
NADD
COMP
SWAP
STT16
LDT16
IDXM
RET
LDTABL
LDTABH
WDRESET
PUSHAF
POPAF
RESET
STOPSYS
STOPEXE
ENGINT
DISGINT
RETI
MUL
NEGC
PCADD
SWAP
TRAP
NOP
LDSPTL
LDSPTH
« Last Edit: November 17, 2018, 08:34:01 am by DocBen »
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #50 on: November 17, 2018, 10:01:10 am »
Found 2 more instructions which are not in manual:

LDSPTL   0x0006
LDSPTH  0x0007

They are fixed instructions with no arguments.

Speculation...
Looks like it is a syntax which uses L and H 
Since the stack pointer is mapped on IO 0x02 and does not have High or Low, the "SP" inside the name might me misleading

----
There are 2 more undocumented instructions which the IDE knows but refuses to compile. I tried many many different 1xx processors:

WORD data
...

LDTABL  data
LDTABH  data

Compiler always says: "The 'LDTABx' not be supported at PFS154" (for every 1xx processor I tried)

All other instructions from the list are already mapped.

One special exception is the "TRAP" instruction. The IDE just put's a "NOP" inside the binary. I assume this is used for the ICE only... so need to wait for my ICE to arrive ;D
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #51 on: November 17, 2018, 10:12:27 am »
@ js_12345678_55AA: Could you post the modifications you made to deobfuscate the PDKs in the USB_Driver directory?

I updated the initial post (both source and windows binary)
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #52 on: November 17, 2018, 07:58:02 pm »
Speaking of ICE
The USB_Driver/USB directory also seems to contain the firmware for the ICE (*.usb and *.hid files)
As far as I can tell this should be firmware for an Cypress EZ-USB FX2LP Chip CY7C68013A (8051 code) it is not obfuscated.

I assume that the ICE*PDK files are for GAL/PAL/FPGA device seen in the video of the ICE. (Cypress even markets the chip as an FPGA companion "Booting an FPGA from FX2LP" so probably an FPGA.

AN63620 - Configuring a Xilinx Spartan-3E FPGA Over USB Using EZ-USB FX2LP™:
"This  application  note  demonstrates  a  technique  for  dynamically  configuring  a  Xilinx  Spartan-3E  Field  Programmable  Gate Array  (FPGA)  over  USB  using  EZ-USB  FX2LP,  a  high-speed  USB  peripheral  controller.  After  the  FPGA  is  configured, FX2LP  can  act  as  a  high-speed  data  path  between  the  USB  host  and  the  FPGA.  This  capability of  FX2LP  enhances 
FPGA-based USB applications such as logical analyzers, oscilloscopes, image processing,
and high-speed data acquisition."

They are all wildly different from each other, which would make sense if they all are for differnt cores.
The file sizes are however all divisible by 64 -> Logic cells/blocks?




ICE_3.usb and WRITER_5.usb on the other hand are almost identical, so I assume thats for the same thing (as far as I understand thats the multicore ICE)

ICE5.fw would then be the obfuscated single core firmware for the ICE that Dave has. It seems that they still use a Cypress FX2 chip, so probably almost identical to ICE_3.usb.
Maybe that helps with deobfuscation.
« Last Edit: November 17, 2018, 08:42:47 pm by DocBen »
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #53 on: November 17, 2018, 09:55:58 pm »

@ js_12345678_55AA:

Also: in the USB_Driver/USB directory there seems to be the firmware for the programmer (in obfuscated form):

P5SP_BOOT_UPDATER.fw
P5SP_G1.fw
P5SP_G2.fw
P5SP_TESTER.fw

from Dave's video the P5SP files could be for an STM32F072V8T6

You asked for it... here it is:

It's a command line utility called defw which requires 2 parameters: inputfile and outputfile.

Example: ./defw input.fw output.bin

Compilation with gcc -o defw defw.c

Or use the attached compiled executable for Windows.

Have fun,

JS  8)

P.S. works for all *.fw files and also the *.hid files in "USB_Driver/USB" directory. All other files (*.usb) there seem not to be obfuscated. For the PDK files use "depdk".

defw.c


#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main( int argc, const char * argv [] )
{
  if( 3 != argc ) {
    printf("usage: %s inputfile outputfile\n\n", argv[0]);
    return 0;
  }

  FILE* fin = fopen( argv[1], "rb");
  if( !fin ) { printf("Could not open %s for reading.\n", argv[1]); return -1; }

  FILE* fout = fopen( argv[2], "wb");
  if( !fin ) { printf("Could not open %s for writing.\n", argv[2]); return -1; }
 
  uint16_t data[0x10000];
  int lenwords = fread( data, sizeof(uint16_t), sizeof(data)/sizeof(uint16_t), fin );
  if( lenwords<=0 ) {
     printf("Could not read %s.\n", argv[1]); return -1;
  }

  for( uint32_t i=0; i<lenwords; i++ ) {
    data[ i ] ^= i;
    if( i & 1 ) data[ i ] ^= 0x55;
    else
    if( i & 2 ) data[ i ] ^= 0xAA23;
    else
    if( i & 4 ) data[ i ] ^= 0x3759;
    else
      data[ i ] ^= 0xAFCD;
    data[ i ] ^= (lenwords-i-1)<<3;
  }
   
  if( lenwords != fwrite( data, sizeof(uint16_t), lenwords, fout ) ) {
    printf("Error writing output file\n");
    return -1;
  }

  fclose(fin);
  fclose(fout);

  return 0;
}



... it is indeed STM32 firmware in there :-)


Edit: fixed forum formatting of data[ i ]
« Last Edit: November 17, 2018, 10:42:29 pm by js_12345678_55AA »
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #54 on: November 17, 2018, 10:07:18 pm »
Hi,

seems youtuber "bigclivedotcom" spotted a PADAUK MCU containing device in the wild:



 :)
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #55 on: November 17, 2018, 10:24:16 pm »
Hey thanks!

Whats interesting is that there is a "simple emulator" that isnt available anywhere:
5S-I-S0 2B

http://www.padauk.com.tw//upload/ICEmanual/5S-ICE_UM_EN_V002_20181105.pdf (page 15)

But: there is an dev board with Cypress FX2 Chip
https://de.aliexpress.com/wholesale?catId=0&SearchText=EZ-USB+FX2LP+CY7C68013A
for ~3.5 USD

If we can find out what FPGA they use  :popcorn:
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #56 on: November 17, 2018, 10:29:38 pm »
small error:
data ^= ...
should read
 data square brackets i ^= ... (Forum doesnt let me post square brackets  :-//)
fixed locally and seems to work
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #57 on: November 17, 2018, 10:40:55 pm »
and more voltages appear:
T:CN5/CN6
VPP_PWR != 11V
T:CN7
T:CN12/CN6/CN5
VPP_PWR != 0V
VDD_PWR != 7.8V
T:CN11
T:CN11/CN4/CN3
VDD_PWR != 0V
HVPP_IC != 11V
T:IC_PA5
T:Q32
VPP_IC != 0V
VDD_IC != 7.8V
T:IC_VDD
T:Q9
VDD_IC != 0V
`pGp
d!/H
VDD_PWR != 3V
 T:CN11
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #58 on: November 17, 2018, 11:28:03 pm »

seems youtuber "bigclivedotcom" spotted a PADAUK MCU containing device in the wild:


Too bad he doesnt desolder the chip to show the bottom so we can see the package markings.

Just FYI package markings on the chips I have:
PMS150C: YS17 RBAAADO 1839XA0
PMC232-S16A: FS20 FC62450 1737YAD
PFS154-S16: YP56 R2E9691 1609XBD
Bj8P509FNB (supposedly clone of elan 13-bit clone of microchip 12c509): BJY180338
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #59 on: November 18, 2018, 01:34:14 am »
I was thinking about creating a library (may be called "libpdk") which contains all the code one may need to create tools for these MCUs. The lib would contain stuff like the PDK decryption/encryption code, the instruction list with their opcode encoding/decoding rules, etc... then all the tools like disassembler, assembler, emulator, etc... can link to the same library. This would let us have only one codebase where the "important stuff" is so if we need to make changes and adjustments (like adding new instrs etc) we wouldn't have to change every single other tool. I'm starting to layout the instruction list in C++ in a way that can be used both to assemble, disassemble or emulate stuff. Is there a place for people interested in helping with the code to chat with the others so we somehow coordinate the work? Like a Slack or Discord channel or something
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #60 on: November 18, 2018, 02:00:49 am »
IMHO it would be more useful to add the padauk controllers to already existing toolchains like radare
similarly to 8051 or 6502 or pic that are already there:

https://github.com/radare/radare2/tree/master/libr/asm/arch/8051
https://github.com/radare/radare2/tree/master/libr/asm/arch/6502
https://github.com/radare/radare2/tree/master/libr/asm/arch/avr
https://github.com/radare/radare2/tree/master/libr/asm/arch/pic

You can also add file formats like this:
https://github.com/radare/radare2/blob/master/libr/io/p/io_ihex.c

I think it would save you and others a lot of work, because most of the underlying work has already been done and tested.
Also radare has already got quite a few tools build in for analysis, disassembling and low level debugging as you can see here:

https://www.megabeets.net/reverse-engineering-a-gameboy-rom-with-radare2/

For compiling it might be interesting to add this architecture to sdcc.
« Last Edit: November 18, 2018, 03:07:42 am by DocBen »
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #61 on: November 18, 2018, 03:16:35 am »
Too bad he doesnt desolder the chip to show the bottom so we can see the package markings.

You asked for it...  :)

Just stopped at ALDI and saw them having a similar LED Christmas lights offering for 2.99 EUR.

I bought and opened it (without powering it on, because "Don't turn it on, take it apart!" 8) ) ...

... and yes, PCB and MCU looks same as from bigclivedotcom's video.

But to my surprise it is having a 32kHz crystal so it can do much better than the more cost optimized version bigclivedotcom was testing.

Last picture shows the MCU from back side. I'm pretty sure it is a PMC154 (just the cheapest and the pinout for GND, VDD, crystal also matches).


JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 
The following users thanked this post: thm_w, DocBen, rhodges

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • Posts: 1370
  • Country: pl
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #62 on: November 18, 2018, 03:17:17 am »
(Forum doesnt let me post square brackets  :-//)

Look here: https://wiki.simplemachines.org/smf/Alphabetical_list_of_all_bulletin_board_codes

The ones that might work for that are pre or nobbc, me thinks.
 
The following users thanked this post: DocBen

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #63 on: November 18, 2018, 03:35:59 am »

Last picture shows the MCU from back side. I'm pretty sure it is a PMC154 (just the cheapest and the pinout for GND, VDD, crystal also matches).


I dont think so. The chips I have have 3 lines of markings. This just has the one.
No Bojuxing Industry BJ8P509FNB either because thats more laser carved and the chip marking you have seems inkjetted.

All these chips are probably very interchangable anyhow. Or they just rewrite the code, after all these are throw away products

Maybe ALDI has the premium version for germans  :-DD thus the crystal for milisecond switching precision
(seriously the cheapest crystal I could find on lcsc costs more than the pms150c  :scared: utter madness)
« Last Edit: November 18, 2018, 03:59:31 am by DocBen »
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #64 on: November 18, 2018, 09:17:42 am »
This isnt complete but its a start.
If you would like to extend this, youre welcome
Its based on
https://github.com/limkokhole/radare2/wiki/Implementing-a-new-architecture
and by no means any good, but I think its not too hard to get it usable.

create a directory. put the two files in it. install radare2 if you havent already.
make
sudo make install

I also had to
cp /usr/lib/radare2/last/* ~/.config/radare2/plugins
otherwise the plugin isnt recognized

rasm2 -L should list it at the end
and then you can
rasm2 -a PADAUK -d 0x0069
to get:  neg a

padauk.c

Code: [Select]
/* Padauk disassembler plugin for radare */

#include <r_asm.h>
#include <r_lib.h>
#include <string.h>

static struct {
ut8 op1;
ut8 op2;
char *name;
} ops[] = {
{0x00, 0x00, "nopi"},
{0x00, 0x60, "addc a"},
{0x00, 0x61, "subc a"},
{0x00, 0x62, "izsn a"},
{0x00, 0x63, "dzsn a"},
{0x00, 0x64, "?"},
{0x00, 0x65, "?"},
{0x00, 0x66, "?"},
{0x00, 0x67, "pcadd a"},
{0x00, 0x68, "not a"},
{0x00, 0x69, "neg a"},
{0x00, 0x6a, "sr a"},
{0x00, 0x6b, "sl a"},
{0x00, 0x6c, "src a"},
{0x00, 0x6d, "slc a"},
{0x00, 0x6e, "swap a"},
{0x00, 0x6f, "?"},
{0x3f, 0xff, NULL}};

static int _PADAUKDisass (RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
int i;
op->size = 2;
for (i=0; ops[i].name != NULL; i++) {
if (ops[i].op1 == buf[0]) {
if (ops[i].op2 == buf[1]) {
sprintf (op->buf_asm, "%s", ops[i].name);
break;
}
}
}
return op->size;
}

RAsmPlugin r_asm_plugin_padauk = {
        .name = "PADAUK",
        .arch = "PADAUK",
        .license = "LGPL3",
        .bits = 16,
        .desc = "Padauk disassembler",
        .disassemble = &_PADAUKDisass,
};

#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
        .type = R_LIB_TYPE_ASM,
        .data = &r_asm_plugin_padauk
};
#endif

Makefile

Code: [Select]
NAME=padauk
R2_PLUGIN_PATH=$(shell r2 -hh|grep LIBR_PLUGINS|awk '{print $$2}')
CFLAGS=-g -fPIC $(shell pkg-config --cflags r_asm)
LDFLAGS=-shared $(shell pkg-config --libs r_asm)
OBJS=$(NAME).o
SO_EXT=$(shell uname|grep -q Darwin && echo dylib || echo so)
LIB=$(NAME).$(SO_EXT)

all: $(LIB)

clean:
rm -f $(LIB) $(OBJS)

$(LIB): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(LIB)

install:
cp -f $(NAME).$(SO_EXT) $(R2_PLUGIN_PATH)

uninstall:
rm -f $(R2_PLUGIN_PATH)/$(NAME).$(SO_EXT)
« Last Edit: November 18, 2018, 09:31:22 am by DocBen »
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #65 on: November 18, 2018, 11:27:02 pm »
This is a slightly improved version tested with radare 3.1 git.
The documentation for radare is shall we say "sparse" and every backend seems to have multiple layers of indirection and slightly different ways of going about it, especially for the assembler.
But once you found a way it works quite nicely. This is also not very complete and thus minimalistic because I dont know what the best way to de/encode the instructions is.
The table approach has the advantage of being inversible i.e the dissassembler is the inverse of the assembler, but its quite pointless to do it in this manor for instructions that take addresses etc.

Use the makefile from above.
make && sudo make install
and then you can do
rasm2 -a padauk -d 0x0073
to get "popaf" or
rasm2 -a padauk 'addc a'
to get "0x0060"
and you also get stuff like this
rasm2 -a padauk 'nop; ret; reti; addc a; sr a;'
rasm2 -a padauk -d 0x0000006000720073
for free

padauk.c
Code: [Select]
/* Padauk (dis)assembler plugin for radare 3.1 git - DocBen 2018 */

#include <r_asm.h>
#include <r_lib.h>
#include <string.h>

static struct {
ut16 op;
char *name;
} ops[] = {
{0x0000, "nop"},
{0x0060, "addc a"},
{0x0061, "subc a"},
{0x0062, "izsn a"},
{0x0063, "dzsn a"},
{0x0064, "?"},
{0x0065, "?"},
{0x0066, "?"},
{0x0067, "pcadd a"},
{0x0068, "not a"},
{0x0069, "neg a"},
{0x006c, "src a"},
{0x006d, "slc a"},
{0x006a, "sr a"},
{0x006b, "sl a"},
{0x006e, "swap a"},
{0x006f, "?"},
{0x0070, "wdreset"},
{0x0071, "?"},
{0x0072, "pushaf"},
{0x0073, "popaf"},
{0x0074, "?"},
{0x0075, "reset"},
{0x0076, "stopsys"},
{0x0077, "stopexe"},
{0x0078, "engint"},
{0x0079, "disgint"},
{0x007b, "reti"},
{0x007a, "ret"},
{0x007c, "mul"},
{0x007d, "?"},
{0x007e, "?"},
{0x007f, "?"},
{0x4000, NULL}};

int _PADAUKDisass (RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
int i;
op->size = 2;
const char *buf_asm = "unknown";
for (i=0; ops[i].name != NULL; i++) {
if (ops[i].op == 0x100 * buf[0] + buf[1]) {
buf_asm = sdb_fmt ("%s", ops[i].name);
break;
}
}
r_strbuf_set (&op->buf_asm, buf_asm);
return op->size;
}

int _PADAUKAss (RAsm *a, RAsmOp *op, const char *buf) {
int i;
op->size = 2;
ut16 opbuf = 0x4000;
const char *buf_hex = "unknown";
for (i = 0; ops[i].name != NULL; i++) {
if (!strncmp(ops[i].name, buf, strlen(ops[i].name))) {
opbuf = ops[i].op;
buf_hex = sdb_fmt ("0x%.4X\n", opbuf);
break;
}
}
r_strbuf_set (&op->buf_hex, buf_hex);
return op->size;
}

RAsmPlugin r_asm_plugin_padauk = {
        .name = "padauk",
        .arch = "padauk",
        .license = "LGPL3",
        .bits = 16,
        .desc = "Padauk (dis)assembler",
        .disassemble = &_PADAUKDisass,
        .assemble = &_PADAUKAss,
};

#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
        .type = R_LIB_TYPE_ASM,
        .data = &r_asm_plugin_padauk
};
#endif
« Last Edit: November 18, 2018, 11:56:25 pm by DocBen »
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #66 on: November 19, 2018, 07:15:18 am »
Playing further with radare I noticed that there are mostly disassembler backends but only a few assemblers.
I kind of like the idea of having something table driven that allows for a certain symmetry of assembler and disassembler.
Also looks more like a datasheet. Again not complete but recognizes the instructions given, if you want more instructions its literally copy and paste from the website somewhere above.

Don't know if I'll be able to finish this soon though. Just to give an idea that this could be generalized I did the same for pic12 and at least it looks good ;)

Code: [Select]
/* Padauk (dis)assembler plugin for radare 3.1 git - DocBen 2018
now looking more like a datasheet
*/

#include <r_asm.h>
#include <r_lib.h>
#include <string.h>

static struct {
char *op;
char *name;
ut8 args;
char *comment;
} ops[] = {
// memory mapped io i (6-bit)
// nth bit n (3-bit)
// memory address m (6 bit)
// memory address M (7 bit)
// immediate c (8 bit)
// address k (11 bit)
//"binary representation","mnemonic"(,"num parameters (could be inferred)"),"comment"
"0000.0000.0000.0000", "nop", 0, "does nothing (tm)",
"0000.0000.0110.0000", "addc a", 1, "A ← A + CF",
"0000.0000.11ii.iiii", "xor io,a", 2, "IO ← IO ^ A",
"0000.0001.10ii.iiii", "mov io,a", 2, "IO ← A",
"0000.0001.11ii.iiii", "mov a,io", 2, "A ← IO",
"0000.0010.cccc.cccc", "ret c", 1, "",
"0000.0011.1MMM.MMM0", "idxm M, a", 2, "[M] ← A (last bit of M set to 0, M must be word aligned, 2 cycles)",
"0000.0011.1MMM.MMM1", "idxm a, M", 2, "a ← [M] (last bit of M set to 1, M must be word aligned, 2 cycles)",
"0000.010n.nnii.iiii", "swapc io.n", 2, "",
"0000.0110.0MMM.MMMM", "comp a, M", 2, "",
"0010.000n.nnmm.mmmm", "t0sn m.n", 2, "",
"0011.0kkk.kkkk.kkkk", "goto k", 1, "goto address",
"0011.1kkk.kkkk.kkkk", "call k", 1, "call address",
"2222.2222.2222.2222", NULL, 0, "",
};


void bitstring(uint16_t val, char buffer[]) {
int size = 20;
buffer[--size] = 0;
while (size > 0) {
buffer[--size] = (val % 2 ? '1' : '0');
if ( size % 5 == 0 && size > 0) buffer[--size] = '.';
val = val >> 1;
}
}

int _PADAUKDisass (RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
int i;
op->size = 2;
const char *buf_asm = "unknown";
char buf_bin[40];
bitstring(0x100 * buf[0] + buf[1], buf_bin);
for (i=0; ops[i].name != NULL ; i++) {
for (int j = 0; j < 20; j++) {
if (ops[i].op[j] != buf_bin[j]) {
if (ops[i].op[j] != '0' && ops[i].op[j] != '1') { // treat all letters as dont care
continue;
} else {
break;
}
}
if (j == 19) {
buf_asm = sdb_fmt ("%s = %s ; %s", buf_bin, ops[i].name, ops[i].comment);
r_strbuf_set (&op->buf_asm, buf_asm);
return op->size;
}
}
}
r_strbuf_set (&op->buf_asm, buf_asm);
return op->size;
}

int _PADAUKAss (RAsm *a, RAsmOp *op, const char *buf) {
int i;
op->size = 2;
ut16 opbuf = 0x4000;
const char *buf_hex = "unknown";
for (i = 0; ops[i].name != NULL; i++) {
if (!strncmp(ops[i].name, buf, strlen(ops[i].name))) {
//opbuf = ops[i].op;
buf_hex = sdb_fmt ("0x%.4X\n", opbuf);
break;
}
}
r_strbuf_set (&op->buf_hex, buf_hex);
return op->size;
}

RAsmPlugin r_asm_plugin_padauk = {
        .name = "padauk2",
        .arch = "padauk2",
        .license = "LGPL3",
        .bits = 16,
        .desc = "Padauk (dis)assembler",
        .disassemble = &_PADAUKDisass,
        .assemble = &_PADAUKAss,
};

#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
        .type = R_LIB_TYPE_ASM,
        .data = &r_asm_plugin_padauk
};
#endif

PIC12
Code: [Select]
static struct {
char *op;
char *name;
ut8 args;
char *comment;
} ops[] = {
// direction d (1 bit)
// tri-state register t (2 bit)
// nth bit b (3-bit)
// register bank (3 bit)
// register f (5 bit)
// immediate c (8 bit)
// address k (8 bit)
// address K (9 bit)
//"binary representation","mnemonic"(,"num parameters"), "comment"
"0000.0000.0000.0000", "nop", 0, "No operation (MOVW 0,W)",
"0000.0000.0000.0010", "option", 0, "Copy W to OPTION register",
"0000.0000.0000.0011", "sleep", 0, "Go into standby mode",
"0000.0000.0000.0100", "clrwdt", 0, "Restart watchdog timer",
"0000.0000.0000.01tt", "tris t", 0, "Copy W to tri-state register (f = 1, 2 or 3)",
"0000.0000.0001.0BBB", "movlb k", 1, "Set bank select register to k",
"0000.0000.0001.1110", "return", 0, "Return from subroutine, W unmodified",
"0000.0000.0001.1111", "retfie", 0, "Return from interrupt; return & enable interrupts",
"0000.0000.001f.ffff", "movwf f", 1, "dest ← W",
"0000.0000.01df.ffff", "clr f,d", 2, "dest ← 0, usually written CLRW or CLRF f",
"0000.0000.10df.ffff", "subwf f,d", 2, "dest ← f−W (dest ← f+~W+1)",
"0000.0000.11df.ffff", "decf f,d", 2, "dest ← f−1",
"0000.0001.00df.ffff", "iorwf f,d", 2, "dest ← f | W, logical inclusive or",
"0000.0001.01df.ffff", "andwf f,d", 2, "dest ← f & W, logical and",
"0000.0001.10df.ffff", "xorwf f,d", 2, "dest ← f ^ W, logical exclusive or",
"0000.0001.11df.ffff", "addwf f,d", 2, "dest ← f+W",
"0000.0010.00df.ffff", "movwf f,d", 2, "dest ← f",
"0000.0010.01df.ffff", "comf f,d", 2, "dest ← ~f, bitwise complement",
"0000.0010.10df.ffff", "incf f,d", 2, "dest ← f+1",
"0000.0010.11df.ffff", "decfsz f,d", 2, "dest ← f−1, then skip if zero",
"0000.0011.00df.ffff", "rrf f,d", 2, "dest ← CARRY<<7 | f>>1, rotate right through carry",
"0000.0011.01df.ffff", "rlf f,d", 2, "dest ← F<<1 | CARRY, rotate left through carry",
"0000.0011.10df.ffff", "swapf f,d", 2, "dest ← f<<4 | f>>4, swap nibbles",
"0000.0011.11df.ffff", "incfsz f,d", 2, "dest ← f+1, then skip if zero",
"0000.0100.bbbf.ffff", "bcf f,b", 2, "Clear bit b of f",
"0000.0101.bbbf.ffff", "bsf f,b", 2, "Set bit b of f",
"0000.0110.bbbf.ffff", "btfsc f,b", 2, "Skip if bit b of f is clear",
"0000.0111.bbbf.ffff", "btfss f,b", 2, "Skip if bit b of f is set",
"0000.1000.cccc.cccc", "retlw c", 2, "Set W ← k, then return from subroutine",
"0000.1001.kkkk.kkkk", "call k", 2, "Call subroutine, 8-bit address k",
"0000.101K.KKKK.KKKK", "goto k", 2, "Jump to 9-bit address k",
"0000.1100.cccc.cccc", "movlw c", 2, "W ← c",
"0000.1101.cccc.cccc", "iorlw c", 2, "W ← c | W, bitwise logical or",
"0000.1110.cccc.cccc", "andlw c", 2, "W ← c & W, bitwise and",
"0000.1111.cccc.cccc", "xorlw c", 2, "W ← c ^ W, bitwise exclusive or",
"2222.2222.2222.2222", NULL, 0, "",
};
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #67 on: November 19, 2018, 09:11:11 pm »
Nice job, would it be possible to make a github repo out of it?

Anyhow my idea for a "universal" instruction table was to have a list of objects like this, if this can somehow interest you:

opcode (16bit)
opcode_mask (16bit)
parameters (array)
[
  {
    type {IO/MEM/IMM/...}
    length (in bits)
    pos (bit n#)
  }
]

There are not a lot of instructions that have more than one parameter encoded, but there are still some, so having an array of parameters descriptions covers everything. Let's call the object above "instr_t". You could write functions to create an instr_t from an assembly line, from an opcode or whatever. Also you could write functions to convert it to an opcode, to an assembly line or to emulate the thing (or maybe the emulator is just a big switch on the opcode and you do everything manually, idk). The point is, this should cover everything and be pretty flexible and somewhat clean.

It may be faster than your current approach (which I like anyway, it is very readable IMHO) but by pattern matching like that may not be the most efficient thing, also you'll have to reconstruct the parameter values and other stuff which would be easier with a table like mine, at least that's what I anticipate.
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #68 on: November 19, 2018, 09:20:31 pm »
Also you may want the make install rule to install the plugin under the user plugins directory (on my Linux system it's ~/.local/share/radare2/plugins) which is a bit less invasive ;)
 

Offline david.given

  • Contributor
  • Posts: 6
  • Country: ch
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #69 on: November 20, 2018, 12:58:23 am »
The architecture's engagingly minimal --- memory/memory architecture, one register! I actually have a self-hosting tiny compiler (<plug> http://cowlark.com/cowgol </plug>) which would map very nicely onto this thing. Sadly, it doesn't have enough RAM to run the compiler on itself...

If anyone comes up with a simulator which will run PDK files, I'd love to know about it!
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #70 on: November 20, 2018, 01:37:44 am »
Uhm, I just noticed the PMS150/PMS150C opcodes are different from the PMS154C ones, while still being 14-bit wide. Seems like there are multiple encodings for the same instructions.

For instance:

mov A, 0xAA       -> 0x17AA
mov <addr>, A    -> 0x05C.. something like that
pcadd a               -> 0x0017
wdreset                -> 0x0030

But they're not totally different, most of the time it's just one bit off. Also the PDK fill pattern is 0x1FFF instead of 0x3FFF.

This may need some investigation.

edit: actually no value goes beyond 0x1FFF, I should have noticed that before. Seems like they shaved one bit off and the opcodes are 13-bit (?) if that makes any sense.
« Last Edit: November 20, 2018, 01:42:39 am by gdelazzari »
 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #71 on: November 20, 2018, 02:11:50 am »
If anyone comes up with a simulator which will run PDK files, I'd love to know about it!

Maybe it could be added as a target for QEMU. It has already all kinds of infrastructure functions to implement a new target without too much effort, and it is very fast, because it translates the code to native assembler code on the fly, like a JIT compiler. And it has already functions for timers, interrupts etc.
So Long, and Thanks for All the Fish
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #72 on: November 20, 2018, 02:27:18 am »
If anyone comes up with a simulator which will run PDK files, I'd love to know about it!

I intend to get support for some Padauk devices into SDCC. For this, they'd need to be supported in the asxxxx fork that SDCC uses, the linker and the uCsim simulator. Support for the Single-Core devices will probably come first (as the lack of sp-relative addressing is a serious restriction for the multicore devices, requiring careful though on how to work around it).

Philipp
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #73 on: November 20, 2018, 02:35:43 am »
Uhm, I just noticed the PMS150/PMS150C opcodes are different from the PMS154C ones, while still being 14-bit wide. Seems like there are multiple encodings for the same instructions.

For instance:

mov A, 0xAA       -> 0x17AA
mov <addr>, A    -> 0x05C.. something like that
pcadd a               -> 0x0017
wdreset                -> 0x0030

But they're not totally different, most of the time it's just one bit off. Also the PDK fill pattern is 0x1FFF instead of 0x3FFF.

This may need some investigation.

edit: actually no value goes beyond 0x1FFF, I should have noticed that before. Seems like they shaved one bit off and the opcodes are 13-bit (?) if that makes any sense.

There are 3 different instruction sets¹ (each with some minor variation such as possible presence of mul). I assumed them to be 14, 15 and 16 bits. But from what you found it seems that they are 13, 14 and 16 bits. The 13-bit instruction set would be used on devices that have up to 1 kiloword of program memory, the 14-bit instruction set for up to 2 kilowords of program memory. The 16-bit instruction set would then be for larger and multicore devices.

Philipp

¹ According to an email by Padauk.
 

Offline DDunfield

  • Contributor
  • Posts: 32
  • Country: ca
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #74 on: November 20, 2018, 03:49:12 am »
Hi Guys,

Just found this thread. Seems like we've been duplicating some work.

I was planning to develop a PC based simulator to allow code to be quickly
tested and debugged, and also perhaps an STM32 based one which would allow
code to be tested "in circuit" with downloadability and decent debugging
capability. Would also like to eventually include device programming in
the STM32 but I've not looked really looked into it yet.

Here's what I've figured out about the instruction set:
I've added some notes and questions at the end, if anyone can help clarify
these points, please let me know.

The PMS/C150 uses a 13 bit opcode:

00000 101ppppp  MOV       A,io-addr
00000 100ppppp  MOV       io-addr,A
10111 dddddddd  MOV       A,imm-data
00111 11aaaaaa  MOV       A,ram-addr
00101 11aaaaaa  MOV       ram-addr,A
00000 110aaaa1  LDT16     ram-addr-even
00000 110aaaa0  STT16     ram-addr-even
00000 111aaaa1  IDXM      A,ram-addr-even
00000 111aaaa0  IDXM      ram-addr-even,A
01001 11aaaaaa  XCH       ram-addr
00000 00110010  PUSHAF
00000 00110011  POPAF
10000 dddddddd  ADD       A,imm-data
00110 00aaaaaa  ADD       A,ram-addr
00100 00aaaaaa  ADD       ram-addr,a
00000 00010000  ADDC      A
00110 10aaaaaa  ADDC      A,ram-addr
00100 10aaaaaa  ADDC      ram-addr,A
10001 dddddddd  SUB       A,imm-data
00110 01aaaaaa  SUB       A,ram-addr
00100 01aaaaaa  SUB       ram-addr,a
00000 00010001  SUBC      A
00110 11aaaaaa  SUBC      A,ram-addr
00100 11aaaaaa  SUBC      ram-addr,A
01001 00aaaaaa  INC       ram-addr
01001 01aaaaaa  DEC       ram-addr
01001 10aaaaaa  CLEAR     ram-addr
00000 00011010  SR        A
01010 10aaaaaa  SR        ram-addr
00000 00011100  SRC       A
01011 00aaaaaa  SRC       ram-addr
00000 00011011  SL        A
01010 11aaaaaa  SL        ram-addr
00000 00011101  SLC       A
01011 01aaaaaa  SLC       ram-addr
00000 00011110  SWAP      A
10100 dddddddd  AND       A,imm-data
00111 00aaaaaa  AND       A,ram-addr
00101 00aaaaaa  AND       ram-addr,A
10101 dddddddd  OR        A,imm-data
00111 01aaaaaa  OR        A,ram-addr
00101 01aaaaaa  OR        ram-addr,A
10110 dddddddd  XOR       A,imm-data
00111 10aaaaaa  XOR       A,ram-addr
00101 10aaaaaa  XOR       ram-addr,A
00000 011ppppp  XOR       io-addr,A
00000 00011000  NOT       A
01010 00aaaaaa  NOT       ram-addr
00000 00011001  NEG       A
01010 01aaaaaa  NEG       ram-addr
01110 bbbppppp  SET0      io-addr.bit
01111 bbbppppp  SET1      io-addr.bit
00011 bbb0aaaa  SET0      ram-addr.bit
00011 bbb1aaaa  SET1      ram-addr.bit
10010 dddddddd  CEQSN     A,imm-data
01011 10aaaaaa  CEQSN     A,ram-addr
01100 bbbppppp  T0SN      io-addr.bit
01101 bbbppppp  T1SN      io-addr.bit
00010 bbb0aaaa  T0SN      ram-addr.bit
00010 bbb1aaaa  T1SN      ram-addr.bit
00000 00010010  IZSN      A
00000 00010011  DZSN      A
01000 10aaaaaa  IZSN      ram-addr
01000 11aaaaaa  DZSN      ram-addr
110aa aaaaaaaa  GOTO      code-addr
111aa aaaaaaaa  CALL      code-addr
00001 dddddddd  RET       imm-data
00000 00111010  RET
00000 00111011  RETI
00000 00000000  NOP
00000 00010111  PCADD     A
00000 00111000  ENGINT
00000 00111001  DISGINT
00000 00110110  STOPSYS
00000 00110111  STOPEXE
00000 00110101  RESET
00000 00110000  WDRESET
00000 00000000  TRAP     // Assembler accepts, but same as NOP

General notes:
--------------
Full ram-addr range is 0x00-0x3B (60 bytes).

Instructions requiring ram-addr-even allow only 0x00-0x1E, lowest bit
is *NOT* encoded and is assumed to be zero.

Bit set/clear instructions on ram-addr allow only 0x00-0x0F.

Full io-addr range is 0x00-0x1F.


Instruction set notes:
----------------------
According to the data sheet, there are 4 flags: OV, Z, C, AC

Other than 'C' which can be accessed in the ADDC, SUBC, SRC and SLC
instructions, it is not clear what role the OV, Z and AC flags play.
There does not appear to be any instructions which access them.
The only conditionals are "compare ACC" and skip.

The only way I can see to access the other flags is via PUSHAF and then
reading them from memory (you would need to know exactly where SP points).

I'm wondering if this is "cut/paste" error and this processor does not
actually have OV, Z and AC (would make writing the simulator easier).

Perhaps someone with the actual part could write some test code using
arithmetic instructions and PUSHAF to test if these flags are actually
implemented on the PMS150?


The data sheet also says (page 18): (sic)
"The OTP program memory may contains the data, tables and interrupt entry."

I can see no capability in the instruction set to read data/tables from
program memory (other than immediate data).
Perhaps I have missed something?


The instruction set allows for a MAXIMUM of 64 bytes of RAM ... RAM
addresses are encoded in 6 bits. Yet, the indirect instruction IDXM uses
"pointer" values in memory which are two bytes in size. This makes no
sense to me as RAM is a very limited resource, and only one byte is needed
to address all of it. It also wastes instructions clearing the unused top
byte of the pointer - also a limited resource.

Perhaps "special" values in the upper byte allow indexed access to other
things, such as CODE memory or IO space ... but I can find no mention of
any such capability. Anyone know better?


PADAUK assembler notes:
-----------------------
HB@,LB@/HD@,LD@ can be used to access high/low byte of word data:
   MOV A,hb@word_symbol

HA@,LA@ can be used to get high/low symbol address as immediate-data:
   MOV A,ha@symbol

IO. can be used to specify an arbitrary IO address:
   MOV A,io.2

I've not found a prefix for force a RAM access. The only way I've found
to access ROM is by explicitly declaring symbols with "word" and "byte"
directives. Anyone know better?


Regards,
Dave

 
The following users thanked this post: oPossum

Offline david.given

  • Contributor
  • Posts: 6
  • Country: ch
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #75 on: November 20, 2018, 03:57:52 am »
Incidentally, some interesting ISA quirks I've noticed:

  • Stack grows up!
  • No stack-relative addressing (C will be hard)
  • Indirect addressing uses a 16-bit pointer where the MSB must be 0

So if you wanted C-style stack frames, god help you, your function preamble/postamble would look like:

Code: [Select]
mov a, lb@fp ; read old frame pointer
pushaf ; save
mov a, sp ; read stack pointer
mov fp, a ; set new frame pointer
add A, 8 ; allocate stack frame
mov SP, A ; update stack pointer
...main code here...
mov a, fp ; read current frame pointer
mov sp, a ; retrack over frame
popaf ; load old frame pointer
mov fp, a ; reload old frame pointer
ret
 

Blech.

To read a value from the frame, you'd need:

Code: [Select]
mov a, 4 ; frame offset
add a, fp ; add frame pointer
mov lb@ptr, a
idxm a, ptr

...which is equally grim. Running traditional C on this would be a mug's game, of course.

Cowgol doesn't use stack frames, though, so it's golden.

You might be able to do some incredibly basic Forth, based around an opcode interpreter, with some hoops to jump through to be able to read words out of RAM as well as program memory, but it's probably only worth it for the lols --- I expect it would eat most of the program space and be slow to boot, and with the very limited I/O capability you wouldn't be able to interact with it once you'd done it. Admittedly, running Forth on a 3c machine would make for some pretty serious lols.
 

Offline david.given

  • Contributor
  • Posts: 6
  • Country: ch
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #76 on: November 20, 2018, 04:05:46 am »
Yay, so much talking across people...

Re data tables: I think they're referring to this sort of thing:

Code: [Select]
; index in A, returns value in A
load_value_from_table:
  pcadd a ; jump to pc + a
  ret 42
  ret 99
  ret -6
  ret 127
  ...etc...

I haven't seen anything for accessing program data. I assume the assembler knows whether to generate an IO or RAM instruction by the type of the symbol you're addressing.

Re the other flags: the flags byte is at IO address 0, so you can test any individual but with t1sn IO.3 or similar. I don't think we can get away with ignoring them...
 

Offline DDunfield

  • Contributor
  • Posts: 32
  • Country: ca
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #77 on: November 20, 2018, 04:12:50 am »
Re the other flags: the flags byte is at IO address 0, so you can test any individual but with t1sn IO.3 or similar. I don't think we can get away with ignoring them...

Thanks, I hadn't picked up on that little detail yet (been busy working out the instructions). That explains it.

Dave
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #78 on: November 20, 2018, 04:48:10 am »
Seems like we've been duplicating some work.

I would like to insist on finding a way to better collaborate on this. Something like Slack could help since we would have a decent chat platform to keep everything organized and coordinate stuff. We could have various channels for RE of the programmer, RE of the ISA, tools implementation, etc... would anyone be interested?

Cowgol doesn't use stack frames, though, so it's golden.

Your small language seems really interesting. I also do not see a lot of sense in porting "full" C for this architecture, IMHO it's just less of an hassle to write assembly. A mixed language with assembly+some high level constructs is the best thing, which is in fact what PADAUK did with their Mini-C. If we make an open source toolchain it wouldn't be bad to have our own language for this thing. Of course the self-hosting capability of your compiler (while being really cool) here is pointless, but I see myself liking a language like Cowgol with the possibility to interleave assembly code like PADAUK's Mini-C lets you do. I mean, instead of replicating their Mini-C we could take the opportunity to try something else.

Of course if someone manages to make C compile for this MCUs through SDCC or whatever, that would be really cool, but I would like to see how much overhead it is added, especially regarding function calls.
 

Offline gslick

  • Regular Contributor
  • *
  • Posts: 210
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #79 on: November 20, 2018, 04:52:34 am »
Hi Guys,

Just found this thread. Seems like we've been duplicating some work.

I was planning to develop a PC based simulator to allow code to be quickly
tested and debugged, and also perhaps an STM32 based one which would allow
code to be tested "in circuit" with downloadability and decent debugging
capability. Would also like to eventually include device programming in
the STM32 but I've not looked really looked into it yet.

Regards,
Dave

Are you the ImageDisk Dave? Interesting to see you pop up on this thread and looking at these low cost microcontrollers.
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #80 on: November 20, 2018, 05:24:31 am »
Hi Dave,

Great that you did the 13 bit instruction set. This is no duplicated work. I did the 154C which uses 14 bit instructions.

Please have a look at the github project I started:

https://github.com/free-pdk

If you like I can add you to the developer list.

Regarding FLAGs:

Have a look at the ".INC" include file in IDE. You can see that IO @ 0x00 holds all the flags:

Code: [Select]
FLAG IO_RW 0x00
OV IO_RW FLAG.3
AC IO_RW FLAG.2
CF IO_RW FLAG.1
ZF IO_RW FLAG.0

So with simple bit tests like T0SN IO.n  and T1SN IO.n you can check and skip next instructions with flags.

Example: To test for OV flag following code can be used:

Code: [Select]
T1SN OV
GOTO OVCLEAR
NOP
NOP
OVCLEAR:

You also could use  T1SN  FLAG.3

In the .INC file you also see that SP is emulated as an IO register and more interesting stuff.


In the next few days I will write a simulator for the 14 bit core. This should not take long at all.

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #81 on: November 20, 2018, 05:26:48 am »
Your small language seems really interesting. I also do not see a lot of sense in porting "full" C for this architecture, IMHO it's just less of an hassle to write assembly. A mixed language with assembly+some high level constructs is the best thing, which is in fact what PADAUK did with their Mini-C. If we make an open source toolchain it wouldn't be bad to have our own language for this thing. Of course the self-hosting capability of your compiler (while being really cool) here is pointless, but I see myself liking a language like Cowgol with the possibility to interleave assembly code like PADAUK's Mini-C lets you do. I mean, instead of replicating their Mini-C we could take the opportunity to try something else.

Of course if someone manages to make C compile for this MCUs through SDCC or whatever, that would be really cool, but I would like to see how much overhead it is added, especially regarding function calls.

The Padauks aren't the only architecture on which stack access is inefficient. For other such architectures (e.g. MCS-51), SDCC makes functions non-reentrant by default (i.e. unless the function is marked __reentrant or the --stack-auto command-line argument is supplied), placing local variables at fixed memory locations.

Philipp
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #82 on: November 20, 2018, 06:13:48 am »
SDCC makes functions non-reentrant by default (i.e. unless the function is marked __reentrant or the --stack-auto command-line argument is supplied), placing local variables at fixed memory locations.

Thanks for telling, I never used SDCC before actually and didn't know it supported even this kind of architectures. Nice to know.
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #83 on: November 20, 2018, 06:44:14 am »
By popular demand ;)
https://github.com/mypdk/radare_plugins

Anyhow my idea for a "universal" instruction table was to have a list of objects like this, if this can somehow interest you:

It may be faster than your current approach (which I like anyway, it is very readable IMHO) but by pattern matching like that may not be the most efficient thing, also you'll have to reconstruct the parameter values and other stuff which would be easier with a table like mine, at least that's what I anticipate.

You're absolutely right your instruction table is more precise but it is a lot less generic and requires more work.
My idea was to simply let the computer figure these things out a later point. The basic idea is to have something as easy to read and maintain as possible for these little buggers.
Later a parser can look at the definitions and write something like your structs automatically or generate an optimized assembler/disassembler.

I'm an engineer and thus obligated to be as lazy as possible   :popcorn:
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #84 on: November 20, 2018, 07:07:48 am »
I'm an engineer and thus obligated to be as lazy as possible   :popcorn:

I'm still not an engineer, just half-way through, so I can still be not lazy sometimes :P

I'm implementing the method I described, currently my table is defined like this:

Code: [Select]
static const auto PMS154_INSTRUCTIONS_SPEC = std::vector<instr_spec_t>
{
  // {mnemonic, opcode, opcode_mask, {args...}}

  {"nop",     0x0000, 0x3FFF, {}},

  {"addc",    0x0060, 0x3FFF, {{Accumulator, 0, 0}}},
  {"subc",    0x0061, 0x3FFF, {{Accumulator, 0, 0}}},
  {"izsn",    0x0062, 0x3FFF, {{Accumulator, 0, 0}}},
  {"izsn",    0x0063, 0x3FFF, {{Accumulator, 0, 0}}},

  // ...

  {"wdreset", 0x0070, 0x3FFF, {}},

  {"pushaf",  0x0072, 0x3FFF, {}},
  {"popaf",   0x0073, 0x3FFF, {}},

  // ...

  {"xor",     0x00C0, 0x3FC0, {{IO, 0, 6}, {Accumulator, 0, 0}}},
  {"mov",     0x0180, 0x3FC0, {{IO, 0, 6}, {Accumulator, 0, 0}}},
  {"mov",     0x01C0, 0x3FC0, {{Accumulator, 0, 0}, {IO, 0, 6}}},

  {"ret",     0x0200, 0x3F00, {{Immediate, 0, 8}}},

  {"stt16",   0x0300, 0x3F81, {{Memory, 0, 7}}},
  {"ldt16",   0x0301, 0x3F81, {{Memory, 0, 7}}},
  {"idxm",    0x0380, 0x3F81, {{Memory, 0, 7}, {Accumulator, 0, 0}}},
  {"idxm",    0x0381, 0x3F81, {{Accumulator, 0, 0}, {Memory, 0, 7}}},

  {"swapc",   0x0400, 0x3E00, {{IO, 0, 6}, {Bit_N, 6, 3}}},

  {"comp",    0x0600, 0x3F80, {{Accumulator, 0, 0}, {Memory, 0, 7}}},
  {"comp",    0x0680, 0x3F80, {{Memory, 0, 7}, {Accumulator, 0, 0}}},
  {"nadd",    0x0700, 0x3F80, {{Accumulator, 0, 0}, {Memory, 0, 7}}},
  {"nadd",    0x0780, 0x3F80, {{Memory, 0, 7}, {Accumulator, 0, 0}}},

  // ...
};

Which I hope you agree is still pretty readable thanks to various new C++ things that allow it to be written like that. Maybe with opcodes written in binary would have been easier but well...

And the hearth of the disassembler code is literally 60 lines of code, for the assembler will just be a little bit more. Once you have such a table you can just iterate over all the table and find whatever matches. If you are disassembling you check the opcode with the mask, if you are assembling you check the mnemonic and the parameters in their respective order. If you need to assemble for a variant of the instruction set you just pass another table.

Anyway I'm following my initial idea to create a "libpdk" which does everything as I previously described. That doesn't mean my approach is orthogonal to what you are doing with radare2, i.e. you could then use the library with the assembling/disassembling capabilities to create the plugin pretty easily just by calling in the library code.
« Last Edit: November 20, 2018, 07:10:52 am by gdelazzari »
 

Offline DDunfield

  • Contributor
  • Posts: 32
  • Country: ca
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #85 on: November 20, 2018, 07:27:23 am »
Are you the ImageDisk Dave? Interesting to see you pop up on this thread and looking at these low cost microcontrollers.

I am.

Perhaps more relevant to these discussions is my past-life of creating development tools for little processors (mostly 8-bit). C compilers, assemblers, debuggers, simulators etc.
If you're bored, you can look under "sample projects" at www.dunfield.com to see some of the similar/related stuff I used to support myself with.

MCUs in the "few cents" range are an interesting development!

Regards,
Dave

** Mostly retired now, but always up for an interesting project!
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #86 on: November 20, 2018, 08:00:38 am »
I got a disassembler for the 14-bit ISA working in a preliminary state based on the work that js_12345678_55AA did REing the opcodes. There are some strange things in the code generated by the IDE however, such as:

- sometimes there are calls to 0x07f... which are in the "0x3FFF filled" part of the ROM, 0x3FFF is "call @0x7ff", and at 0x7ff there's "izsn [0x44]" which doesn't make a lot of sense (?)
- there are some opcodes we don't know about, such as 0x0006 or 0x0007
- the code flow doesn't make sense in general in some cases, for instance the "GOTO FPPA0 instruction" at 0x0001 (I'm reading from the datasheet of the PMS154C) is "goto @0xc", at that address there's some code that then calls @0x7f6 which doesn't make sense, shouldn't the user program start?

I can however locate the code I wrote. The void func(void) is at 0x0002 till 0x000b and the FPPA0 is at 0x0086 (there's a goto going there at 0x0013).

This is the code I compiled from the IDE

Code: [Select]
#include "extern.h"

void func(void)
{
byte x = 5;
byte y = 6;
byte c;

c = x + y - ~x;
}

void FPPA0 (void)
{
.ADJUST_IC SYSCLK=IHRC/2 // SYSCLK=IHRC/2

func();

byte c = 0;

while (1)
{
c++;
}
}

I attacched the disassembled ROM if someone wants to take a look.

Has someone figured out this stuff yet? I guess there's most likely something wrong with the opcodes RE, but IDK, I still have to take a look. I'm posting so that anyone can check if interested.

edit: just realized the 0x0006 and 0x0007 where the undocumented instructions js_12345678_55AA found http://www.eevblog.com/forum/blog/eevblog-1144-padauk-programmer-reverse-engineering/msg1970672/#msg1970672 , makes sense
« Last Edit: November 20, 2018, 08:03:44 am by gdelazzari »
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #87 on: November 20, 2018, 08:12:02 am »
Hi,

@gdelazzari

Read about how IDE / WRITER inserts the "rolling code" (is in help / manual of IDE).

For 154 the example says to read the serial numer / rolling code by this:
Code: [Select]
call _SYS(ADR.ROLL);
call _SYS(ADR.ROLL)+1;
call _SYS(ADR.ROLL)+2;

Writer will insert "RET 0xAB  RET 0xCD  RET =0xEF" at those addresses which are located at the end of the ROM.

One call I could not figure out is to (last instruction possible -1) 0x3FFE. Maybe Writer will insert another RET 0x12  there.

I need to wait for my writer to arrive so I can write and read back.

The very last ROM word contains the values to setup IHRC , Security Fuse, ... (everything you setup with .ADJUST_IC).

.ADJUST_IC also will put a lot of init code inside (even contains delay loops, in case you setup something for SYSCLK other than "DISABLED").



Have fun,

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 
The following users thanked this post: gdelazzari

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #88 on: November 20, 2018, 08:22:14 am »
Thanks, this now makes more sense. By the way I have my disassembler implemented with an instruction table like the one I posted before which I believe is a pretty flexible approach, adding an assembler and an emulator based on that should be pretty easy. I'm sure you're almost there to a complete disassembler too (and maybe other tools). What approach did you use? I'm trying to understand if my code could be useful or not, I guess I'll wait for you to upload your disassembler to the GitHub org?
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #89 on: November 20, 2018, 08:36:00 am »
I try to build a cycle accurate simulator which is ultra fast and can synchronize to real time (even on STM32 :-)). I took some inspiration from already existing tiny fast 6502 simulators.

Right now I try to figure out (imagine) how the AC and OV flags are set. The user manual of the processors does not describe it in an understandable way for me.


Here is a part of the source of already finished code for some opcodes (eA holds A, ePC the PC, eF the FLAGs, eSP the SP)

Code: [Select]
  uint8_t  eF = CPUioGet(0x00);             //get flags from emulated IO port, mapped like in IO flags: (- - - - V A C Z)
  uint8_t  eSP = CPUioGet(0x02);            //get SP from emulated IO port
  uint16_t opcode = CPUcodeGet( ePC++ );    //fetch next opcode and advance PC
  eCurrentCycle++;                          //increment current cycle counter

  if( 0x3FFE == opcode ) //special opcode ?
  {
    //TODO... find out what it does. IDE inserts when using ADJUST_CHIP
  }
  else
  //14 bit opcodes 0x0000 - 0x00BF
  if( opcode<=0x00BF )
  {
    switch( opcode )
    {
      case 0x0000: break; //NOP

      ...
  }
  ...
  else
  //6 bit opcodes 0x02.. , 0x2800 - 0x2FFF
  if( (0x0200 == (opcode&0x3F00)) || (0x2800 == (opcode&0x3800)) )
  {
    switch( opcode & 0x3F00 )
    {
      case 0x0200: eA = opcode&0xFF; ePC=(((uint16_t)CPUmemGet(--eSP))<<8); ePC|=CPUmemGet(--eSP); break; //RET k
 
      case 0x2800: eA += opcode&0xFF; eF=(eA>255)<<1;eA&=0xFF;eF|=!eA; break; //ADD A,k //TODO: OV, AC
      case 0x2900: eA -= opcode&0xFF; eF=(eA>=0)<<1;eA&=0xFF;eF|=!eA; break; //SUB A,k //TODO: OV, AC

      case 0x2A00: //CEQSN A,k
      case 0x2B00: //CNEQSN A,k
        T = eA-(opcode&0xFF);            //TODO: A-k or k-A ?
        if( ((0x2A00==(opcode&0x3F00)) && !T) ||
            ((0x2B00==(opcode&0x3F00)) && T) )
        {
          ePC++; eCurrentCycle++;
        }
        eF=(T>255)<<1;T&=0xFF;eF|=!T; //TODO: OV,AC (based on T)
        break;

      case 0x2C00: eA &= opcode&0xFF; eF&=~1;eF|=!eA; break; //AND A,k
      case 0x2D00: eA |= opcode&0xFF; eF&=~1;eF|=!eA; break; //OR A,k
      case 0x2E00: eA ^= opcode&0xFF; eF&=~1;eF|=!eA; break; //XOR A,k
      case 0x2F00: eA  = opcode&0xFF; break; //MOV A,k
    }
  }               
  else
  //5 bit opcodes 0x0400 - 0x0500, 0x1800 - 0x27FF
  if( (0x0400 == (opcode&0x3E00)) || ((opcode>=0x1800) && (opcode<=0x27FF)) )
  {
    uint8_t bit = 1<<((opcode>>6)&7);
    uint8_t addr = opcode&0x3F;
    switch( opcode & 0x3E00 )
    {
      case 0x0400: T=CPUioGet(addr);CPUioPut(addr,eF&2?T|bit:T&~bit); eF&=~2;eF|=(T&bit)?2:0; break; //SWAPC IO.n
      case 0x1800: if( !(CPUioGet(addr)&bit) ) { ePC++; eCurrentCycle++; } break;                    //T0SN IO.n
      case 0x1A00: if( CPUioGet(addr)&bit ) { ePC++; eCurrentCycle++; } break;                       //T1SN IO.n
      case 0x1C00: CPUioPut(addr,CPUioGet(addr)&~bit); break;                                        //SET0 IO.n
      case 0x1E00: CPUioPut(addr,CPUioGet(addr)|bit); break;                                         //SET1 IO.n
      case 0x2000: if( !(CPUmemGet(addr)&bit) ) { ePC++; eCurrentCycle++; } break;                   //T0SN M.n
      case 0x2200: if( CPUmemGet(addr)&bit ) { ePC++; eCurrentCycle++; } break;                      //T1SN M.n
      case 0x2400: CPUmemPut(addr,CPUmemGet(addr)&~bit);break;                                       //SET0 M.n
      case 0x2600: CPUmemPut(addr,CPUmemGet(addr)|bit);break;                                        //SET1 M.n
    }
  }
  else
  //3 bit opcodes 0x3000 - 0x3FFF
  if( (0x3000 == (opcode&0x3000)) )
  {

    if( opcode & 0x0800 ) //CALL needs to put current PC on stack
    {
      CPUmemPut( eSP++, ePC & 0xFF ); //TODO: check if on stack is little endian
      CPUmemPut( eSP++, ePC>>8 );     //TODO: check if on stack is little endian
    }
    eCurrentCycle++;
    ePC = opcode & 0x07FF;
  }
  else
  {
    //unknown instruction
    CPUexceptionEmulation("Unknown instruction", opcode );
  }

  CPUioPut(0x02,eSP);  //store SP to emulated IO port
  CPUioPut(0x00,eF);   //store flags to emulated IO port

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline david.given

  • Contributor
  • Posts: 6
  • Country: ch
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #90 on: November 20, 2018, 08:40:18 am »
Is there any possibility of there being an internal ROM with more code in it? That would explain the weird jumps and calls.

Do any of these things have SPI or I2C? Because if we ever figure out the programming protocol, and you could make one of these processors program another, you could incredibly cheaply build a hypercube cluster of the flash versions of these things, all bootstrapped from one processor at the corner attached to the outside world... it'd be useless, but fascinating. Sadly, without some sort of fast comms it's probably not worth it.
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #91 on: November 20, 2018, 08:54:00 am »
If you are seeking for really fast emulation, why not a lookup table of function pointers? Keep in mind that, since it's an harvard architecture + OTP + no way to read raw data from ROM, it is feasible to pre-process the ROM code as you wish if that helps you encode the instructions in such a way that results in a faster interpretation, given you don't need the original content for other purposes other than interpreting the code.

For instance (just writing down what is passing through my mind right now, will need a lot of refinement, but the idea is this):

- map each instruction to an id (arbitrarly, whatever order you like) starting from 0 to the num of instr-1 so you can have a C array of pointers to functions that execute the instruction
- preprocess the ROM by "disassembling" the 14-bits or whatever-bits opcodes and representing them, for instance, as 3 bytes: one for the id, one for the first parameter and one for the second (if any)
- loop over the processed ROM and lookup the corresponding emulation function like instr_funcs[instr_id]();, place the two parameters in a couple of globals or just let the emulation functions pick them up relative to the PC (which is global ofc)
- the emulated function does it stuff and returns

not sure how to cleanly handle cycle-accurate though, I'll have to think about that.

This may be a bit slower than your fastest if (opcode ...) evaluation, but you gain a constant and predictable time for all instructions, which I think is preferrable especially if the code that runs a cycle of the emulated CPU is inside an interrupt handler which fires at <x> MHz. All of this is assuming you're not on Cortex-M7 i.e. there's no cache in between, that messes everything up obviously.

Another (reeeeeally cool) thing to do would be JIT, I have no idea if that could be feasible given how different the architectures are, and of course you would lock yourself to ARM Cortex, but that would be indeed really cool.
« Last Edit: November 20, 2018, 09:08:21 am by gdelazzari »
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #92 on: November 20, 2018, 09:12:10 am »
Is there any possibility of there being an internal ROM with more code in it? That would explain the weird jumps and calls.

Do any of these things have SPI or I2C? Because if we ever figure out the programming protocol, and you could make one of these processors program another, you could incredibly cheaply build a hypercube cluster of the flash versions of these things, all bootstrapped from one processor at the corner attached to the outside world... it'd be useless, but fascinating. Sadly, without some sort of fast comms it's probably not worth it.

The is a reserevd are of, depeding on the device 8 to 32 words at the end of the ROM. Not a place to hide a lot of code, but, as already explained (and stated in the documentation) for checksums, rolling code, oscillator calibration data, code options. Since the 13-bit and 14-bit instruction sets do not have the ltabh and ltabl instructions, on those devies the rollign code is implemented as ret k instruction. You jump into the code, immediately jump back, and get the data byte in the accumulator.

The devices do not have I²C or SPI. But it can easily be emulated in software. That's actually one of the good things about the multicore design: You let one core handle some I/O protocol, and another core handles your normal program. IMO, this can be a good alternative to hardware peripherals. It makes the hardware simpler, cheaper, and all the gates can be used for the tasks at hand, instead of many of them sitting idle.

Philipp
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #93 on: November 20, 2018, 09:14:24 am »
Perhaps more relevant to these discussions is my past-life of creating development tools for little processors (mostly 8-bit). C compilers, assemblers, debuggers, simulators etc.
[…]
** Mostly retired now, but always up for an interesting project!

Would you be interested in contributing to SDCC, a free C compiler targeting small devices? There is a bit of a lack of developers and developer time recently. SDCC is still progressing, but some backends have fallen a bit behind (and of course there is work to do in the frontend, too).

Philipp
 

Offline david.given

  • Contributor
  • Posts: 6
  • Country: ch
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #94 on: November 20, 2018, 09:36:27 am »
Wait, are you the Dunfield C Dunfield?

I think way back when when I was looking for a portable C compiler I kept running into your C page and thinking it looked ideal and then cursing its closed source-ness... then Amsterdam Compiler Kit got open sourced, and it was so awful to build I begged a copy of the source repository from Ceriel Jacobs, uploaded it to SourceForge, and became the maintainer for it. (I think I now have the oldest genuine timestamps on github.)

With modern eyes I see now that Micro-C is K&R, so it wouldn't have been any good to me back then, but it's still amazingly small. If you're ever thinking of releasing the source I'd be fascinated to see how it works. (Cowgol's a lot larger, and I needed to split it into eight different compiler passes to make it run on a 6502...)
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #95 on: November 20, 2018, 09:56:31 am »
Padauk is not making any money selling the programmer, so why don't ask them for the programming protocol?
The have been asked and they refused to provide any information.

It could make sense to reverese-engineer the protocol for the Flash-based devices first:

1) These devices are probably more interesting to us than the OTP ones
2) The protocol is simpler (less voltages, max 8V on ICVPP)
3) The pins used are documented with signal names (VDD, GND, ICVPP, ICPDA, ICPCK)

Philipp
 

Offline david.given

  • Contributor
  • Posts: 6
  • Country: ch
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #96 on: November 20, 2018, 10:49:52 am »
I don't know if the protocol's the same, but ICPCK/ICPDA are the same names that Holtek use for their line of ludicrously cheap microcontrollers.

http://www.holtek.com/documents/10179/106680/Holtek_Flash_MCU_Quick_Start_Guide_V100_en.pdf
 

Offline DDunfield

  • Contributor
  • Posts: 32
  • Country: ca
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #97 on: November 21, 2018, 02:34:45 am »
Would you be interested in contributing to SDCC, a free C compiler targeting small devices?

Probably not, I've not seen much open-source code I'd be happy working on... but that's a different discussion.


Wait, are you the Dunfield C Dunfield?

Mea culpa!

Regarding the source, I've not made it publicly available, but I've been known to give it out to interested parties.

For things not pertaining to the Padauk discussion, please contact me off list. Either through the messaging here (I'll try to check it at least every couple of days), or to my email at:

  my-first-name{dot}my-last-name{@}gmail{dot}com


Regarding simulation:

With modern tools, "switch" can be as efficient as a function call table, and you can avoid the overhead of functions entry/exit on each instruction (which can be several instructions to establish and release a stack frame).

I find the most difficult part doing the flags... C has a disadvantage of not having visibility to the processor flags, so when coding a simulator in C you need to work out the flag updates manually. This is usually more operations than performing the main operation of the simulated instruction.

Back in the day, when PC's were not a whole lot faster than the embedded systems we were emulating, I coded the simulation functions in assembly language, where I could reduce decoding to a very simple jump table, and access the flags set by the operation directly (which are usually at least similar to the setting of flags on the target processor.

My EMILY52 simulator could emulate an 8051/52 in real time on a Pentium1 (or even a decent 486). The simulation engine was coded in 8086 assembly and had an advantage that the 8051 flags were very similar to the 8086 flags. Instruction that didn't set flags would jump directly back to the next decode, instructions which set flags jumped to one of several routines which saved the flags in question (I think there were 3 or 4 different combinations of flags set by instructions) before heading on back to the next decode.

For instructions which used the flags, I simply loaded the 8086 flags from the saved flags before executing the instruction. When the flags were read as a byte, I used a lookup table to translate the saved 8086 flags into the corresponding 8051 flags positions.

8051 registers were only saved/restored to 8086 registers when the simulation stopped or started ... while running, they resided in 8086 registers and did not have to be loaded "per instruction".

Thing ran fast! - on more modern systems, it runs considerably faster than a hardware 805x ... It was so "streamlined" that the simulation engine had no "test for exit" .. just a tight instruction decode loop. When the user hit "STOP" I would plant a JMP instruction into the loop to break it which was then patched back by the exit handler.

Another technique I've used in the past to achieve high-speed simulation, which works well if:
 1) You can live with variance in the speed the first time a block of code gets executed,
 2) You don't support or accept higher overhead for self-modifying code

Is to have an array of JMP targets for every address (easy if you processor has 1024 words of code memory, harder if it has megs)... At the beginning, each JMP targets a routine which decodes the instruction and updates the JMP target to point to the handler for that instruction before launching it.

On subsequent passes the JMP branches directly to the correct instruction handler, and never even has to look at the opcode.

This is particularity effective if the opcodes are complex to decode words. For simple opcodes, a simple JMP table will be nearly as fast and much simpler to debug.


On a PC I'd probably use a simple JMP table for the PMS150, 13 bit = 8k words (32k bytes) and would give you one simple direct jump to the correct handler.

On the STM with 64K of code, 32K would be a bit much, I'd probably divide the opcodes into blocks based on which bits are used and decode with ANDs and a few switches.

But I haven't really looked into it that far yet...

Dave


 
The following users thanked this post: oPossum

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #98 on: November 22, 2018, 08:11:58 am »
Hi,

I disassembled and commented the code which the IDE inserts at the start of the OTP.

This code is used for calibration of the internal high speed RC oscillator.

It looks like WRITER is doing the following:

1. write the complete OTP and set the calibration value to 0xFF (actually a RET 0xFF)
2. reset the IC and wait for IC to execute the calibration measurement program (handshake and bit bang protocol using WRITER_CLK:PA.3 / WRITER_DAT_OUT:PA.5 / WRITER_DAT_IN:PA.6)
3. write the calibration value over the 0xFF value

=> This is a trick. The OTP is intial all '1'. Programing can change a '1' to a '0' ... but never back to one. So writing 0xFF leaves this cell all '1' and later when the real value is present it can be written there.

As you can see the (quite big) calibration code wastes some valuable OTP.
There is also a small programing mistake inside (near the end of the calibration)  8). ==> @PADAUK: maybe you want to fix it :-) (the mistake is harmless since WRITER can just reset the IC in order to restart a calibration, again ==> @PADAUK: you can save some valuable space here by just removing instructions from 0x004F - 0x0052)
With a little bit of practice the code also could be stripped here and there. Something we can do in future  :)


0x0000:   0x0070    WDRESET                     ;reset watchdog

0x0001:   0x2f00    MOV A, 0x00     
0x0002:   0x0182    MOV IO(0x02), A  ;SP        ;set SP to memory start (0)

0x0003:   0x3fed    CALL 0x7ED                  ;get IHRCR (value inserted from WRITER)
0x0004:   0x018b    MOV IO(0x0B), A  ;IHRCR     ;setup IHRCR

0x0005:   0x3fee    CALL 0x7EE
0x0006:   0x019a    MOV IO(0x1A), A             ;BGTR? (not in datasheet)

0x0007:   0x2f00    MOV A, 0x00                 ;setup low voltage detector (value inserted from IDE .CHIP)
0x0008:   0x019b    MOV IO(0x1B), A             ;MISC_LVR 4V/3V5/3V/2V75/2V5/1V8/2V2/2V

0x0009:   0x2f34    MOV A, 0x34     
0x000a:   0x0183    MOV IO(0x03), A  ;CLKMD     ;setup clock mode (value inserted from IDE .ADJUST_IC)

0x000b:   0x3ffe    CALL 0x7FE                  ;get stored calibration value (stored during programing of OTP)

;This is a nice trick. The OTP reads all as '1' when not programmed. Programing will change the relevant bits to '0'.
;The trick is that you can program the OTP multiple times. It is always possible to change '1' to '0' but never the other way around.
;So they store 0x02FF in code memory at position 0x7FE which translates to RET 0xFF. Later programer can change the 0xFF return value by
;overwriting it with the final value (0xFF still all bits '1').
;This means all the code follows is used for calibration during programing only (big waste of OTP)

0x000c:   0x2aff    CEQSN A, 0xFF               ;Check if is 0xFF (nothing written there?)
0x000d:   0x3054    GOTO 0x054                  ;Jump over calibration routine to user program

0x000e:   0x3fed    CALL 0x7ED                  ;get IHRCR (value inserted from programmer)
0x000f:   0x0b81    MOV [0x01], A               ;store it in memory @0x01

0x0010:   0x1f91    SET1 IO(0x11).6  ;PAC.6     ;configure PA.6 as output

;calibration routine
0x0011:   0x2f20    MOV A, 0x20     
0x0012:   0x0b80    MOV [0x00], A               ;store 0x20 in memory @0x00

0x0013:   0x1ad0    T1SN IO(0x10).3  ;PA.3      ;check for HIGH signal at PA.3   <-- check for handshake signal for WRITER
0x0014:   0x3013    GOTO 0x013                  ;wait until PA.3 is high

0x0015:   0x1f90    SET1 IO(0x10).6  ;PA.6      ;set PA.6 to HIGH                <-- send response to WRITER

0x0016:   0x0063    DZSN A                      ;1c big delay, underflows after first loop
0x0017:   0x3016    GOTO 0x016                  ;2c inner loop apx. 3*256 cycles = 768 cycles
0x0018:   0x1180    DZSN [0x00]                 ;1c
0x0019:   0x3016    GOTO 0x016                  ;2c outer loop apx. 32*(768+3) = 24672 cycles,
                                                ;-224 cycles from first inner loop (was init with 32 instead of 255) = 24448 cycles total delay

0x001a:   0x1d90    SET0 IO(0x10).6  ;PA.6      ;set PA.6 to LOW                 <-- stop sending response to WRITER

0x001b:   0x18d0    T0SN IO(0x10).3  ;PA.3      ;check for LOW signal at PA.3    <-- wait for WRITER to stop sending handshake signal
0x001c:   0x301b    GOTO 0x01B                  ;wait until PA.3 is low

0x001d:   0x2f01    MOV A, 0x01     
0x001e:   0x1950    T0SN IO(0x10).5  ;PA.5      ;if PA.5 is LOW ==> A=0x01 , HIGH ==> A=0xFF <-- WRITER sets ? ? ? value to 1/255 by setting PA.5
0x001f:   0x2fff    MOV A, 0xFF     

0x0020:   0x0c01    ADD A, [0x01]               ;add to IHRCR (value inserted from programmer) 1 or 255 (see above)
0x0021:   0x018b    MOV IO(0x0B), A  ;IHRCR     ;set new IHRCR
0x0022:   0x0b81    MOV [0x01], A               ;store new IHRCR value in memory @0x01

0x0023:   0x1ad0    T1SN IO(0x10).3  ;PA.3      ;check for HIGH signal at PA.3   <-- check for handshake signal for WRITER
0x0024:   0x3023    GOTO 0x023                  ;wait until PA.3 is high

0x0025:   0x1b50    T1SN IO(0x10).5  ;PA.5      ;check for HIGH signal at PA.5   <-- WRITER signals all done?
0x0026:   0x304f    GOTO 0x04F                  ;jump to end of calibration code

0x0027:   0x2f04    MOV A, 0x04     
0x0028:   0x0188    MOV IO(0x08), A  ;MISC      ;disable low voltage detector

0x0029:   0x18d0    T0SN IO(0x10).3  ;PA.3      ;check for LOW signal at PA.3    <-- wait for WRITER to stop sending handshake signal
0x002a:   0x3029    GOTO 0x029                  ;wait until PA.3 is low

;start measurment
0x002b:   0x2f02    MOV A, 0x02
0x002c:   0x0182    MOV IO(0x02), A  ;SP        ;setup SP to memory @0x02

0x002d:   0x1304    CLEAR [0x04]                ;zero memory @0x04
0x002e:   0x1305    CLEAR [0x05]                ;zero memory @0x05
0x002f:   0x2f55    MOV A, 0x55
0x0030:   0x0b82    MOV [0x02], A               ;store 0x55 in memory @0x02
0x0031:   0x2f00    MOV A, 0x00     
0x0032:   0x0b83    MOV [0x03], A               ;store 0x00 in memory @0x03

;16 bit loop (0x0055) times some operations with internal value LDSPTL:LDSPTH (timing register?)
0x0033:   0x0006    LDSPTL                      ;?load from timing register L
0x0034:   0x0b04    XOR [0x04], A
0x0035:   0x0007    LDSPTH                      ;?load from timing register H
0x0036:   0x0805    ADD [0x05], A

0x0037:   0x1584    SL [0x04]                   ;rotate left 16 bit value
0x0038:   0x1685    SLC [0x05]
0x0039:   0x1004    ADDC [0x04]

0x003a:   0x1282    DECM [0x02]                 ;memory low byte -1
0x003b:   0x1083    SUBC [0x03]                 ;memory high byte -1 if carry set
0x003c:   0x1a40    T1SN IO(0x00).1  ;FLAG.CF   ;test for carry (0x0000 -1 => carry set)
0x003d:   0x3033    GOTO 0x033                  ;loop

0x003e:   0x1f90    SET1 IO(0x10).6  ;PA.6      ;set PA.6 to HIGH                <-- send response to WRITER (measurement finished)


;send bit by bit the 16 bit measured value
0x003f:   0x1ad0    T1SN IO(0x10).3  ;PA.3      ;check for HIGH signal at PA.3   <-- check for handshake signal for WRITER
0x0040:   0x303f    GOTO 0x03F                  ;wait until PA.3 is high

0x0041:   0x1584    SL [0x04]                   ;16 bit shift left
0x0042:   0x1685    SLC [0x05]

0x0043:   0x0590    SWAPC IO(0x10).6 ;PA.6      ;set PA.6 according to carry (highest bit from 16 bit value before shift)

0x0044:   0x18d0    T0SN IO(0x10).3  ;PA.3      ;check for LOW signal at PA.3    <-- wait for WRITER to stop sending handshake signal
0x0045:   0x3044    GOTO 0x044                  ;wait until PA.3 is low

0x0046:   0x1950    T0SN IO(0x10).5  ;PA.5      ;check if PA.5 is LOW            <-- WRITER signals to send next bit
0x0047:   0x303f    GOTO 0x03F


0x0048:   0x1d90    SET0 IO(0x10).6  ;PA.6      ;set PA.6 to LOW

0x0049:   0x1ad0    T1SN IO(0x10).3  ;PA.3      ;check for HIGH signal at PA.3   <-- check for handshake signal for WRITER
0x004a:   0x3049    GOTO 0x049                  ;wait until PA.3 is high

0x004b:   0x18d0    T0SN IO(0x10).3  ;PA.3      ;check for LOW signal at PA.3    <-- wait for WRITER to stop sending handshake signal
0x004c:   0x304b    GOTO 0x04B                  ;wait until PA.3 is low

0x004d:   0x1b50    T1SN IO(0x10).5  ;PA.5      ;check for HIGH signal at PA.5   <-- WRITER signals to redo measurement
0x004e:   0x302b    GOTO 0x02B                  ;if PA.5 is LOW do the measurement again

;here seems to be an error in the program from PADAUK, very unlikely PA.3 went hight during last 2 instructions, should be HIGH check for sure
0x004f:   0x18d0    T0SN IO(0x10).3  ;PA.3      ;check for LOW signal at PA.3
0x0050:   0x304f    GOTO 0x04F                  ;wait until PA.3 is low

0x0051:   0x1b50    T1SN IO(0x10).5  ;PA.5      ;check for HIGH signal at PA.5   <-- WRITER signals all done?
0x0052:   0x3011    GOTO 0x011                  ;if PA.5 is LOW do the complete calibration again (including all handshakes)

0x0053:   0x3053    GOTO 0x053                  ;calibration successful, endless loop (chip needs reset + writing of calibration value from WRITER)

;----------------------------------------------------------------------------------------------------------------------------------------------

0x0054:   0x018b    MOV IO(0x0B), A  ;IHRCR     ;normal program start, set IHRCR

0x0055:   0x3055    GOTO 0x055                  ;the user program (was just a "while(1){}" loop)


Have fun,

JS
« Last Edit: November 22, 2018, 08:44:59 am by js_12345678_55AA »
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 
The following users thanked this post: rhodges

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #99 on: November 22, 2018, 08:37:49 am »
Nice job js_12345678_55AA, really interesting. Will take an in depth look.

At the moment I also got the 13-bit ISA implemented in my infrastructure so I can disassemble PMS150 (C) ROMs. I noticed an interesting thing (I still have to look at the disasm). The PMS150 (without the C) has an order of magnitude less init code compared to the PMS150C (which seems to have code that more or less does the same stuff the 154C is doing).

I'm attaching the two listings if someone wants to take a look and start figuring it out.

(to discriminate what's "my" code and PADAUK's code, in both ROMs I only have the main which is simply incrementing a byte in memory, you'll find the inc [0x...]; goto @0x... as the last two instructions in both listings, that are the only two things not part of the init code)
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #100 on: November 22, 2018, 11:02:57 am »
After checking the disassembly of the calibration again some things look suspicious:


;start measurment
0x002b:   0x2f02    MOV A, 0x02
0x002c:   0x0182    MOV IO(0x02), A  ;SP        ;setup SP to memory @0x02

0x002d:   0x1304    CLEAR [0x04]                ;zero memory @0x04
0x002e:   0x1305    CLEAR [0x05]                ;zero memory @0x05
0x002f:   0x2f55    MOV A, 0x55
0x0030:   0x0b82    MOV [0x02], A               ;store 0x55 in memory @0x02
0x0031:   0x2f00    MOV A, 0x00     
0x0032:   0x0b83    MOV [0x03], A               ;store 0x00 in memory @0x03

;16 bit loop (0x0055) times some operations
0x0033:   0x0006    LDSPTL                      ;load from memory where SP is pointing to A
0x0034:   0x0b04    XOR [0x04], A
0x0035:   0x0007    LDSPTH                      ;load from memory where SP is pointing to A
0x0036:   0x0805    ADD [0x05], A

0x0037:   0x1584    SL [0x04]                   ;rotate left 16 bit value
0x0038:   0x1685    SLC [0x05]
0x0039:   0x1004    ADDC [0x04]

0x003a:   0x1282    DECM [0x02]                 ;memory low byte -1
0x003b:   0x1083    SUBC [0x03]                 ;memory high byte -1 if carry set
0x003c:   0x1a40    T1SN IO(0x00).1  ;FLAG.CF   ;test for carry (0x0000 -1 => carry set)
0x003d:   0x3033    GOTO 0x033                  ;loop


At the beginning the SP is setup to point to a new location. SP / stack is never used anywhere after this point in calibration program.
So the only use could be from the undocumented instructions LDSPTL and LDSPTH. Also SP points to the memory which is initialized
with static values.

This lets me think LDSPTL/LDSPTL stands for "LoaD from SP Table Low" / "LoaD from SP Table High":
  LDSPTL   =>   A = [SP]
  LDSPTH   =>   A = [SP+1]

Then the above loop would be again some "obfuscation" crypto from PADAUK (XOR 0x55 ... smells like the magic value they love, known from IDE obfuscation).

The result in this case is just 0x11E4 which is then sent out via bitbang to the WRITER to "verify"  :-DD

The loop also serves the purpose to run for several cycles, so WRITER can measure the time it takes and use it for calibration.


JS

EDIT: The loop runs for exact 1040 cycles (including loop init)  :)
« Last Edit: November 22, 2018, 11:17:10 am by js_12345678_55AA »
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline amyk

  • Super Contributor
  • ***
  • Posts: 5925
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #101 on: November 22, 2018, 02:54:49 pm »
I sorted the 13-bit instructions in opcode order; some interesting patterns emerge (notice ADD SUB ADDC SUBC AND OR XOR MOV), as well as possible present-but-undocumented instructions:

Code: [Select]
00000 00000000  NOP
00000 00000000  TRAP     // Assembler accepts, but same as NOP
00000 00000001
 ..      ..     ??
00000 00001111
00000 00010000  ADDC      A
00000 00010001  SUBC      A
00000 00010010  IZSN      A
00000 00010011  DZSN      A
00000 00010100
 ..      ..     ??
00000 00010110
00000 00010111  PCADD     A
00000 00011000  NOT       A
00000 00011001  NEG       A
00000 00011010  SR        A
00000 00011011  SL        A
00000 00011100  SRC       A
00000 00011101  SLC       A
00000 00011110  SWAP      A
00000 00011111
 ..      ..     ??
00000 00101111
00000 00110000  WDRESET
00000 00110001  ?
00000 00110010  PUSHAF
00000 00110011  POPAF
00000 00110100  ?
00000 00110101  RESET
00000 00110110  STOPSYS
00000 00110111  STOPEXE
00000 00111000  ENGINT
00000 00111001  DISGINT
00000 00111010  RET
00000 00111011  RETI
00000 00111100
 ..      ..     ??
00000 01011111
00000 011ppppp  XOR       io-addr,A
00000 100ppppp  MOV       io-addr,A
00000 101ppppp  MOV       A,io-addr
00000 110aaaa0  STT16     ram-addr-even
00000 110aaaa1  LDT16     ram-addr-even
00000 111aaaa0  IDXM      ram-addr-even,A
00000 111aaaa1  IDXM      A,ram-addr-even
00001 dddddddd  RET       imm-data
00010 bbb0aaaa  T0SN      ram-addr.bit
00010 bbb1aaaa  T1SN      ram-addr.bit
00011 bbb0aaaa  SET0      ram-addr.bit
00011 bbb1aaaa  SET1      ram-addr.bit
00100 00aaaaaa  ADD       ram-addr,a
00100 01aaaaaa  SUB       ram-addr,a
00100 10aaaaaa  ADDC      ram-addr,A
00100 11aaaaaa  SUBC      ram-addr,A
00101 00aaaaaa  AND       ram-addr,A
00101 01aaaaaa  OR        ram-addr,A
00101 10aaaaaa  XOR       ram-addr,A
00101 11aaaaaa  MOV       ram-addr,A
00110 00aaaaaa  ADD       A,ram-addr
00110 01aaaaaa  SUB       A,ram-addr
00110 10aaaaaa  ADDC      A,ram-addr
00110 11aaaaaa  SUBC      A,ram-addr
00111 00aaaaaa  AND       A,ram-addr
00111 01aaaaaa  OR        A,ram-addr
00111 10aaaaaa  XOR       A,ram-addr
00111 11aaaaaa  MOV       A,ram-addr
01000 00000000
 ..      ..     ??
01000 01111111
01000 10aaaaaa  IZSN      ram-addr
01000 11aaaaaa  DZSN      ram-addr
01001 00aaaaaa  INC       ram-addr
01001 01aaaaaa  DEC       ram-addr
01001 10aaaaaa  CLEAR     ram-addr
01001 11aaaaaa  XCH       ram-addr
01010 00aaaaaa  NOT       ram-addr
01010 01aaaaaa  NEG       ram-addr
01010 10aaaaaa  SR        ram-addr
01010 11aaaaaa  SL        ram-addr
01011 00aaaaaa  SRC       ram-addr
01011 01aaaaaa  SLC       ram-addr
01011 10aaaaaa  CEQSN     A,ram-addr
01011 11000000
 ..      ..     ??
01011 11111111
01100 bbbppppp  T0SN      io-addr.bit
01101 bbbppppp  T1SN      io-addr.bit
01110 bbbppppp  SET0      io-addr.bit
01111 bbbppppp  SET1      io-addr.bit
10000 dddddddd  ADD       A,imm-data
10001 dddddddd  SUB       A,imm-data
10010 dddddddd  CEQSN     A,imm-data
10011 00000000
 ..      ..     ??
10011 11111111
10100 dddddddd  AND       A,imm-data
10101 dddddddd  OR        A,imm-data
10110 dddddddd  XOR       A,imm-data
10111 dddddddd  MOV       A,imm-data
110aa aaaaaaaa  GOTO      code-addr
111aa aaaaaaaa  CALL      code-addr
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #102 on: November 22, 2018, 05:51:54 pm »
Nice job js_12345678_55AA, really interesting. Will take an in depth look.

At the moment I also got the 13-bit ISA implemented in my infrastructure so I can disassemble PMS150 (C) ROMs. I noticed an interesting thing (I still have to look at the disasm). The PMS150 (without the C) has an order of magnitude less init code compared to the PMS150C (which seems to have code that more or less does the same stuff the 154C is doing).

I'm attaching the two listings if someone wants to take a look and start figuring it out.

(to discriminate what's "my" code and PADAUK's code, in both ROMs I only have the main which is simply incrementing a byte in memory, you'll find the inc [0x...]; goto @0x... as the last two instructions in both listings, that are the only two things not part of the init code)

Could you also add the 13-bit instructions to the documentation on GitHub?

Philipp
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #103 on: November 22, 2018, 05:56:36 pm »
After checking the disassembly of the calibration again some things look suspicious:


;start measurment
0x002b:   0x2f02    MOV A, 0x02
0x002c:   0x0182    MOV IO(0x02), A  ;SP        ;setup SP to memory @0x02

0x002d:   0x1304    CLEAR [0x04]                ;zero memory @0x04
0x002e:   0x1305    CLEAR [0x05]                ;zero memory @0x05
0x002f:   0x2f55    MOV A, 0x55
0x0030:   0x0b82    MOV [0x02], A               ;store 0x55 in memory @0x02
0x0031:   0x2f00    MOV A, 0x00     
0x0032:   0x0b83    MOV [0x03], A               ;store 0x00 in memory @0x03

;16 bit loop (0x0055) times some operations
0x0033:   0x0006    LDSPTL                      ;load from memory where SP is pointing to A
0x0034:   0x0b04    XOR [0x04], A
0x0035:   0x0007    LDSPTH                      ;load from memory where SP is pointing to A
0x0036:   0x0805    ADD [0x05], A

0x0037:   0x1584    SL [0x04]                   ;rotate left 16 bit value
0x0038:   0x1685    SLC [0x05]
0x0039:   0x1004    ADDC [0x04]

0x003a:   0x1282    DECM [0x02]                 ;memory low byte -1
0x003b:   0x1083    SUBC [0x03]                 ;memory high byte -1 if carry set
0x003c:   0x1a40    T1SN IO(0x00).1  ;FLAG.CF   ;test for carry (0x0000 -1 => carry set)
0x003d:   0x3033    GOTO 0x033                  ;loop


At the beginning the SP is setup to point to a new location. SP / stack is never used anywhere after this point in calibration program.
So the only use could be from the undocumented instructions LDSPTL and LDSPTH. Also SP points to the memory which is initialized
with static values.

This lets me think LDSPTL/LDSPTL stands for "LoaD from SP Table Low" / "LoaD from SP Table High":
  LDSPTL   =>   A = [SP]
  LDSPTH   =>   A = [SP+1]

Then the above loop would be again some "obfuscation" crypto from PADAUK (XOR 0x55 ... smells like the magic value they love, known from IDE obfuscation).

The result in this case is just 0x11E4 which is then sent out via bitbang to the WRITER to "verify"  :-DD

The loop also serves the purpose to run for several cycles, so WRITER can measure the time it takes and use it for calibration.


JS

EDIT: The loop runs for exact 1040 cycles (including loop init)  :)

Well, 0x55 is a value commonly used in self tests (you'll also see it used as a pattern in memory testers, etc). It has every other bit set, so if there is any interference between adjacent lines it can help detect that. Maybe the program above is one that their test enginers designed to test the ALU? E.g. by making the final result depend on nearly all logic gates or connections in the ALU working correctly?

Philipp
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #104 on: November 22, 2018, 06:15:19 pm »
SP / stack is never used anywhere after this point in calibration program.
So the only use could be from the undocumented instructions LDSPTL and LDSPTH.

Uhm, don't assume that because the init code initializes the SP it means that he init code uses the stack/SP register. The init code may very well be just initializing it for the user program and stuff.

Also SP points to the memory which is initialized with static values.

It may just be that they had to store some values and instead of touching the upper memory where the MiniC compiler usually places user variables (at least that's what I noticed) they preferred to use the first locations given they will be overwritten by the first push on the stack so "who cares". Maybe for a more "defined" undefined behaviour  :-DD
I mean, unless you fill your ram with vars and you have variables in 0x00, 0x01, ... you'll never end up reading by accident the values that the init code put somewhere, which is coherent with the fact that they're trying to totally hide the init code and its internal working/effects from the user.

This doesn't mean your hypothesis is wrong, IMHO it is very likely that those two instructions act on the stack in that way. But I just wanted to share my thoughts to look at that in a more objective way.
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #105 on: November 22, 2018, 06:21:43 pm »
Could you also add the 13-bit instructions to the documentation on GitHub?

Even better, as soon as I have some time I'll try to find a rule to derive the 13-bit ISA from the 14-bit one. Trust me, after writing by hand dozens of instructions to implement them in the disasm, I can tell there is A LOT of symmetry. I still didn't go in depth but seems it is just something like one bit missing. As soon as I figure that out I'll probably write a tool to do a mass-conversion from the 14-bit docs already up and eventually adjust by hand. Unless someone is already documenting the 13-bit one.

Also, js_12345678_55AA, I had a pull on the docs repo fixing some stuff that is still unfixed after your last commit (a couple of instr swapped IIRC), maybe you want to check that out.
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #106 on: November 22, 2018, 11:06:21 pm »
Also, js_12345678_55AA, I had a pull on the docs repo fixing some stuff that is still unfixed after your last commit (a couple of instr swapped IIRC), maybe you want to check that out.

Sorry, I did not see the pull request. I merged it now and added you as a project member to github.

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #107 on: November 22, 2018, 11:33:20 pm »
After reading your comments, resting a bit and looking at the init code again I think I found the real purpose.

It is a CHECKSUM of the code in ROM.

-> the value 0x0055 is the code size (it grows and shrinks when I compile programs with more/less code, verified with IDE)
-> LDSPTL and LDSPTH needs to be 2 different instructions so it can load indirect the low and high byte of the code memory
-> Since code memory can be bigger than 8 bit the pointer to load from needs to be 16bit -> they use the memory where SP is pointing to to store 2 bytes (the pointer to code memory)
-> the XOR, ADD and ROR is just the checksum algorithm they use

LDSPTL: A = LowByte(CodeMem([SP 16bit]))
LDSPTH: A = HighByte(CodeMem([SP 16bit]))

The 16 bit loop counter in init code also serves as pointer into code mem. So it calculates backwards a checksum of all *used* code memory (excluding unused space and special data at end of chip, IDE inserts the real code length in init code).

Only question left is... What are the MSB of LDSPTH when we only have 14 bit stored. Either they read as '1' or as '0'. Experiments with real hardware will show.


Since reading code memory is always a potential thread for chip readout security it would be understandable why this instructions are not in PADAUK user manual.

But with this method we can now store 14 bit tables instead of 8 bit only per instruction word

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #108 on: November 23, 2018, 02:37:14 am »
The checksum thing makes sense only if the programmer is not able to read back the OTP whenever it likes (which I guess is the case). Does that mean you can only verify the code if you disabled "security" or before the calibration phase?

Also worth noting that the PMS150 (non-C version) doesn't have any code like that by looking at its listing (I uploaded it some posts ago). That in fact makes sense, I just checked and the non C version doesn't have the "security" feature you can enable/disable. This mean the programmer can get away calculating the checksum just by reading the OTP which can always be read.
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #109 on: November 23, 2018, 03:14:12 am »
There might be an explanation why they do all these checks from another post:

Back in 2006 I was talking to a uC manufacturer in China about their 4 bit uC then costing $0,11 and lower with high volume we were discussing. It could replace $0,40 of logic on our boards so quite interesting with massproduction.
There were some bizar quirks in those things. They were manufactured for one single goal: cheap toys.
The manufacturing process was not as you expect from fabs these days with a result that in your firmware at boottime you had to test the ram since unknown bits would (not could) be dead and you had to make a map so not to use that byte in ram. Also upto 2% of the devices would have problems in the alu or other critical parts. I asked how I could know that the first code would run ok if the ram was not to be trusted. The answer was you could tell from the end product if it worked or not. :-DD
I couldnt believe this but had it b&w in an email.
They probably also sell 100% tested uCs that had no flaws but that was pricewise much less interesting.
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #110 on: November 23, 2018, 04:07:54 am »
Actually they even hint to that in their product description. That or low ESD tolerance as that doesnt seem to be selling argument for the cheapest chips.
I guess we will see once someone has programmed a few.

PMC150:
**Very stable performance.
**Using 0.5um OTP process with High EFT proprietary design
**Allow using at high EFT requirement products such as home-appliances and durables etc.
**Operating temperature range: -40°C ~ 85°C

PMS150:
**Valuable price
**Using 0.5um OTP process
**Good for battery or DC power based products but required higher noise immunity
**Not supposed to use in AC RC step-down powered or high EFT requirement applications
**Operating temperature range: -20°C ~ 70°C

PMS150C:
**Very Competitive price
**Using 0.18um OTP process
**Good for battery or DC power based products, such as toys or premiums etc.
**Not supposed to use in AC RC step-down powered or high EFT requirement applications
**Operating temperature range: -20°C ~ 70°C
« Last Edit: November 23, 2018, 04:13:14 am by DocBen »
 
The following users thanked this post: oPossum

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #111 on: November 23, 2018, 11:01:06 pm »
Hi,

I just got my ICE today... and when you connect it and start debugging you can bring up a disassembly window (no opcodes of course but good to verify our stuff).

I created a new project (name "P2") for PFS154 with the following sample code in "P2.C" (no real purpose, just to check the init code):
Code: [Select]

#include  "extern.h"



void<>FPPA0 (void)
{
  .ADJUST_IC  SYSCLK=IHRC/2    //  SYSCLK=IHRC/2


  while (1){}
}

Then I compiled it and now we got 2 outputs:
 
  - "P2_IDE_LST.txt" is what I got from IDE).

  - "P2_DIS_LST.txt" is from my disassembler using the opcodes we found out


You can see that they hide the "secret" checksum calculation part by inserting a bunch of NOPs (actually ICE really executes NOPs only there). There are also some funny instructions in their output (e.g. when there is an undefined IO)

left from IDE / right from custom disassembler
Code: [Select]
...
00000008     MOV ---- A      /         0x0008:   0x019b    MOV IO(0x1B), A  ;
...
00000033     NOP             /         0x0033:   0x0006    LDSPTL       
00000034     NOP             /         0x0034:   0x0b04    XOR [0x04], A
00000035     NOP             /         0x0035:   0x0007    LDSPTH       
00000036     NOP             /         0x0036:   0x0805    ADD [0x05], A
00000037     NOP             /         0x0037:   0x1584    SL [0x04]   
00000038     NOP             /         0x0038:   0x1685    SLC [0x05]   
00000039     NOP             /         0x0039:   0x1004    ADDC [0x04] 
0000003A     NOP             /         0x003a:   0x1282    DECM [0x02] 
0000003B     NOP             /         0x003b:   0x1083    SUBC [0x03] 
...


Unfortunately when I try to make a program with the undocumented instructions LDSPTL and LDSPTH it compiles fine, but ICE also inserts NOPs there so I can not test their behavior (I need to wait for PFS154 to arrive so I can play with the real IC).

Anyway, our opcode table looks very accurate. :)

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #112 on: November 24, 2018, 02:21:32 am »
Hi,

I just got my ICE today... and when you connect it and start debugging you can bring up a disassembly window (no opcodes of course but good to verify our stuff).


Is there any way you could determine the type of fpga they are using?
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #113 on: November 24, 2018, 02:34:09 am »
Is there any way you could determine the type of fpga they are using?

I will try. Without removing the cover it looks like the surface of the big IC was "chinese polished" (with Dremel  :)).

Will post some pictures later.

JS

EDIT:
USB enumeration shows this:
VID: 0x0797
PID: 0x7002
Device String: "LGS_DEV FX2-HID 0.01"

« Last Edit: November 24, 2018, 02:36:17 am by js_12345678_55AA »
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #114 on: November 24, 2018, 02:50:43 am »
EDIT:
USB enumeration shows this:
VID: 0x0797
PID: 0x7002
Device String: "LGS_DEV FX2-HID 0.01"

The FPPA_IDE.exe has some strings in it refering to:
L.G.S. TECHNOLOGY CO. ,LTD
K.K.K. TECHNOLOGY CO. ,LTD
Kent Lee Developer Studio Version 2014 and an email adress lgs.........@yahoo.com.tw
http://home.kimo.com.tw/lgs............/WEB_EXE_.jpg
D:\\KentLee\\Custom\\PDK80\\Source\\Refer\\Test_IC\\Wrt_ROM\\Wrt_ROM.txt

Also the device string you found is included in the exe along with some others:
x6337ec 17 16 IDW-360 FX2-HID
0x633800 17 16 PDK-ICE FX2-HID
0x633814 17 16 LGS-DEV FX2-HID
0x633828 17 16 LGS_DEV FX2-HID

0x6338d4 21 20 Writer : PDK3S-P-002
0x6338ec 30 29 Writer : PDK3S-P-002 (No Cap)
0x63390c 21 20 ICE    : PDK3S-I-002
0x633924 21 20 ICE    : PDK3S-I-003
0x63393c 17 16 SOCKET : EV3-004
0x633950 24 23 ICE    : PDK3S-I-004(*)
0x633968 21 20 ICE    : PDK5S-I-S01
0x633980 21 20 ICE    : PDK5S-I-S02
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #115 on: November 24, 2018, 03:03:07 am »
BTW the FX2 chip used has its firmware programmed on the fly (ie when connecting to USB into its onboard RAM), so it should be possible to experiment with it without any risk of bricking it.
 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #116 on: November 24, 2018, 03:09:45 am »
I got my ICE today as well. Here is a high resolution image: https://i.imgur.com/8yef37g.jpg

The FPGA has no markings. It might be possible to capture the JTAG init sequence, if it doesn't store the configuration data inside the FPGA, because looks like there is no external configuration flash memory.

The USB device is a CY7C68013A, with high speed USB (480 Mbps) and an integrated 8051 CPU, that can be booted through USB (there is an interesting project, which implements a communication through such a Cypress chip to a FPGA over USB, FPGALink). So this could be a very flexible construction, booting first the firmware of the 8051, then booting the FPGA bitstream, all over USB. But I think it might be easier to develop a new emulator than trying to reverse engineer this. Would be nearly impossible to decode the FPGA bitstream back to the HDL code.

"usb-devices" shows the same as js_12345678_55AA wrote:

Code: [Select]
T:  Bus=01 Lev=01 Prnt=01 Port=01 Cnt=03 Dev#=  9 Spd=480 MxCh= 0                                                                                                                                             
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1                                                                                                                                                 
P:  Vendor=0797 ProdID=7002 Rev=80.01                                                                                                                                                                         
S:  Manufacturer=PADAUK                                                                                                                                                                                       
S:  Product=LGS_DEV FX2-HID 0.01                                                                                                                                                                             
C:  #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=500mA                                                                                                                                                                       
I:  If#= 0 Alt= 0 #EPs= 2 Cls=03(HID  ) Sub=00 Prot=00 Driver=usbhid   
So Long, and Thanks for All the Fish
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #117 on: November 24, 2018, 03:17:33 am »
I got my ICE today as well. Here is a high resolution image: https://i.imgur.com/8yef37g.jpg

The FPGA has no markings. It might be possible to capture the JTAG init sequence, if it doesn't store the configuration data inside the FPGA, because looks like there is no external configuration flash memory.


Does the FPGA have markings on the bottom? It doesnt look dremeled on the top to me.
 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #118 on: November 24, 2018, 03:33:56 am »
I got my ICE today as well. Here is a high resolution image: https://i.imgur.com/8yef37g.jpg

The FPGA has no markings. It might be possible to capture the JTAG init sequence, if it doesn't store the configuration data inside the FPGA, because looks like there is no external configuration flash memory.


Does the FPGA have markings on the bottom? It doesnt look dremeled on the top to me.

I just ordered one of these PLCC remover from China. Will report back in 4 weeks when it arrives :)
So Long, and Thanks for All the Fish
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #119 on: November 24, 2018, 03:55:10 am »
I just ordered one of these PLCC remover from China. Will report back in 4 weeks when it arrives :)

I try to anticipate these things and ordered my 3.5$ FX2 dev board a week ago  ;)
 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 11686
  • Country: gb
    • Mike's Electric Stuff
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #120 on: November 24, 2018, 04:55:27 am »
Hi,

I just got my ICE today... and when you connect it and start debugging you can bring up a disassembly window (no opcodes of course but good to verify our stuff).


Is there any way you could determine the type of fpga they are using?
Could be a CPLD - plenty of PLC44 options showing on Digikey for that package. If there is 5V anywhere that would narrow it down a lot.

Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #121 on: November 24, 2018, 05:16:36 am »
Could be a CPLD - plenty of PLC44 options showing on Digikey for that package. If there is 5V anywhere that would narrow it down a lot.

I'm kind of hoping for a XC9572XL. It could very well be a cpld because the newest version (5S
-I-S02B dated 2017/7/24) of the ice also uses a socketed plcc44.

On second thought a CPLD probably does not have enough memory on board to emulate a full chip so must be something else.
« Last Edit: November 24, 2018, 05:40:49 am by DocBen »
 

Offline gdelazzari

  • Contributor
  • Posts: 15
  • Country: it
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #122 on: November 24, 2018, 05:46:12 am »
I'm reporting a conversation between me and js_12345678_55AA regarding planning of what to do next (and how) if anyone wants to share its thoughts. Not sure why I didn't directly post here in the forum thread, sorry for that  :-//

The things of most interest are probably the assembler and the syntax

Quote
Hi,

>Hi, do you have any plans to upload your disassembler (and eventually assembler if you have one) to the GitHub organization?

Sure I will do (I just want to structure it a bit more, will take 1-2 days)


>I also have tools in a preliminary state working with the 13-bit and 14-bit ISAs, which unfortunately is duplicate work but I wanted to disasm some listings so I proceeded anyway in implementing them, but that was not a lot of work so it's not a problem for me to trash everything if we want to keep your infrastructure.

All of the code I did is also just for experimentation. Most likely it will be replaced by better implementations later. So no need to keep / stick to something from me right now.


>Also I think we should define a bit how we want to proceed with the assembler.

I did not start with an assembler implementation. Maybe this is something you/somebody else want to try?
I'm already busy reversing stuff and find out how things are connected.
Today my WRITER and SIMULATOR arrived. So now I can start to work with real hardware :-)


>Some stuff to be discussed may be:
>- syntax quirks (how to represent various kind of values/addresses), asm directives, macros, defines, includes, etc...

I did not really investigated on this. I just used a syntax which I thought was good enough for first tests.
Mainly I used the syntax PADAUK used in their manuals. Just to distinguish between RAM / ROM / IO we would need to invent something. Note: The "." syntax is mainly used to represent a special bit (8051 assembly). "[ ]" are used for normal memory access. "WORD PTR" is usually used for 16 bit address references, ... I think we should adapt already known schemes so it easier for others to understand

Creating a document defining the syntax of the assembler would be a good starting point.

I think during implementation of assembler some changes will be required. Since the disassembler is fairly easy to adapt I consider it to follow any syntax changes the assembler creator might need to do.


>- whether to deviate from PADAUK's ASM syntax and implement something of our own, or whether to implement their same syntax for compatibility; or even both at the same time (i.e. a flag to choose the syntax)

One syntax please :-). As close as possible to PADAUK syntax with just some extensions for direct memory/io access.


>- what binary format we want to use across the open source toolchain, i.e. just the raw ROM content on a .bin file, or keeping their PDK format for compatibility with their OTP Writer, or have our own format, or a mix of these three things, or whatever :)

I think we should use the PDK format. The creation for a "liberated" WRITER seems to be the most difficult part which most likely will take the longest time.


>- if it makes sense to keep the ISA description open enough so that it can be imported by someone that wants to implement for instance an SDCC backend or a radare2 plugin to disasm, etc... or just keep it simple and hard coded in the tools

The ISA is so small and simple, everyone can adapt and implement it for a disasm within a few hours. So I think there is no need to be generic here.


>Also, regarding an hypothetical PC simulator (not real time, maybe cycle accurate, or even not) for debugging only:

Why "hypothetical PC simulator"? I finished this task already  8)


>- how that would be presented to the user, i.e.
>- a GUI? With what features? I/O interaction?
>- some kind of simulation you launch and outputs a waveform file in some standard format for inspection later (and that can also accept an input waveform file or some kind of description of what to do with the inputs - i.e. after 0.1s set PA.3 high etc...)
>- a command line tool like GDB where you can single step, inspect memory and regs, run, pause, etc...
>- a combination of some of the things above
>- ...

I was having a look at a 8051 emulator which uses ncurses ( https://github.com/jarikomppa/emu8051 ). This simulator I plan to repurpose for the front end.


>- we'll need our own init code if we want to create a full toolchain you can use from start to finish without touching PADAUK's tools, what should be done in that regard? Should we replicate PADAUK's code (eventually improving it) or do something else? Maybe have different init code options i.e. if you don't need precise clock speeds you can free up space by not having the calibration code, or you can chose to have it, you can have the ROM checksum or not, etc...

The init code is tied to the WRITER which I think we should stay compatible with (see comment above).
Usually this kind of things (init code) is implemented in include (.INC) files which the developer gets automatically in his project when he starts a new project (e.g. from a empty project template).
Then it up to the developer to modify / delete stuff from init code or use different/optimized implementations.


>- least important thing in this message but cool: a library of pre-made routines for stuff like SPI, UART, etc... could be made and optimized by the community. Like a collection of include files "spi.inc" "uart.inc" you can just bring in and use would be pretty cool

Personally I prefer simple sample projects with code snippets I can just cut and paste to my project. I don't like big libraries (like Arduino or STM32). Especially when every byte counts.


>The STM32 emulator you're working on is also vital in the toolchain I think, so keep that up. I started to play around with some methods of efficiently emulating the code on ARM Thumb by checking what assembly GCC generates for various approaches, and it seems like writing the time critical parts in assembly may be the easiest route... GCC insists on keeping the PC/ACC/ecc in RAM but having 12 general purpose registers I think the best thing is to assign the ACC, PC, SP, etc... to a couple of regs and avoid all the LDRs that just slow things down. Of course I may be wrong and there may be a way to write the C code in such a way that GCC does this by itself, but I still didn't find a way. I thought we could map every PADAUK's cycle to 8 cortex cycles with a CPU clock of 64MHz which sounds a reasonable choice given there's the ultracheap STM32F103C8T6 everywhere on eBay, Aliexpress, etc... that fits that frequency, staying in an 8 cycle frame might be viable if most of the stuff is in registers since most instructions take 1 cycle only. Did you make any progress regarding emulation on STM32?

After implementing the FLAG solver for AC and OV i recognized emulation will be quite complex.
Also keep in mind that you need to emulate the CLOCK, IO, PWM, INTERRUPTS, TIMER, WATCHDOG, ...
So I don't think a near real time emulation on STM32 will be possible.

But why not using FPGA? Simple ones are also very cheap. And one guy here in forum already said he would be able to create a FPGA version.


>Let me know what you think about my points and how we should proceed. If we can coordinate at least a bit the work that should be done (and how it should be done) I can start working on some tools.

Creating the assembler would be nice.
I really would love to have an assembler as soon as possible so I can automate tests for the simulator :-)
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #123 on: November 24, 2018, 07:04:05 am »
Does the FPGA have markings on the bottom? It doesnt look dremeled on the top to me.

Here comes the money shot:

Picture shows the ICE main IC (PLCC 44) from bottom.

Based on the top shape / edge / dot / corner  and the "SCD" marking on the bottom it most probably is a Xilinix.

Shape matches exact this drawing: https://japan.xilinx.com/support/documentation/package_specs/pc44.pdf  Most other PLCC44 FPGA/CLPD have marks on top / 2 edges / no dot in middle / ...



Happy hunting!

JS
« Last Edit: November 24, 2018, 07:19:27 am by js_12345678_55AA »
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #124 on: November 24, 2018, 07:32:03 am »
Reverse engineering the writer firmware might be a good idea, but to be sure maybe would be good to record a programming sequence as well.

I did some tests. I have only some free PMC884 samples at the moment which Padauk sent me. I also bought some PMS150C chips from lcsc.com, as recommended by Padauk, but needs some time until I get them.

First I programmed a blinky program, with all 8 FFPAs and different output frequencies. This is the main file (full project is attached) :

Code: [Select]
// define pin names
Out0 BIT PB.0;
Out1 BIT PB.1;
Out2 BIT PB.2;
Out3 BIT PB.3;
Out4 BIT PB.4;
Out5 BIT PB.5;
Out6 BIT PB.6;
Out7 BIT PB.7;

// FPPA0 is started first
void FPPA0 (void)
{
.ADJUST_IC SYSCLK=IHRC/2, IHRC=16MHz, VDD=5V, Bandgap=On;

// set pins to output
$ Out0 High, Out;
$ Out1 High, Out;
$ Out2 High, Out;
$ Out3 High, Out;
$ Out4 High, Out;
$ Out5 High, Out;
$ Out6 High, Out;
$ Out7 High, Out;

// see datasheet "pmode": FPPA duty cycle, 1/8 for all 8 FPPAs
pmode 31;

// enable all FPPAs
fppen = 0xFF;

// generate test output
while (1) {
Out0 = 0;
.delay 1;
Out0 = 1;
.delay 1;
}
}

void FPPA1 (void)
{
// generate test output
while (1) {
Out1 = 0;
.delay 10;
Out1 = 1;
.delay 10;
}
}

void FPPA2 (void)
{
// generate test output
while (1) {
Out2 = 0;
.delay 100;
Out2 = 1;
.delay 100;
}
}

void FPPA3 (void)
{
// generate test output
while (1) {
Out3 = 0;
.delay 1000;
Out3 = 1;
.delay 1000;
}
}

void FPPA4 (void)
{
// generate test output
while (1) {
Out4 = 0;
.delay 10000;
Out4 = 1;
.delay 10000;
}
}

void FPPA5 (void)
{
// generate test output
while (1) {
Out5 = 0;
.delay 100000;
Out5 = 1;
.delay 100000;
}
}

void FPPA6 (void)
{
// generate test output
while (1) {
Out6 = 0;
.delay 1000000;
Out6 = 1;
.delay 1000000;
}
}

void FPPA7 (void)
{
// generate test output
while (1) {
Out7 = 0;
.delay 10000000;
Out7 = 1;
.delay 10000000;
}
}

/*
void Interrupt (void)
{
pushaf;

if (Intrq.T16)
{ // T16 Trig
// User can add code
Intrq.T16 = 0;
//...
}

popaf;
}

*/

I measured the following frequencies (AVDD needs to be connected as well, otherwise looks like the internal oscillator doesn't run) :

Code: [Select]
PB0: 203 kHz
PB1: 44 kHz
PB2: 5 kHz
PB3: 508 Hz
PB4: 50.8 Hz
PB5: 5.08 Hz
PB6: 0.5 Hz
PB7: 0.05 Hz

Nice about the PMC884 is that you can select the duty cycle scheme, e.g. if you want to run FFPA0 more than the other FFPAs. So this was just a first test to see if everything works.

Then I tried to measure the programming signals (as David already noted in his video, you can program the OTP chip as often as you want, if it is the same bitstream). But connecting GND of the scope to the GND pin of the microcontroller was not a good idea, because the programmer tests all pins for shorts and then doesn't start the programming sequence. But here is a nice GND point near the jumpers at the back:



Then I measured some pins. In David's video it was difficult or impossible to see the timescale. Here is an example for pin 3, this time with proper time scale, for the whole programming cycle:



This is a data pin. Pin 19 is a clock pin. When I zoom in, it looks like this:



Looks like about 1 us is the shortest signal length. Might be good to sample it with 10 MHz for higher resolution.

I don't know how many signals I need to scan in parallel, 2 might be enough with multiple passes, but maybe 4 would be better and easier to analyze later. If I use an 8 bit ADC, this would mean a data rate of 320 Mbits/s. Might be possible with high speed USB to transfer it in realtime on a PC. As you can see in the first scope image, the whole programming cycle needs about 800 ms (the spikes before and after are the detection of the programmer if there is a chip, which does it all the time). So a full sample with 4 channels would need only 32 MB. This could be even done with a BeagleBone and its PRUs, a simple external board with 4 ADCs and input stages for dividing the input voltage, and then recording it to memory.

But I don't have much time at the moment to build the board and program the Beagle Bone. Is there already such a thing I can buy, which records 4 channels with 8 bit at 10 MHz for 1 second?

PS: Anyone who wants to swap some PMS150C (or other Padauk) chips for PMC884? I have 100 x PMC884. Here is the datasheet.
So Long, and Thanks for All the Fish
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #125 on: November 24, 2018, 08:00:43 am »
Does the FPGA have markings on the bottom? It doesnt look dremeled on the top to me.

Here comes the money shot:

Picture shows the ICE main IC (PLCC 44) from bottom.

Based on the top shape / edge / dot / corner  and the "SCD" marking on the bottom it most probably is a Xilinix.

Shape matches exact this drawing: https://japan.xilinx.com/support/documentation/package_specs/pc44.pdf  Most other PLCC44 FPGA/CLPD have marks on top / 2 edges / no dot in middle / ...



Happy hunting!

JS

Thank you very much!

judging from lcsc pictures xilinx chips dont have bottom markings.
Also I think that padauk might have put their own markings on the bottom because it would match their package marking scheme

However I have the strong feeling this is neither a fpga nor a cpld but an 8051, because the beginning of the deobfuscated pdk files looks like this, which kind of looks like a jump table:

X0000:   add   a,r2
X0001:   xrl   rb0r2,a
   anl   a,r6
   xrl   a,r4
   jnz   X005e
   jnc   X005b
   jnc   X006a
   jnc   X0061
X000d:   jnc   X0062
   jnc   X0020
   acall   X0357
   jnc   X0064
   jnc   X0076
X0017:   jnc   X006d
   jnc   X005e
   jnc   X0060
   jnc   X0038
   acall   X0357
   jnc   X0075
   jnc   X0084
   jnc   X007b
   jnc   X0074
   jnc   X0070
   jnc   X005e
X002d:   jnc   X0057
   acall   X0357
   jnc   X0085

the markings in the circles in the corners look similar to those of stc 8051 chips on lcsc (up to 80 Mhz apperantly). Maybe they do software emulation on an 8051?  :-//

Is that feasible? Are the files in USB_Driver/USB/ICE* really 8051ish code?
 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #126 on: November 24, 2018, 08:17:05 am »
Is that feasible? Are the files in USB_Driver/USB/ICE* really 8051ish code?

The 8051 code might be for the Cypress USB microcontroller, which can load firmware over USB for itself as well.
So Long, and Thanks for All the Fish
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #127 on: November 24, 2018, 08:24:52 am »
There are *.hid files for that which fill the complete 8 to 16kb for the fx2

But its really hard to say, the first part of the *pdk (unobfuscated) could very well also be lets say I/O mappings of an FPGA.

However its very hard to find any in an plcc44, cpld dont really fit the profile because they dont have sufficient memory to emulate ram/rom of the micro, and that basically leaves other microcontrollers.

Weird.
« Last Edit: November 24, 2018, 08:40:10 am by DocBen »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 2794
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #128 on: November 24, 2018, 08:49:58 am »
I'm a bit surprised that I don't see any voltage switching circuits between the PLCC and the connector that leads to the chip?   That would sort-of imply that the chip has some analog capability rather than being a digital FPGA?
(oh wait - is this "ICE Only" box with no programmer?  If so, never mind...)
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #129 on: November 24, 2018, 08:09:41 pm »
I'm reporting a conversation between me and js_12345678_55AA regarding planning of what to do next (and how) if anyone wants to share its thoughts. Not sure why I didn't directly post here in the forum thread, sorry for that  :-//

The things of most interest are probably the assembler and the syntax

Quote
Hi,

>Hi, do you have any plans to upload your disassembler (and eventually assembler if you have one) to the GitHub organization?

Sure I will do (I just want to structure it a bit more, will take 1-2 days)


>I also have tools in a preliminary state working with the 13-bit and 14-bit ISAs, which unfortunately is duplicate work but I wanted to disasm some listings so I proceeded anyway in implementing them, but that was not a lot of work so it's not a problem for me to trash everything if we want to keep your infrastructure.

All of the code I did is also just for experimentation. Most likely it will be replaced by better implementations later. So no need to keep / stick to something from me right now.


>Also I think we should define a bit how we want to proceed with the assembler.

I did not start with an assembler implementation. Maybe this is something you/somebody else want to try?
I'm already busy reversing stuff and find out how things are connected.
Today my WRITER and SIMULATOR arrived. So now I can start to work with real hardware :-)


>Some stuff to be discussed may be:
>- syntax quirks (how to represent various kind of values/addresses), asm directives, macros, defines, includes, etc...

I did not really investigated on this. I just used a syntax which I thought was good enough for first tests.
Mainly I used the syntax PADAUK used in their manuals. Just to distinguish between RAM / ROM / IO we would need to invent something. Note: The "." syntax is mainly used to represent a special bit (8051 assembly). "[ ]" are used for normal memory access. "WORD PTR" is usually used for 16 bit address references, ... I think we should adapt already known schemes so it easier for others to understand

Creating a document defining the syntax of the assembler would be a good starting point.

I think during implementation of assembler some changes will be required. Since the disassembler is fairly easy to adapt I consider it to follow any syntax changes the assembler creator might need to do.


>- whether to deviate from PADAUK's ASM syntax and implement something of our own, or whether to implement their same syntax for compatibility; or even both at the same time (i.e. a flag to choose the syntax)

One syntax please :-). As close as possible to PADAUK syntax with just some extensions for direct memory/io access.


>- what binary format we want to use across the open source toolchain, i.e. just the raw ROM content on a .bin file, or keeping their PDK format for compatibility with their OTP Writer, or have our own format, or a mix of these three things, or whatever :)

I think we should use the PDK format. The creation for a "liberated" WRITER seems to be the most difficult part which most likely will take the longest time.


>- if it makes sense to keep the ISA description open enough so that it can be imported by someone that wants to implement for instance an SDCC backend or a radare2 plugin to disasm, etc... or just keep it simple and hard coded in the tools

The ISA is so small and simple, everyone can adapt and implement it for a disasm within a few hours. So I think there is no need to be generic here.


>Also, regarding an hypothetical PC simulator (not real time, maybe cycle accurate, or even not) for debugging only:

Why "hypothetical PC simulator"? I finished this task already  8)


>- how that would be presented to the user, i.e.
>- a GUI? With what features? I/O interaction?
>- some kind of simulation you launch and outputs a waveform file in some standard format for inspection later (and that can also accept an input waveform file or some kind of description of what to do with the inputs - i.e. after 0.1s set PA.3 high etc...)
>- a command line tool like GDB where you can single step, inspect memory and regs, run, pause, etc...
>- a combination of some of the things above
>- ...

I was having a look at a 8051 emulator which uses ncurses ( https://github.com/jarikomppa/emu8051 ). This simulator I plan to repurpose for the front end.


>- we'll need our own init code if we want to create a full toolchain you can use from start to finish without touching PADAUK's tools, what should be done in that regard? Should we replicate PADAUK's code (eventually improving it) or do something else? Maybe have different init code options i.e. if you don't need precise clock speeds you can free up space by not having the calibration code, or you can chose to have it, you can have the ROM checksum or not, etc...

The init code is tied to the WRITER which I think we should stay compatible with (see comment above).
Usually this kind of things (init code) is implemented in include (.INC) files which the developer gets automatically in his project when he starts a new project (e.g. from a empty project template).
Then it up to the developer to modify / delete stuff from init code or use different/optimized implementations.

[…]

>Let me know what you think about my points and how we should proceed. If we can coordinate at least a bit the work that should be done (and how it should be done) I can start working on some tools.

Creating the assembler would be nice.
I really would love to have an assembler as soon as possible so I can automate tests for the simulator :-)


My plans so far:
  • Create an SDCC backend for the 14-Bit instruction set (since it is used on the small flash devices, will will probably be popular for development).
  • Create a simple PFS154 / PFS 173 dev board (want to wait with this until mid-december, when Padauk will release additional information on the upcoming PFC232, so maybe I can make the layout so the PFC232 would work on the same board).
  • Create an SDCC backend for the 13-Bit instruction set.
  • Create an SDCC backend for the 16-Bit instruction set (this will get complicated when support for multithreading gets included).

Things I will help with (I know someone who might want to do part of this):
  • Get support for the Padauk instruction sets (intially the 14-Bit one) into the asxxxx fork used in SDCC. Syntax will probably be the same as the Padauk assembler, maybe with a few exceptions (the flags would be called Z and C, like in padauk documentation, while the Padauk assembler seems to use ZF and CF; ltabl index would be ltabl a, index, ldsptl would be ldsptl a, since both write into a; so the syntax would be more similar to that of the idxm instruction). Output formats will probably we Intel hex and ELF as that is what SDCC uses for the other backends.
  • Get support for the Padauk instruction sets (intially the 14-Bit one) into the uCsim simulator used in SDCC for regression testing.

What I'd like to see but don't want to do myself:
  • Support for the Padauk binary format in other tools (objcopy)
  • Free software for programming the devices using Padauk's programmer (so we don't have to use Padauk's non-free Windows tool)
  • Free soft-/hardware for programming hte devices (so we get a cheaper alternative to Padauk's programmer, and with free firmware)

Philipp
 

Offline DDunfield

  • Contributor
  • Posts: 32
  • Country: ca
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #130 on: November 24, 2018, 09:42:26 pm »
I have a simulator implemented and somewhat working (have not tested all
instructions yet), and trying to run the startup code generated by the
assembler exposed a "weirdness" I had not noticed before:

The assembler insists that you put these startup macros in, so I used the
samples found in Demo/Dummy/Dummy.asm :

------------------- Cut here -------------
.CHIP PMS150
//{{PADAUK_CODE_OPTION
        .Code_Option    Under_20mS_VDD_Ok       No
        .Code_Option    LVR             2.5V
        .Code_Option    Security        Disable// Security Disable
//}}PADAUK_CODE_OPTION
.WRITER O_S
        .ADJUST_IC      SYSCLK=IHRC/8, IHRC=16MHz, VDD=5V;
------------------- Cut here -------------

Here is a disassembly of what it generates:

0000: 1700   MOV     A,0x00
0001: 0085   MOV     IO.0x05,A
0002: 0FE4   SET1    IO.0x04.7   // B7 documented as "reserved"
0003: 1700   MOV     A,0x00
0004: 0082   MOV     IO.0x02,A
0005: 1700   MOV     A,0x00
0006: 008B   MOV     IO.0x0B,A
0007: 173C   MOV     A,0x3C
0008: 0083   MOV     IO.0x03,A
0009: 1FFE   CALL    03FE       // ?? This is the problem ??
000A: 12FF   CEQSN   A,0xFF
000B: 181C   GOTO    001C
000C: 0FD1   SET1    IO.0x11.6
000D: 0981   CLEAR   MEM.0x01
000E: 1709   MOV     A,0x09
000F: 05C0   MOV     MEM.0x00,A
0010: 0D90   T1SN    IO.0x10.4
0011: 1810   GOTO    0010
0012: 0FD0   SET1    IO.0x10.6
0013: 0013   DZSN    A
0014: 1813   GOTO    0013
0015: 08C0   DZSN    MEM.0x00
0016: 1813   GOTO    0013
0017: 0ED0   SET0    IO.0x10.6
0018: 0901   INC     MEM.0x01
0019: 07C1   MOV     A,MEM.0x01
001A: 008B   MOV     IO.0x0B,A
001B: 180E   GOTO    000E
 // .. user code goes here
03F8: 0000   NOP     
03F9: 0000   NOP     
03FA: 0000   NOP     
03FB: 0000   NOP     
03FC: 0000   NOP     
03FD: 0000   NOP     
03FE: 1FFF   CALL    03FF
03FF: 1F9D   CALL    039D

As you can see, it generates a CALL to address 0x3FE which contains all
ones which is the default value for unused locations, and happens to
translate to "CALL 03FF".

Prior to doing this, they set Bit7 of IO.4 which is the interrupt enable
register, and Bit7 is documented as "reserved".

Following the CALL 03FE they test the accumulator value for 0xFF, and
going in to the call, it is clearly 0x3C - so they expect that this CALL
can modify the accumulator.

I'm wondering if setting IO.4.7 is mapping some special code, perhaps
"RET immediate" into the reserved area in order to retrieve some chip
dependant value, but I have no way to test this. It is also possible
that the progammer automatically programs some calibration value into
this location, however that leads to two questions:

1) What does the ICE do in this case?
2) The obtained value is only used to either 1) continue the startup
   code, or 2) jump directly to the user code bypassing the remainder
   of the startup code, why would the writer be making this decision
   For that matter why would anything not under user control be
   doing this?, it does not appear to be a calibration value as it is
   lost 4 instructions later having not been used.

Could someone with the ICE look into this and see what is happening?

Thanks,
Dave
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #131 on: November 24, 2018, 10:53:05 pm »
Hello DDunfield,

I posted a complete commented disassembly of the init code some posts back in this thread.

If you look in the .INC file of a regular project you can see more IO definitions (e.g. IO 0x0b is called "IHRCR"  which is the InternalHighspeedRC-Register").

IO 0x0B (IHRCR) will hold a "tuning" value to tune the internal high speed oscillator.


The complete init code is used to set a specific value and go up and down commanded by WRITER so it can measure and tuning the oscillator.

At first write WRITER places a "RET 0xFF" at last position of ROM-1 (0x3FE in your case).

So when WRITER starts the IC init code is executed. Then it uses bit bang protocol on PA to get data in (+/-1 of current IHRCR value) and out (checksum of code) and can measure the timing of the process.
When WRITER is done it overwrites the "RET 0xFF" with "RET 0xXY" so all later starts of the IC will not execute the init code at all. Just the defined IHRC value is written to IHRCR.

The overwriting of OTP is possible only when you change '1' bits to '0' so you can change value 0xFF to anything (but not the other way around, 0x00 can not be changed to anything anymore).
The OTP writing just can change '1' bits to '0' permanently.

Have fun,

JS.


Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #132 on: November 26, 2018, 12:56:32 am »
Here is some C++ code that will decode and encode the MCU firmware contained within a PDK file. This operates in-place in memory. Derived from code posted by js_12345678_55AA.

The encoder/decoder...
Code: [Select]
void xcode_pdk_data(TPDKinfo &info, bool encode)
{
    if (info.length & 31) return; // Must be a multiple of 32 words

    uint16_t const x0 = 0x55AA;
    CKey key(info.key);
    uint16_t x1 = key[3] ^ key[14];
    uint16_t x2 = key[7] ^ key[15];
    if ((info.version >= 0x15) && (info.version <= 0x17))
        x1 ^= 0x1234, x2 ^= 0x5678;
    uint16_t t1 = 0, t2 = 0;
    unsigned ki = 0, n = 0;
    uint16_t *d = info.data;

    while (n < info.length) {
        for (unsigned j = 0; j < 4; ++j) {
            if (encode) {
                t1 = *d++ = (*d - key[ki += x1])     ;    key[ n] ^= t1;
                t2 = *d++ = (*d ^ key[ki += t1]) - x2;    key[x2] ^= x1;
                x1 = *d++ = (*d - key[ki ^= t2])     ;    key[x2] ^= x0;
                x2 = *d++ = (*d ^ key[ki = kx(ki, x1)]) + t1;
                t1 = *d++ = (*d ^ key[ki += x2])     ;    key[x1] += x2;
                t2 = *d++ = (*d ^ key[ki ^= t1]) ^ x2;    key[t2] ^= t1;
                x1 = *d++ = (*d - key[ki ^= t2])     ;    key[t1] += t2;
                x2 = *d++ = (*d ^ key[ki += x1]) - t1;
            } else {
                *d++ = ((t1 = *d)     ) + key[ki += x1];   key[ n] ^= t1;
                *d++ = ((t2 = *d) + x2) ^ key[ki += t1];   key[x2] ^= x1;
                *d++ = ((x1 = *d)     ) + key[ki ^= t2];   key[x2] ^= x0;
                *d++ = ((x2 = *d) - t1) ^ key[ki = kx(ki, x1)];
                *d++ = ((t1 = *d)     ) ^ key[ki += x2];   key[x1] += x2;
                *d++ = ((t2 = *d) ^ x2) ^ key[ki ^= t1];   key[t2] ^= t1;
                *d++ = ((x1 = *d)     ) + key[ki ^= t2];   key[t1] += t2;
                *d++ = ((x2 = *d) + t1) ^ key[ki += x1];
            }
            key[1] ^= key[15]; key[2] ^= t1;
            key[3] ^= key[14]; key[4] += t2;
            key[5] ^= key[13]; key[6] += x2;
            key[8] -= x1;
            ki += j;
        }
        n += 32;
    }
}

The other stuff...
Code: [Select]
struct TPDKinfo
{
    unsigned version;
    unsigned length;
    uint16_t *key;
    uint16_t *data;
};

class CKey
{
private:
    uint16_t k[16];
public:
    CKey(uint16_t *_k) { memcpy(k, _k, sizeof(k)); }
    inline uint16_t & operator [] (unsigned const i) { return k[i & 15]; }
};

static inline unsigned kx(unsigned const k, unsigned const i) { return ((k & 0xFFFF) + (i & 0xFFFF)) >> 1; }


/* xcode_pdk_data() goes here */


int get_pdk_info(uint8_t *bd, unsigned len, TPDKinfo &info)
{
    // Note: this will only work on little endian CPUs due to the use of
    //          uint16_t and uint32_t reinterpret casts

    memset(&info, 0, sizeof(info));

    if (len < 256) return -1; // Header too short

    uint16_t *wd = reinterpret_cast<uint16_t *>(bd); // Word (16 bit) data pointer
    uint32_t *ld = reinterpret_cast<uint32_t *>(bd); // Long (32 bit) data pointer

    uint32_t const version = ld[4 >> 1];
    info.version = version;

    uint32_t const datalen = ld[16 >> 1];
    if (datalen & 31) return -2; // Data size is not a multiple of 32
    info.length = datalen;

    uint32_t const extrahdr = wd[0x13] + wd[0x14] + wd[0x16] + wd[0x68] + (version > 0x1C ? wd[0x24] >> 8 : 0);
    if (extrahdr & 1) return -3; // Data is not word aligned

    uint32_t const hdrlen = 256 + extrahdr;
    if (len < hdrlen + (datalen << 1)) return -4; // Not enough data

    info.key = wd + 0x70;
    info.data = reinterpret_cast<uint16_t *>(bd + hdrlen);

    return 0;
}

void decode_fw(uint16_t *d, unsigned len)
{
    uint16_t const o[8] = { 0xAFCD, 0x0055, 0xAA23, 0x0055, 0x3759, 0x0055, 0xAA23, 0x0055 };
    unsigned j = len << 3;
    unsigned i = 0;
    do *d++ ^= o[i & 7] ^ i++ ^ (j -= 8); while (j);
}

int main()
{
    // Read a PDK file into memory
    FILE *f;
    errno_t e = fopen_s(&f, "test.pdk", "rb");
    if (e) return -1;
    uint8_t x[9000];
    unsigned const l = fread(x, 1, sizeof(x), f);
    fclose(f);
    if (!l) return -2;

    // Get info from the header
    TPDKinfo info;
    if (get_pdk_info(x, l, info)) return -3;
    printf("PDK version: %i\nPDK data size: %i words\n", info.version, info.length);

    // Decode it
    xcode_pdk_data(info);

    // Write the decoded file
    e = fopen_s(&f, "test_decode.bin", "wb");
    if (e) return -4;
    fwrite(x, 1, l, f);
    fclose(f);

    // Encode it
    xcode_pdk_data(info, true);

    // Write the encoded file
    e = fopen_s(&f, "test_encode.bin", "wb");
    if (e) return -4;
    fwrite(x, 1, l, f);
    fclose(f);

    return 0;
}
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #133 on: November 26, 2018, 03:42:10 am »
16 bit instruction set encoding used by PMS234

The encoding allows for addressing of up to 64 byte IO, 512 byte RAM and 8192 word program.

EDIT: Added a few instructions that I missed (skipped a page in the manual)

Code: [Select]
0000_0000_0000_0000  nop
0000_0000_0001_0000  addc     a
0000_0000_0001_0001  subc     a
0000_0000_0001_0010  izsn     a
0000_0000_0001_0011  dzsn     a
0000_0000_0001_0111  pcadd    a
0000_0000_0001_1000  not      a
0000_0000_0001_1001  neg      a
0000_0000_0001_1010  sr       a
0000_0000_0001_1011  sl       a
0000_0000_0001_1100  src      a
0000_0000_0001_1101  slc      a
0000_0000_0001_1110  swap     a
0000_0000_0001_1111  delay    a
0000_0000_0011_0000  wdreset
0000_0000_0011_0010  pushaf
0000_0000_0011_0011  popaf
0000_0000_0011_0101  reset
0000_0000_0011_0110  stopsys
0000_0000_0011_0111  stopexe
0000_0000_0011_1000  engint
0000_0000_0011_1001  disgint
0000_0000_0011_1010  ret
0000_0000_0011_1011  reti
0000_0000_10pp_pppp  mov      IO,a
0000_0000_11pp_pppp  mov      a,IO
0000_0001_kkkk_kkkk  cneqsn   a,I
0000_001w_wwww_www0  stt16    word
0000_001w_wwww_www1  ldt16    word
0000_100w_wwww_www0  idxm     index,a
0000_100w_wwww_www1  idxm     a,index
0000_101w_wwww_www0  ldtabl   word
0000_101w_wwww_www1  ldtabh   word
0000_1110_kkkk_kkkk  delay    I
0000_1111_kkkk_kkkk  ret      I
0001_0000_00pp_pppp  xor      IO,a
0001_0000_01pp_pppp  xor      a,IO
0001_011m_mmmm_mmmm  cneqsn   a,M
0001_1000_kkkk_kkkk  add      a,I
0001_1001_kkkk_kkkk  sub      a,I
0001_1010_kkkk_kkkk  ceqsn    a,I
0001_1011_kkkk_kkkk  comp     a,I
0001_1100_kkkk_kkkk  and      a,I
0001_1101_kkkk_kkkk  or       a,I
0001_1110_kkkk_kkkk  xor      a,I
0001_1111_kkkk_kkkk  mov      a,I
0010_000b_bbpp_pppp  t0sn     IO.n
0010_001b_bbpp_pppp  t1sn     IO.n
0010_010b_bbpp_pppp  set0     IO.n
0010_011b_bbpp_pppp  set1     IO.n
0010_100b_bbpp_pppp  tog      IO.n
0010_101b_bbpp_pppp  wait0    IO.n
0010_110b_bbpp_pppp  wait1    IO.n
0010_111b_bbpp_pppp  swapc    IO.n
0011_000m_mmmm_mmmm  nmov     M,a
0011_001m_mmmm_mmmm  nmov     a,M
0011_010m_mmmm_mmmm  nadd     M,a
0011_011m_mmmm_mmmm  nadd     a,M
0011_100m_mmmm_mmmm  ceqsn    M,a
0011_101m_mmmm_mmmm  ceqsn    a,M
0011_110m_mmmm_mmmm  comp     M,a
0011_111m_mmmm_mmmm  comp     a,M
0100_000m_mmmm_mmmm  add      M,a
0100_001m_mmmm_mmmm  add      a,M
0100_011m_mmmm_mmmm  sub      a,M
0100_100m_mmmm_mmmm  addc     M,a
0100_101m_mmmm_mmmm  addc     a,M
0100_010m_mmmm_mmmm  sub      M,a
0100_111m_mmmm_mmmm  subc     a,M
0100_110m_mmmm_mmmm  subc     M,a
0101_000m_mmmm_mmmm  and      M,a
0101_001m_mmmm_mmmm  and      a,M
0101_010m_mmmm_mmmm  or       M,a
0101_011m_mmmm_mmmm  or       a,M
0101_100m_mmmm_mmmm  xor      M,a
0101_101m_mmmm_mmmm  xor      a,M
0101_110m_mmmm_mmmm  mov      M,a
0101_111m_mmmm_mmmm  mov      a,M
0110_000m_mmmm_mmmm  addc     M
0110_001m_mmmm_mmmm  subc     M
0110_010m_mmmm_mmmm  izsn     M
0110_011m_mmmm_mmmm  dzsn     M
0110_100m_mmmm_mmmm  inc      M
0110_101m_mmmm_mmmm  dec      M
0110_110m_mmmm_mmmm  clear    M
0110_111m_mmmm_mmmm  xch      M
0111_000m_mmmm_mmmm  not      M
0111_001m_mmmm_mmmm  neg      M
0111_010m_mmmm_mmmm  sr       M
0111_011m_mmmm_mmmm  sl       M
0111_100m_mmmm_mmmm  src      M
0111_101m_mmmm_mmmm  slc      M
0111_110m_mmmm_mmmm  swap     M
0111_111m_mmmm_mmmm  delay    M
1000_bbbm_mmmm_mmmm  t0sn     M.n
1001_bbbm_mmmm_mmmm  t1sn     M.n
1010_bbbm_mmmm_mmmm  set0     M.n
1011_bbbm_mmmm_mmmm  set1     M.n
110a_aaaa_aaaa_aaaa  goto     label
111a_aaaa_aaaa_aaaa  call     label
« Last Edit: November 26, 2018, 07:55:12 am by oPossum »
 
The following users thanked this post: js_12345678_55AA

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #134 on: November 26, 2018, 04:02:00 am »
16 bit instruction set encoding used by PMS234

...

Code: [Select]
0000_0000_0001_1111  delay    a
...

Maybe delay instruction is also available in 14 bit ? There is an empty space in opcode list there...

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #135 on: November 26, 2018, 05:05:56 am »
PMS234 startup code

Code: [Select]
000  C002  goto    0x002
001  C049  goto    0x049
002  1F00  mov     a,0x00
003  0082  mov     SP,a
004  1F00  mov     a,0x00
005  008B  mov     IHRCR,a
006  EFFD  call    0x3FD
007  00B8  mov     A_IHRC,a
008  1F3C  mov     a,0x3C
009  0083  mov     CLKCMD,a
00A  1F0F  mov     a,0x0F
00B  5C01  mov     M001,a
00C  1FFE  mov     a,0xFE
00D  5C00  mov     M000,a
00E  0A00  ldtabl  M000
00F  1AFF  ceqsn   a,0xFF
010  C040  goto    0x040
011  2791  set1    PAC.6
012  6C01  clear   M001
013  1F20  mov     a,0x20
014  5C00  mov     M000,a
015  2D10  wait1   PA.4
016  2790  set1    PA.6
017  001F  delay   a
018  6600  dzsn    M000
019  C017  goto    0x017
01A  2590  set0    PA.6
01B  2210  t1sn    PA.0
01C  C03C  goto    0x03C
01D  1FA4  mov     a,0xA4
01E  00A0  mov     ADCC,a
01F  1F84  mov     a,0x84
020  00A1  mov     ADCM,a
021  1F80  mov     a,0x80
022  5C00  mov     M000,a
023  5E00  mov     a,M000
024  00B9  mov     BGTR,a
025  27A0  set1    ADCC.6
026  2DA0  wait1   ADCC.6
027  27A0  set1    ADCC.6
028  2DA0  wait1   ADCC.6
029  00E2  mov     a,ADCRH
02A  5C01  mov     M001,a
02B  00E3  mov     a,ADCRL
02C  2CD0  wait1   PA.3
02D  001B  sl      a
02E  7A01  slc     M001
02F  2F90  swapc   PA.6
030  2AD0  wait0   PA.3
031  2010  t0sn    PA.0
032  C02C  goto    0x02C
033  2150  t0sn    PA.5
034  C025  goto    0x025
035  1FBC  mov     a,0xBC
036  00A0  mov     ADCC,a
037  21D0  t0sn    PA.7
038  6800  inc     M000
039  23D0  t1sn    PA.7
03A  6A00  dec     M000
03B  C023  goto    0x023
03C  6801  inc     M001
03D  5E01  mov     a,M001
03E  008B  mov     IHRCR,a
03F  C013  goto    0x013
040  008B  mov     IHRCR,a
041  0A01  ldtabh  M000
042  00B9  mov     BGTR,a

; FPPA0 User Code
043  1F00  mov     a,0x00
044  0082  mov     SP,a
045  0030  wdreset
046  0E64  delay   0x64
047  2810  tog     PA.0
048  C045  goto    0x045

; FPPA1 User Code
049  1F04  mov     a,0x04
04A  0082  mov     SP,a
04B  0EC8  delay   0xC8
04C  2850  tog     PA.1
04D  C04B  goto    0x04B
« Last Edit: November 26, 2018, 07:53:04 am by oPossum »
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #136 on: November 26, 2018, 06:54:15 am »
I think it might be better to refer to the opcodes by their symbol than their bitsize or the device
Which apparently can be different for IDE and ICE and can also be redefined in the same file (PMS150.INC for example)
The symbol files are probably also the reason why the ICE cannot assemble certain instructions and outputs NOPs instead (but probably also enables TRAP)
Unfortunately they are somewhat binary.

./PMS132.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PDK22C13.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./PMC131.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./XN1210.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC234.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PES502C.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS134.INC
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_86A
./PDK22C58A.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./PMS132B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./P201CS16A.INC
.Assembly   INSTRUMENT   SYM_83A
./PMS271.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMS150B.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PFS154.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PDK82S_EV.INC
.Assembly   INSTRUMENT   SYM_82A
./PDK82C12.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./P234C.INC
.Assembly   INSTRUMENT   SYM_83A
./P232CS20.INC
.Assembly   INSTRUMENT   SYM_83A
./PMS234.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PFC154.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC156.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PMC882.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./PDK82C13.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./XN1320B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS232.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMS154C.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./P232C.INC
.Assembly   INSTRUMENT   SYM_83A
./PMS131.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PMS155C.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC251.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMC150.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PMS154.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS156.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PES502D.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC166.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./ip5dB.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PES503.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMS155.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PDK3S_EV.INC
.Assembly   INSTRUMENT   SYM_83A
./P234CS24.INC
.Assembly   INSTRUMENT   SYM_83A
./PMS130.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PDK22C58.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./PMS171.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS171B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./MCU371.INC
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_86A
./PMR210.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_86A
./PMS165C.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS153.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PES501.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PDK_EV5.INC
.Assembly   INSTRUMENT   SYM_86A
./XN1210B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC884.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMC232.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMS152.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS150C.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_86A
./PMS164.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PDK22C13A.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./ip5dC.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_86A
./PMS132K.INC
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_86A
./XN1320D.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS133.INC
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_86A
./XN1210D.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS154B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC153.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PFS173.INC
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_86A
./XN1210C.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC271.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./P201CS14A.INC
.Assembly   INSTRUMENT   SYM_83A
./PMS150.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PMS155B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PES502.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
 
The following users thanked this post: oPossum

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #137 on: November 26, 2018, 07:48:12 am »
A comparison of the 13, 14, and 16 bit instruction sets.

Code: [Select]
add      a,I        1_0000_kkkk_kkkk    10_1000_kkkk_kkkk    0001_1000_kkkk_kkkk
add      a,M        0_0110_00mm_mmmm    00_1100_0mmm_mmmm    0100_001m_mmmm_mmmm
add      M,a        0_0100_00mm_mmmm    00_1000_0mmm_mmmm    0100_000m_mmmm_mmmm
addc     a          0_0000_0001_0000    00_0000_0110_0000    0000_0000_0001_0000
addc     a,M        0_0110_10mm_mmmm    00_1101_0mmm_mmmm    0100_101m_mmmm_mmmm
addc     M                              01_0000_0mmm_mmmm    0110_000m_mmmm_mmmm
addc     M,a        0_0100_10mm_mmmm    00_1001_0mmm_mmmm    0100_100m_mmmm_mmmm
and      a,I        1_0100_kkkk_kkkk    10_1100_kkkk_kkkk    0001_1100_kkkk_kkkk
and      a,M        0_0111_00mm_mmmm    00_1110_0mmm_mmmm    0101_001m_mmmm_mmmm
and      M,a        0_0101_00mm_mmmm    00_1010_0mmm_mmmm    0101_000m_mmmm_mmmm
call     label      1_11aa_aaaa_aaaa    11_1aaa_aaaa_aaaa    111a_aaaa_aaaa_aaaa
ceqsn    a,I        1_0010_kkkk_kkkk    10_1010_kkkk_kkkk    0001_1010_kkkk_kkkk
ceqsn    a,M        0_1011_10mm_mmmm    01_0111_0mmm_mmmm    0011_101m_mmmm_mmmm
ceqsn    M,a                                                 0011_100m_mmmm_mmmm
clear    M          0_1001_10mm_mmmm    01_0011_0mmm_mmmm    0110_110m_mmmm_mmmm
cneqsn   a,I                            10_1011_kkkk_kkkk    0000_0001_kkkk_kkkk
cneqsn   a,M                            01_0111_1mmm_mmmm    0001_011m_mmmm_mmmm
comp     a,I                                                 0001_1011_kkkk_kkkk
comp     a,M                            00_0110_0mmm_mmmm    0011_111m_mmmm_mmmm
comp     M,a                            00_0110_1mmm_mmmm    0011_110m_mmmm_mmmm
dec      M          0_1001_01mm_mmmm    01_0010_1mmm_mmmm    0110_101m_mmmm_mmmm
delay    a                                                   0000_0000_0001_1111
delay    I                                                   0000_1110_kkkk_kkkk
delay    M                                                   0111_111m_mmmm_mmmm
disgint             0_0000_0011_1001    00_0000_0111_1001    0000_0000_0011_1001
dzsn     a          0_0000_0001_0011    00_0000_0110_0011    0000_0000_0001_0011
dzsn     M          0_1000_11mm_mmmm    01_0001_1mmm_mmmm    0110_011m_mmmm_mmmm
engint              0_0000_0011_1000    00_0000_0111_1000    0000_0000_0011_1000
goto     label      1_10aa_aaaa_aaaa    11_0aaa_aaaa_aaaa    110a_aaaa_aaaa_aaaa
idxm     a,index    0_0000_111w_www1    00_0011_1www_www1    0000_100w_wwww_www1
idxm     index,a    0_0000_111w_www0    00_0011_1www_www0    0000_100w_wwww_www0
inc      M          0_1001_00mm_mmmm    01_0010_0mmm_mmmm    0110_100m_mmmm_mmmm
izsn     a          0_0000_0001_0010    00_0000_0110_0010    0000_0000_0001_0010
izsn     M          0_1000_10mm_mmmm    01_0001_0mmm_mmmm    0110_010m_mmmm_mmmm
ldspth                                  00_0000_0000_0111
ldsptl                                  00_0000_0000_0110
ldt16    word       0_0000_110w_www1    00_0011_0www_www1    0000_001w_wwww_www1
ldtabh   word                                                0000_101w_wwww_www1
ldtabl   word                                                0000_101w_wwww_www0
mov      a,I        1_0111_kkkk_kkkk    10_1111_kkkk_kkkk    0001_1111_kkkk_kkkk
mov      a,IO       0_0000_101p_pppp    00_0001_11pp_pppp    0000_0000_11pp_pppp
mov      a,M        0_0111_11mm_mmmm    00_1111_1mmm_mmmm    0101_111m_mmmm_mmmm
mov      IO,a       0_0000_100p_pppp    00_0001_10pp_pppp    0000_0000_10pp_pppp
mov      M,a        0_0101_11mm_mmmm    00_1011_1mmm_mmmm    0101_110m_mmmm_mmmm
mul                                     00_0000_0111_1100
nadd     a,M                            00_0111_0mmm_mmmm    0011_011m_mmmm_mmmm
nadd     M,a                            00_0111_1mmm_mmmm    0011_010m_mmmm_mmmm
neg      a          0_0000_0001_1001    00_0000_0110_1001    0000_0000_0001_1001
neg      M          0_1010_01mm_mmmm    01_0100_1mmm_mmmm    0111_001m_mmmm_mmmm
nmov     a,M                                                 0011_001m_mmmm_mmmm
nmov     M,a                                                 0011_000m_mmmm_mmmm
nop                 0_0000_0000_0000    00_0000_0000_0000    0000_0000_0000_0000
not      a          0_0000_0001_1000    00_0000_0110_1000    0000_0000_0001_1000
not      M          0_1010_00mm_mmmm    01_0100_0mmm_mmmm    0111_000m_mmmm_mmmm
or       a,I        1_0101_kkkk_kkkk    10_1101_kkkk_kkkk    0001_1101_kkkk_kkkk
or       a,M        0_0111_01mm_mmmm    00_1110_1mmm_mmmm    0101_011m_mmmm_mmmm
or       M,a        0_0101_01mm_mmmm    00_1010_1mmm_mmmm    0101_010m_mmmm_mmmm
pcadd    a          0_0000_0001_0111    00_0000_0110_0111    0000_0000_0001_0111
popaf               0_0000_0011_0011    00_0000_0111_0011    0000_0000_0011_0011
pushaf              0_0000_0011_0010    00_0000_0111_0010    0000_0000_0011_0010
reset               0_0000_0011_0101    00_0000_0111_0101    0000_0000_0011_0101
ret                 0_0000_0011_1010    00_0000_0111_1010    0000_0000_0011_1010
ret      I          0_0001_kkkk_kkkk    00_0010_kkkk_kkkk    0000_1111_kkkk_kkkk
reti                0_0000_0011_1011    00_0000_0111_1011    0000_0000_0011_1011
set0     IO.n       0_1110_bbbp_pppp    01_110b_bbpp_pppp    0010_010b_bbpp_pppp
set0     M.n        0_0011_bbb0_mmmm    10_010b_bbmm_mmmm    1010_bbbm_mmmm_mmmm
set1     IO.n       0_1111_bbbp_pppp    01_111b_bbpp_pppp    0010_011b_bbpp_pppp
set1     M.n        0_0011_bbb1_mmmm    10_011b_bbmm_mmmm    1011_bbbm_mmmm_mmmm
sl       a          0_0000_0001_1011    00_0000_0110_1011    0000_0000_0001_1011
sl       M          0_1010_11mm_mmmm    01_0101_1mmm_mmmm    0111_011m_mmmm_mmmm
slc      a          0_0000_0001_1101    00_0000_0110_1101    0000_0000_0001_1101
slc      M          0_1011_01mm_mmmm    01_0110_1mmm_mmmm    0111_101m_mmmm_mmmm
sr       a          0_0000_0001_1010    00_0000_0110_1010    0000_0000_0001_1010
sr       M          0_1010_10mm_mmmm    01_0101_0mmm_mmmm    0111_010m_mmmm_mmmm
src      a          0_0000_0001_1100    00_0000_0110_1100    0000_0000_0001_1100
src      M          0_1011_00mm_mmmm    01_0110_0mmm_mmmm    0111_100m_mmmm_mmmm
stopexe             0_0000_0011_0111    00_0000_0111_0111    0000_0000_0011_0111
stopsys             0_0000_0011_0110    00_0000_0111_0110    0000_0000_0011_0110
stt16    word       0_0000_110w_www0    00_0011_0www_www0    0000_001w_wwww_www0
sub      a,I        1_0001_kkkk_kkkk    10_1001_kkkk_kkkk    0001_1001_kkkk_kkkk
sub      a,M        0_0110_01mm_mmmm    00_1100_1mmm_mmmm    0100_011m_mmmm_mmmm
sub      M,a        0_0100_01mm_mmmm    00_1000_1mmm_mmmm    0100_010m_mmmm_mmmm
subc     a          0_0000_0001_0001    00_0000_0110_0001    0000_0000_0001_0001
subc     a,M        0_0110_11mm_mmmm    00_1101_1mmm_mmmm    0100_111m_mmmm_mmmm
subc     M                              01_0000_1mmm_mmmm    0110_001m_mmmm_mmmm
subc     M,a        0_0100_11mm_mmmm    00_1001_1mmm_mmmm    0100_110m_mmmm_mmmm
swap     a          0_0000_0001_1110    00_0000_0110_1110    0000_0000_0001_1110
swap     M                                                   0111_110m_mmmm_mmmm
swapc    IO.n                           00_010b_bbpp_pppp    0010_111b_bbpp_pppp
t0sn     IO.n       0_1100_bbbp_pppp    01_100b_bbpp_pppp    0010_000b_bbpp_pppp
t0sn     M.n        0_0010_bbb0_mmmm    10_000b_bbmm_mmmm    1000_bbbm_mmmm_mmmm
t1sn     IO.n       0_1101_bbbp_pppp    01_101b_bbpp_pppp    0010_001b_bbpp_pppp
t1sn     M.n        0_0010_bbb1_mmmm    10_001b_bbmm_mmmm    1001_bbbm_mmmm_mmmm
tog      IO.n                                                0010_100b_bbpp_pppp
wait0    IO.n                                                0010_101b_bbpp_pppp
wait1    IO.n                                                0010_110b_bbpp_pppp
wdreset             0_0000_0011_0000    00_0000_0111_0000    0000_0000_0011_0000
xch      M          0_1001_11mm_mmmm    01_0011_1mmm_mmmm    0110_111m_mmmm_mmmm
xor      a,I        1_0110_kkkk_kkkk    10_1110_kkkk_kkkk    0001_1110_kkkk_kkkk
xor      a,IO                                                0001_0000_01pp_pppp
xor      a,M        0_0111_10mm_mmmm    00_1111_0mmm_mmmm    0101_101m_mmmm_mmmm
xor      IO,a       0_0000_011p_pppp    00_0000_11pp_pppp    0001_0000_00pp_pppp
xor      M,a        0_0101_10mm_mmmm    00_1011_0mmm_mmmm    0101_100m_mmmm_mmmm

« Last Edit: November 26, 2018, 08:51:52 am by oPossum »
 

Offline amyk

  • Super Contributor
  • ***
  • Posts: 5925
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #138 on: November 26, 2018, 01:15:08 pm »
No immediately discernable obvious systema to the opcode layout besides the fixed position of the address/data fields --- I'd be really curious to see a decap of these MCUs, because the randomness of the assignment means they're probably implemented directly with a PLA and no microcode nor field-specific decoding.
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #139 on: November 26, 2018, 08:46:30 pm »
A comparison of the 13, 14, and 16 bit instruction sets.
[…]

You seem to be missing  few instructions in the 16-bit instruction set. In particular, I noticed pushw word, popw word, pushw pcN, popw pcN.

Philipp
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #140 on: November 26, 2018, 09:01:28 pm »
What chip has those instructions? I used the PMC234 as a reference and it does not have them.
 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 11686
  • Country: gb
    • Mike's Electric Stuff
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #141 on: November 26, 2018, 09:09:12 pm »
No immediately discernable obvious systema to the opcode layout besides the fixed position of the address/data fields --- I'd be really curious to see a decap of these MCUs, because the randomness of the assignment means they're probably implemented directly with a PLA and no microcode nor field-specific decoding.
Ken Sherriff just did a teardown and decap of a flame lamp that uses a 16-pin unmarked MCU, which may or may not be a PADUK chip. Unfortunately no schematic to compare pinouts

https://electronupdate.blogspot.com/
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #142 on: November 26, 2018, 09:24:32 pm »
What chip has those instructions? I used the PMC234 as a reference and it does not have them.

I am not sure in general, but so far all the 8-core dveices that I read datasheets of have them, while the 2-core devices don't.

Philipp
 
The following users thanked this post: oPossum

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #143 on: November 26, 2018, 10:08:35 pm »
.CHIP PDK82S_EV made more opcodes acceptable to the assembler

Code: [Select]
0x0400  popw   word
0x0401  pushw  word
0x0060  popw   pcN
0x0070  pushw  pcN
0x003C  mul

Looking for ideas on how to get the opcodes for 13 and 16 bit ldsptl/ldspth
 
The following users thanked this post: DocBen

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #144 on: November 26, 2018, 10:21:20 pm »
pushw/popw pcN use 4 bits for the core number :)
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #145 on: November 26, 2018, 11:06:16 pm »
.CHIP PDK82S_EV made more opcodes acceptable to the assembler

Code: [Select]
0x0400  popw   word
0x0401  pushw  word
0x0060  popw   pcN
0x0070  pushw  pcN
0x003C  mul

Looking for ideas on how to get the opcodes for 13 and 16 bit ldsptl/ldspth


There should also be instructions
IGOTO
ICALL
and
PMODE

The best idea I have is to look at the Symbol Files but if they encode the Opcodes as well as the mnemonics it seems to be in different places
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #146 on: November 26, 2018, 11:23:39 pm »
Code: [Select]
0x0040  pmode   n
0x0600  igoto   word
0x0601  icall   word

Not many gaps remaining in the 16 bit instruction set
 
The following users thanked this post: DocBen

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #147 on: November 26, 2018, 11:45:52 pm »
Code: [Select]
0x0040  pmode   n
0x0600  igoto   word
0x0601  icall   word

Not many gaps remaining in the 16 bit instruction set


True, although I would consider calling this PDK_SYM_82A instruction set.

Could you also point out what chips you used for the other instruction sets?

If I counted correctly there are only these instruction set families
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
.Assembly   INSTRUMENT   SYM_82A
.Assembly   INSTRUMENT   SYM_83A
.Assembly   INSTRUMENT   SYM_86A

I suspect that INSTRUMENT means same for ASM and ICE
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #148 on: November 27, 2018, 12:04:29 am »
I have a startup file for the pfs154 that doesnt dissasemble correctly using the current sets, I suspect that 85A is still different from the others
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #149 on: November 27, 2018, 12:54:51 am »
I started to create simple demo projects for PADAUK IDE:

- simple blink in mini-C
- simple blink in ASM embedded in mini-C
- simple blink in pure ASM
- timer based blink using interrupt

https://github.com/free-pdk/simple-pdk-code-examples

If you have analyzed some special functions please try to create a simple demo project just describing / using this function.
This will come handy for regression testing emulation.

To research:
 - watchdog
 - edge triggered interrupts for PA/PB
 - timer source PA/PB pin change
 - stopsys / stopexe and wakeup interrupt
 - adc
 - multicore
 - ...

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 
The following users thanked this post: oPossum

Offline DDunfield

  • Contributor
  • Posts: 32
  • Country: ca
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #150 on: November 27, 2018, 06:56:58 am »
In case anyone else wants to fool with it, I've made my *very Quick and Dirty*/preliminary simulator for the PMC150/PMS150 available on a google drive at the following link:

https://drive.google.com/open?id=1iNK7dmASzDRcld0SGHDq_lqcMhntBvrv

Before you bother downloading it, take note:

Most of you won't like it - the main reason being that I tend to prototype software things with the tools that I am most familiar with and in this case I built it with a compiler I wrote back in the 80's, which builds DOS executables. That means you need a DOS compatible environment. For most modern 64-bit systems, DOSBOX works well, and is available for Windows/Linux/Mac/Android etc. (yeah, I can run PSM150 code on my phone!) - for Windows, I recommend the DOSBOX that I have posted under "DOS wigets" on my site (www.dunfield.com).

It is a very preliminary prototype. It is not optimized in any way.

It does not yet simulate any of the on-chip hardware (timer, interrupts etc). At this time this is for fooling with the instruction set only.

I've confirmed that it understands all the instructions listed in the PMC150/PMS150 manual, however I have not exhaustively tested them. I do not have the Paudak ICE or programmer, so I cannot easily verify the operation of the actual CPU (implementation is a combination of guesswork and "as documented" in the Paudak data sheet). There are most certainly bugs. I will update the simulator as these are found/reported. Please contact me as 'DDunfield' on the EEVBLOG forums.

Refer to the QDS150.TXT file included in the above archive for more information.

Dave
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #151 on: November 27, 2018, 09:20:39 am »
Hi,

I just created a repository on github containing new tools and source code for PDK FPPA controller:

https://github.com/free-pdk/fppa-pdk-tools

depdk : deobfuscate PDK file to binary format
dispdk : disassemble PDK file (the 14 bit instruction set disassembler is already working, only mapped processors are PMx154 variants)
emupdk: simulates PDK (PMx154 is implemented and mapped)

I spent quite some time with the flag solver for OV, AC, CF, ZF. But it is easy to reuse now for all other processor types.
Basic testing was done with most ALU operations so it's looking good.

-> adapting disassembler for 13/16 bit is a simple task
-> adapting emulator for 13 bit should be straight forward, 16 bit needs some understanding of new opcodes

I will focus on interrupt / peripheral emulation and GUI (ncurses).

So if anybody wants to assist, 13/16 bit needs implementation.


JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #152 on: November 28, 2018, 05:20:05 am »
Code: [Select]
0x0040  pmode   n
0x0600  igoto   word
0x0601  icall   word

Not many gaps remaining in the 16 bit instruction set


True, although I would consider calling this PDK_SYM_82A instruction set.

Could you also point out what chips you used for the other instruction sets?

If I counted correctly there are only these instruction set families
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
.Assembly   INSTRUMENT   SYM_82A
.Assembly   INSTRUMENT   SYM_83A
.Assembly   INSTRUMENT   SYM_86A

I suspect that INSTRUMENT means same for ASM and ICE

Chips settings I have used...

13 bit:  PMS150C
14 bit:  PFS154
16 bit:  PMS234  PMC882  PMC884  PDK82C12  PDK82C13  PDK82S_EV

I think the SYM_8xx designations refer to subsets of the full instruction set that run on specific hardware revs.
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #153 on: November 28, 2018, 05:22:55 am »
I have a startup file for the pfs154 that doesnt dissasemble correctly using the current sets, I suspect that 85A is still different from the others

Looks like the same 14 bit instruction set to me. What differences did you notice?

Test program
Code: [Select]
.CHIP PFS154
//{{PADAUK_CODE_OPTION
.Code_Option LVR 2.5V
.Code_Option Security Enable // Security 7/8 words Enable
.Code_Option Comparator_Edge All_Edge
.Code_Option LCD2 Disable // At ICE, LCD always disable, PB0 PA0/3/4 are independent pins
.Code_Option Bootup_Time Fast
.Code_Option Drive Normal
//}}PADAUK_CODE_OPTION

goto FPPA0

WORD Stack_FPPA0 [2]

FPPA0:
.ADJUST_IC SYSCLK=IHRC/8, IHRC=16MHz, VDD=5V

SP = Stack_FPPA0;

@@:
wdreset
nop
goto @B

Disassembly
Code: [Select]
000  3001  goto    0x001
001  2F00  mov     a,0x00
002  0182  mov     SP,a
003  3FED  call    0x7ED
004  018B  mov     IHRCR,a
005  3FEE  call    0x7EE
006  019A  mov     BGTR,a
007  2F80  mov     a,0x80
008  019B  mov     MISC_LVR,a
009  2F3C  mov     a,0x3C
00A  0183  mov     CLKCMD,a
00B  3FFE  call    0x7FE
00C  2AFF  ceqsn   a,0xFF
00D  3054  goto    0x054
00E  3FED  call    0x7ED
00F  0B81  mov     M01,a
010  1F91  set1    PAC.6
011  2F09  mov     a,0x09
012  0B80  mov     M00,a
013  1AD0  t1sn    PA.3
014  3013  goto    0x013
015  1F90  set1    PA.6
016  0063  dzsn    a
017  3016  goto    0x016
018  1180  dzsn    M00
019  3016  goto    0x016
01A  1D90  set0    PA.6
01B  18D0  t0sn    PA.3
01C  301B  goto    0x01B
01D  2F01  mov     a,0x01
01E  1950  t0sn    PA.5
01F  2FFF  mov     a,0xFF
020  0C01  add     a,M01
021  018B  mov     IHRCR,a
022  0B81  mov     M01,a
023  1AD0  t1sn    PA.3
024  3023  goto    0x023
025  1B50  t1sn    PA.5
026  304F  goto    0x04F
027  2F04  mov     a,0x04
028  0188  mov     MISC,a
029  18D0  t0sn    PA.3
02A  3029  goto    0x029
02B  2F02  mov     a,0x02
02C  0182  mov     SP,a
02D  1304  clear   M04
02E  1305  clear   M05
02F  2F59  mov     a,0x59
030  0B82  mov     M02,a
031  2F00  mov     a,0x00
032  0B83  mov     M03,a
033  0006  ldsptl
034  0B04  xor     M04,a
035  0007  ldspth
036  0805  add     M05,a
037  1584  sl      M04
038  1685  slc     M05
039  1004  addc    M04
03A  1282  dec     M02
03B  1083  subc    M03
03C  1A40  t1sn    FLAG.1
03D  3033  goto    0x033
03E  1F90  set1    PA.6
03F  1AD0  t1sn    PA.3
040  303F  goto    0x03F
041  1584  sl      M04
042  1685  slc     M05
043  0590  swapc   PA.6
044  18D0  t0sn    PA.3
045  3044  goto    0x044
046  1950  t0sn    PA.5
047  303F  goto    0x03F
048  1D90  set0    PA.6
049  1AD0  t1sn    PA.3
04A  3049  goto    0x049
04B  18D0  t0sn    PA.3
04C  304B  goto    0x04B
04D  1B50  t1sn    PA.5
04E  302B  goto    0x02B
04F  18D0  t0sn    PA.3
050  304F  goto    0x04F
051  1B50  t1sn    PA.5
052  3011  goto    0x011
053  3053  goto    0x053
054  018B  mov     IHRCR,a
055  2F00  mov     a,0x00
056  0182  mov     SP,a
057  0070  wdreset
058  0000  nop
059  3057  goto    0x057
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #154 on: November 28, 2018, 05:51:18 am »
Updated instruction set encodings. Sorted by opcode. All gaps indicated.

16 bit
Code: [Select]
0x0000  0000_0000_0000_0000  nop
0x0001  0000_0000_0000_0001
0x0002  0000_0000_0000_0010
0x0003  0000_0000_0000_0011
0x0004  0000_0000_0000_0100
0x0005  0000_0000_0000_0101
0x0006  0000_0000_0000_0110
0x0007  0000_0000_0000_0111
0x0008  0000_0000_0000_1000
0x0009  0000_0000_0000_1001
0x000A  0000_0000_0000_1010
0x000B  0000_0000_0000_1011
0x000C  0000_0000_0000_1100
0x000D  0000_0000_0000_1101
0x000E  0000_0000_0000_1110
0x000F  0000_0000_0000_1111
0x0010  0000_0000_0001_0000  addc     a
0x0011  0000_0000_0001_0001  subc     a
0x0012  0000_0000_0001_0010  izsn     a
0x0013  0000_0000_0001_0011  dzsn     a
0x0014  0000_0000_0001_0100
0x0015  0000_0000_0001_0101
0x0016  0000_0000_0001_0110
0x0017  0000_0000_0001_0111  pcadd    a
0x0018  0000_0000_0001_1000  not      a
0x0019  0000_0000_0001_1001  neg      a
0x001A  0000_0000_0001_1010  sr       a
0x001B  0000_0000_0001_1011  sl       a
0x001C  0000_0000_0001_1100  src      a
0x001D  0000_0000_0001_1101  slc      a
0x001E  0000_0000_0001_1110  swap     a
0x001F  0000_0000_0001_1111  delay    a
0x0020  0000_0000_0010_----
0x0030  0000_0000_0011_0000  wdreset
0x0031  0000_0000_0011_0001
0x0032  0000_0000_0011_0010  pushaf
0x0033  0000_0000_0011_0011  popaf
0x0034  0000_0000_0011_0100
0x0035  0000_0000_0011_0101  reset
0x0036  0000_0000_0011_0110  stopsys
0x0037  0000_0000_0011_0111  stopexe
0x0038  0000_0000_0011_1000  engint
0x0039  0000_0000_0011_1001  disgint
0x003A  0000_0000_0011_1010  ret
0x003B  0000_0000_0011_1011  reti
0x003C  0000_0000_0011_1100  mul
0x003D  0000_0000_0011_1101
0x003E  0000_0000_0011_1110
0x003F  0000_0000_0011_1111
0x0040  0000_0000_010k_kkkk  pmode    n
0x0060  0000_0000_0110_tttt  popw     pcN
0x0070  0000_0000_0111_tttt  pushw    pcN
0x0080  0000_0000_10pp_pppp  mov      IO,a
0x00C0  0000_0000_11pp_pppp  mov      a,IO
0x0100  0000_0001_kkkk_kkkk  cneqsn   a,I
0x0200  0000_001w_wwww_www0  stt16    word
0x0201  0000_001w_wwww_www1  ldt16    word
0x0400  0000_010w_wwww_www0  popw     word
0x0401  0000_010w_wwww_www1  pushw    word
0x0600  0000_011w_wwww_www0  igoto    word
0x0601  0000_011w_wwww_www1  icall    word
0x0800  0000_100w_wwww_www0  idxm     index,a
0x0801  0000_100w_wwww_www1  idxm     a,index
0x0A00  0000_101w_wwww_www0  ldtabl   word
0x0A01  0000_101w_wwww_www1  ldtabh   word
0x0C00  0000_110-_----_----
0x0E00  0000_1110_kkkk_kkkk  delay    I
0x0F00  0000_1111_kkkk_kkkk  ret      I
0x1000  0001_0000_00pp_pppp  xor      IO,a
0x1040  0001_0000_01pp_pppp  xor      a,IO
0x1080  0001_0000_1---_----
0x1100 0001_0001_----_----
0x1200 0001_001-_----_----
0x1400 0001_010m_mmmm_mmmm  cneqsn   M,a
0x1600  0001_011m_mmmm_mmmm  cneqsn   a,M
0x1800  0001_1000_kkkk_kkkk  add      a,I
0x1900  0001_1001_kkkk_kkkk  sub      a,I
0x1A00  0001_1010_kkkk_kkkk  ceqsn    a,I
0x1B00  0001_1011_kkkk_kkkk  comp     a,I
0x1C00  0001_1100_kkkk_kkkk  and      a,I
0x1D00  0001_1101_kkkk_kkkk  or       a,I
0x1E00  0001_1110_kkkk_kkkk  xor      a,I
0x1F00  0001_1111_kkkk_kkkk  mov      a,I
0x2000  0010_000b_bbpp_pppp  t0sn     IO.n
0x2200  0010_001b_bbpp_pppp  t1sn     IO.n
0x2400  0010_010b_bbpp_pppp  set0     IO.n
0x2600  0010_011b_bbpp_pppp  set1     IO.n
0x2800  0010_100b_bbpp_pppp  tog      IO.n
0x2A00  0010_101b_bbpp_pppp  wait0    IO.n
0x2C00  0010_110b_bbpp_pppp  wait1    IO.n
0x2E00  0010_111b_bbpp_pppp  swapc    IO.n
0x3000  0011_000m_mmmm_mmmm  nmov     M,a
0x3200  0011_001m_mmmm_mmmm  nmov     a,M
0x3400  0011_010m_mmmm_mmmm  nadd     M,a
0x3600  0011_011m_mmmm_mmmm  nadd     a,M
0x3800  0011_100m_mmmm_mmmm  ceqsn    M,a
0x3A00  0011_101m_mmmm_mmmm  ceqsn    a,M
0x3C00  0011_110m_mmmm_mmmm  comp     M,a
0x3E00  0011_111m_mmmm_mmmm  comp     a,M
0x4000  0100_000m_mmmm_mmmm  add      M,a
0x4200  0100_001m_mmmm_mmmm  add      a,M
0x4400  0100_010m_mmmm_mmmm  sub      M,a
0x4600  0100_011m_mmmm_mmmm  sub      a,M
0x4800  0100_100m_mmmm_mmmm  addc     M,a
0x4A00  0100_101m_mmmm_mmmm  addc     a,M
0x4C00  0100_110m_mmmm_mmmm  subc     M,a
0x4E00  0100_111m_mmmm_mmmm  subc     a,M
0x5000  0101_000m_mmmm_mmmm  and      M,a
0x5200  0101_001m_mmmm_mmmm  and      a,M
0x5400  0101_010m_mmmm_mmmm  or       M,a
0x5600  0101_011m_mmmm_mmmm  or       a,M
0x5800  0101_100m_mmmm_mmmm  xor      M,a
0x5A00  0101_101m_mmmm_mmmm  xor      a,M
0x5C00  0101_110m_mmmm_mmmm  mov      M,a
0x5E00  0101_111m_mmmm_mmmm  mov      a,M
0x6000  0110_000m_mmmm_mmmm  addc     M
0x6200  0110_001m_mmmm_mmmm  subc     M
0x6400  0110_010m_mmmm_mmmm  izsn     M
0x6600  0110_011m_mmmm_mmmm  dzsn     M
0x6800  0110_100m_mmmm_mmmm  inc      M
0x6A00  0110_101m_mmmm_mmmm  dec      M
0x6C00  0110_110m_mmmm_mmmm  clear    M
0x6E00  0110_111m_mmmm_mmmm  xch      M
0x7000  0111_000m_mmmm_mmmm  not      M
0x7200  0111_001m_mmmm_mmmm  neg      M
0x7400  0111_010m_mmmm_mmmm  sr       M
0x7600  0111_011m_mmmm_mmmm  sl       M
0x7800  0111_100m_mmmm_mmmm  src      M
0x7A00  0111_101m_mmmm_mmmm  slc      M
0x7C00  0111_110m_mmmm_mmmm  swap     M
0x7E00  0111_111m_mmmm_mmmm  delay    M
0x8000  1000_bbbm_mmmm_mmmm  t0sn     M.n
0x9000  1001_bbbm_mmmm_mmmm  t1sn     M.n
0xA000  1010_bbbm_mmmm_mmmm  set0     M.n
0xB000  1011_bbbm_mmmm_mmmm  set1     M.n
0xC000  110a_aaaa_aaaa_aaaa  goto     label
0xE000  111a_aaaa_aaaa_aaaa  call     label


14 bit
Code: [Select]
0x0000  00_0000_0000_0000   nop
0x0001  00_0000_0000_0001
0x0002  00_0000_0000_0010
0x0003  00_0000_0000_0011
0x0004  00_0000_0000_0100
0x0005  00_0000_0000_0101
0x0006  00_0000_0000_0110   ldsptl         
0x0007  00_0000_0000_0111   ldspth         
0x0008  00_0000_0000_1---
0x0010  00_0000_0001_----
0x0020  00_0000_001-_----
0x0040  00_0000_010-_----
0x0060  00_0000_0110_0000   addc    a       
0x0061  00_0000_0110_0001   subc    a       
0x0062  00_0000_0110_0010   izsn    a       
0x0063  00_0000_0110_0011   dzsn    a       
0x0064  00_0000_0110_0100
0x0065  00_0000_0110_0101
0x0066  00_0000_0110_0110
0x0067  00_0000_0110_0111   pcadd   a       
0x0068  00_0000_0110_1000   not     a       
0x0069  00_0000_0110_1001   neg     a       
0x006a  00_0000_0110_1010   sr      a       
0x006b  00_0000_0110_1011   sl      a       
0x006c  00_0000_0110_1100   src     a       
0x006d  00_0000_0110_1101   slc     a       
0x006e  00_0000_0110_1110   swap    a       
0x006f  00_0000_0110_1111
0x0070  00_0000_0111_0000   wdreset         
0x0071  00_0000_0111_0001
0x0072  00_0000_0111_0010   pushaf         
0x0073  00_0000_0111_0011   popaf           
0x0074  00_0000_0111_0100
0x0075  00_0000_0111_0101   reset           
0x0076  00_0000_0111_0110   stopsys         
0x0077  00_0000_0111_0111   stopexe         
0x0078  00_0000_0111_1000   engint         
0x0079  00_0000_0111_1001   disgint         
0x007a  00_0000_0111_1010   ret             
0x007b  00_0000_0111_1011   reti           
0x007c  00_0000_0111_1100   mul             
0x007d  00_0000_0111_1101
0x007e  00_0000_0111_1110
0x007f  00_0000_0111_1111
0x0080  00_0000_10--_----
0x00c0  00_0000_11pp_pppp   xor     io,a   
0x0100  00_0001_00--_----
0x0140  00_0001_01--_----
0x0180  00_0001_10pp_pppp   mov     io,a   
0x01c0  00_0001_11pp_pppp   mov     a,io   
0x0200  00_0010_kkkk_kkkk   ret     k       
0x0300  00_0011_0aaa_aaa0   stt16   m       
0x0301  00_0011_0aaa_aaa1   ldt16   m       
0x0380  00_0011_1aaa_aaa0   idxm    m,a     
0x0381  00_0011_1aaa_aaa1   idxm    a,m     
0x0400  00_010b_bbpp_pppp   swapc   io.b   
0x0600  00_0110_0aaa_aaaa   comp    a,m     
0x0680  00_0110 1aaa_aaaa   comp    m,a     
0x0700  00_0111_0aaa_aaaa   nadd    a,m     
0x0780  00_0111_1aaa_aaaa   nadd    m,a     
0x0800  00_1000_0aaa_aaaa   add     m,a     
0x0880  00_1000_1aaa_aaaa   sub     m,a     
0x0900  00_1001_0aaa_aaaa   addc    m,a     
0x0980  00_1001_1aaa_aaaa   subc    m,a     
0x0a00  00_1010_0aaa_aaaa   and     m,a     
0x0a80  00_1010_1aaa_aaaa   or      m,a     
0x0b00  00_1011_0aaa_aaaa   xor     m,a     
0x0b80  00_1011_1aaa_aaaa   mov     m,a     
0x0c00  00_1100_0aaa_aaaa   add     a,m     
0x0c80  00_1100_1aaa_aaaa   sub     a,m     
0x0d00  00_1101_0aaa_aaaa   addc    a,m     
0x0d80  00_1101_1aaa_aaaa   subc    a,m     
0x0e00  00_1110_0aaa_aaaa   and     a,m     
0x0e80  00_1110_1aaa_aaaa   or      a,m     
0x0f00  00_1111_0aaa_aaaa   xor     a,m     
0x0f80  00_1111_1aaa_aaaa   mov     a,m     
0x1000  01_0000_0aaa_aaaa   addc    m       
0x1080  01_0000_1aaa_aaaa   subc    m       
0x1100  01_0001_0aaa_aaaa   izsn    m       
0x1180  01_0001_1aaa_aaaa   dzsn    m       
0x1200  01_0010_0aaa_aaaa   inc     m       
0x1280  01_0010_1aaa_aaaa   dec     m       
0x1300  01_0011_0aaa_aaaa   clear   m       
0x1380  01_0011_1aaa_aaaa   xch     m       
0x1400  01_0100_0aaa_aaaa   not     m       
0x1480  01_0100_1aaa_aaaa   neg     m       
0x1500  01_0101_0aaa_aaaa   sr      m       
0x1580  01_0101_1aaa_aaaa   sl      m       
0x1600  01_0110_0aaa_aaaa   src     m       
0x1680  01_0110_1aaa_aaaa   slc     m       
0x1700  01_0111_0aaa_aaaa   ceqsn   a,m     
0x1780  01_0111_1aaa_aaaa   cneqsn  a,m     
0x1800  01_100b_bbpp_pppp   t0sn    io.b   
0x1a00  01_101b_bbpp_pppp   t1sn    io.b   
0x1c00  01_110b_bbpp_pppp   set0    io.b   
0x1e00  01_111b_bbpp_pppp   set1    io.b   
0x2000  10_000b_bbaa_aaaa   t0sn    m.b     
0x2200  10_001b_bbaa_aaaa   t1sn    m.b     
0x2400  10_010b_bbaa_aaaa   set0    m.b     
0x2600  10_011b_bbaa_aaaa   set1    m.b     
0x2800  10_1000_dddd_dddd   add     a,k     
0x2900  10_1001_dddd_dddd   sub     a,k     
0x2a00  10_1010_dddd_dddd   ceqsn   a,k     
0x2b00  10_1011_dddd_dddd   cneqsn  a,k     
0x2c00  10_1100_dddd_dddd   and     a,k     
0x2d00  10_1101_dddd_dddd   or      a,k     
0x2e00  10_1110_dddd_dddd   xor     a,k     
0x2f00  10_1111_dddd_dddd   mov     a,k     
0x3000  11_0aaa_aaaa_aaaa   goto    k       
0x3800  11_1aaa_aaaa_aaaa   call    k       


13 bit
Code: [Select]
0x0000 0_0000_0000_0000  nop
0x0001 0_0000_0000_0001 
0x0002 0_0000_0000_0010 
0x0003 0_0000_0000_0011 
0x0004 0_0000_0000_0100 
0x0005 0_0000_0000_0101 
0x0006 0_0000_0000_0110 
0x0007 0_0000_0000_0111 
0x0008 0_0000_0000_1000 
0x0009 0_0000_0000_1001 
0x000a 0_0000_0000_1010 
0x000b 0_0000_0000_1011 
0x000c 0_0000_0000_1100 
0x000d 0_0000_0000_1101 
0x000e 0_0000_0000_1110 
0x000f 0_0000_0000_1111 
0x0010 0_0000_0001_0000  addc      a
0x0011 0_0000_0001_0001  subc      a
0x0012 0_0000_0001_0010  izsn      a
0x0013 0_0000_0001_0011  dzsn      a
0x0014 0_0000_0001_0100 
0x0015 0_0000_0001_0101 
0x0016 0_0000_0001_0110 
0x0017 0_0000_0001_0111  pcadd     a
0x0018 0_0000_0001_1000  not       a
0x0019 0_0000_0001_1001  neg       a
0x001a 0_0000_0001_1010  sr        a
0x001b 0_0000_0001_1011  sl        a
0x001c 0_0000_0001_1100  src       a
0x001d 0_0000_0001_1101  slc       a
0x001e 0_0000_0001_1110  swap      a
0x001f 0_0000_0001_1111 
0x0020 0_0000_0010_---- 
0x0030 0_0000_0011_0000  wdreset
0x0031 0_0000_0011_0001 
0x0032 0_0000_0011_0010  pushaf
0x0033 0_0000_0011_0011  popaf
0x0034 0_0000_0011_0100 
0x0035 0_0000_0011_0101  reset
0x0036 0_0000_0011_0110  stopsys
0x0037 0_0000_0011_0111  stopexe
0x0038 0_0000_0011_1000  engint
0x0039 0_0000_0011_1001  disgint
0x003a 0_0000_0011_1010  ret
0x003b 0_0000_0011_1011  reti
0x003c 0_0000_0011_1100 
0x003d 0_0000_0011_1101 
0x003e 0_0000_0011_1110 
0x003f 0_0000_0011_1111 
0x0040 0_0000_010-_---- 
0x0060 0_0000_011p_pppp  xor       io,a
0x0080 0_0000_100p_pppp  mov       io,a
0x00a0 0_0000_101p_pppp  mov       a,io
0x00c0 0_0000_110a_aaa0  stt16     m
0x00c1 0_0000_110a_aaa1  ldt16     m
0x00e0 0_0000_111a_aaa0  idxm      m,a
0x00e1 0_0000_111a_aaa1  idxm      a,m
0x0100 0_0001_dddd_dddd  ret       k
0x0200 0_0010_bbb0_aaaa  t0sn      m.b
0x0210 0_0010_bbb1_aaaa  t1sn      m.b
0x0300 0_0011_bbb0_aaaa  set0      m.b
0x0310 0_0011_bbb1_aaaa  set1      m.b
0x0400 0_0100_00aa_aaaa  add       m,a
0x0440 0_0100_01aa_aaaa  sub       m,a
0x0480 0_0100_10aa_aaaa  addc      m,a
0x04c0 0_0100_11aa_aaaa  subc      m,a
0x0500 0_0101_00aa_aaaa  and       m,a
0x0540 0_0101_01aa_aaaa  or        m,a
0x0580 0_0101_10aa_aaaa  xor       m,a
0x05c0 0_0101_11aa_aaaa  mov       m,a
0x0600 0_0110_00aa_aaaa  add       a,m
0x0640 0_0110_01aa_aaaa  sub       a,m
0x0680 0_0110_10aa_aaaa  addc      a,m
0x06c0 0_0110_11aa_aaaa  subc      a,m
0x0700 0_0111_00aa_aaaa  and       a,m
0x0740 0_0111_01aa_aaaa  or        a,m
0x0780 0_0111_10aa_aaaa  xor       a,m
0x07c0 0_0111_11aa_aaaa  mov       a,m
0x0800 0_1000_00aa_aaaa  addc      m
0x0840 0_1000_01aa_aaaa  subc      m
0x0880 0_1000_10aa_aaaa  izsn      m
0x08c0 0_1000_11aa_aaaa  dzsn      m
0x0900 0_1001_00aa_aaaa  inc       m
0x0940 0_1001_01aa_aaaa  dec       m
0x0980 0_1001_10aa_aaaa  clear     m
0x09c0 0_1001_11aa_aaaa  xch       m
0x0a00 0_1010_00aa_aaaa  not       m
0x0a40 0_1010_01aa_aaaa  neg       m
0x0a80 0_1010_10aa_aaaa  sr        m
0x0ac0 0_1010_11aa_aaaa  sl        m
0x0b00 0_1011_00aa_aaaa  src       m
0x0b40 0_1011_01aa_aaaa  slc       m
0x0b80 0_1011_10aa_aaaa  ceqsn     a,m
0x0bc0 0_1011_11aa_aaaa  cneqsn    a,m
0x0c00 0_1100_bbbp_pppp  t0sn      p.b
0x0d00 0_1101_bbbp_pppp  t1sn      p.b
0x0e00 0_1110_bbbp_pppp  set0      p.b
0x0f00 0_1111_bbbp_pppp  set1      p.b
0x1000 1_0000_dddd_dddd  add       a,k
0x1100 1_0001_dddd_dddd  sub       a,k
0x1200 1_0010_dddd_dddd  ceqsn     a,k
0x1300 1_0011_dddd_dddd  cneqsn    a,k
0x1400 1_0100_dddd_dddd  and       a,k
0x1500 1_0101_dddd_dddd  or        a,k
0x1600 1_0110_dddd_dddd  xor       a,k
0x1700 1_0111_dddd_dddd  mov       a,k
0x1800 1_10aa_aaaa_aaaa  goto      j
0x1c00 1_11aa_aaaa_aaaa  call      j


Comparison sorted by 16 bit opcode
Code: [Select]
nop                 0000_0000_0000_0000   00_0000_0000_0000   0_0000_0000_0000
ldsptl                                    00_0000_0000_0110
ldspth                                    00_0000_0000_0111
addc      a         0000_0000_0001_0000   00_0000_0110_0000   0_0000_0001_0000
subc      a         0000_0000_0001_0001   00_0000_0110_0001   0_0000_0001_0001
izsn      a         0000_0000_0001_0010   00_0000_0110_0010   0_0000_0001_0010
dzsn      a         0000_0000_0001_0011   00_0000_0110_0011   0_0000_0001_0011
pcadd     a         0000_0000_0001_0111   00_0000_0110_0111   0_0000_0001_0111
not       a         0000_0000_0001_1000   00_0000_0110_1000   0_0000_0001_1000
neg       a         0000_0000_0001_1001   00_0000_0110_1001   0_0000_0001_1001
sr        a         0000_0000_0001_1010   00_0000_0110_1010   0_0000_0001_1010
sl        a         0000_0000_0001_1011   00_0000_0110_1011   0_0000_0001_1011
src       a         0000_0000_0001_1100   00_0000_0110_1100   0_0000_0001_1100
slc       a         0000_0000_0001_1101   00_0000_0110_1101   0_0000_0001_1101
swap      a         0000_0000_0001_1110   00_0000_0110_1110   0_0000_0001_1110
delay     a         0000_0000_0001_1111
wdreset             0000_0000_0011_0000   00_0000_0111_0000   0_0000_0011_0000
pushaf              0000_0000_0011_0010   00_0000_0111_0010   0_0000_0011_0010
popaf               0000_0000_0011_0011   00_0000_0111_0011   0_0000_0011_0011
reset               0000_0000_0011_0101   00_0000_0111_0101   0_0000_0011_0101
stopsys             0000_0000_0011_0110   00_0000_0111_0110   0_0000_0011_0110
stopexe             0000_0000_0011_0111   00_0000_0111_0111   0_0000_0011_0111
engint              0000_0000_0011_1000   00_0000_0111_1000   0_0000_0011_1000
disgint             0000_0000_0011_1001   00_0000_0111_1001   0_0000_0011_1001
ret                 0000_0000_0011_1010   00_0000_0111_1010   0_0000_0011_1010
reti                0000_0000_0011_1011   00_0000_0111_1011   0_0000_0011_1011
mul                 0000_0000_0011_1100   00_0000_0111_1100
pmode     n         0000_0000_010k_kkkk
popw      pcN       0000_0000_0110_tttt
pushw     pcN       0000_0000_0111_tttt
mov       IO,a      0000_0000_10pp_pppp   00_0001_10pp_pppp   0_0000_100p_pppp
mov       a,IO      0000_0000_11pp_pppp   00_0001_11pp_pppp   0_0000_101p_pppp
cneqsn    a,I       0000_0001_kkkk_kkkk   10_1011_kkkk_kkkk   1_0011_kkkk_kkkk
stt16     word      0000_001w_wwww_www0   00_0011_0www_www0   0_0000_110w_www0
ldt16     word      0000_001w_wwww_www1   00_0011_0www_www1   0_0000_110w_www1
popw      word      0000_010w_wwww_www0
pushw     word      0000_010w_wwww_www1
igoto     word      0000_011w_wwww_www0
icall     word      0000_011w_wwww_www1
idxm      index,a   0000_100w_wwww_www0   00_0011_1www_www0   0_0000_111w_www0
idxm      a,index   0000_100w_wwww_www1   00_0011_1www_www1   0_0000_111w_www1
ldtabl    word      0000_101w_wwww_www0
ldtabh    word      0000_101w_wwww_www1
delay     I         0000_1110_kkkk_kkkk
ret       I         0000_1111_kkkk_kkkk   00_0010_kkkk_kkkk   0_0001_kkkk_kkkk
xor       IO,a      0001_0000_00pp_pppp   00_0000_11pp_pppp   0_0000_011p_pppp
xor       a,IO      0001_0000_01pp_pppp
cneqsn    M,a       0001_010m_mmmm_mmmm
cneqsn    a,M       0001_011m_mmmm_mmmm   01_0111_1mmm_mmmm   0_1011_11mm_mmmm
add       a,I       0001_1000_kkkk_kkkk   10_1000_kkkk_kkkk   1_0000_kkkk_kkkk
sub       a,I       0001_1001_kkkk_kkkk   10_1001_kkkk_kkkk   1_0001_kkkk_kkkk
ceqsn     a,I       0001_1010_kkkk_kkkk   10_1010_kkkk_kkkk   1_0010_kkkk_kkkk
comp      a,I       0001_1011_kkkk_kkkk
and       a,I       0001_1100_kkkk_kkkk   10_1100_kkkk_kkkk   1_0100_kkkk_kkkk
or        a,I       0001_1101_kkkk_kkkk   10_1101_kkkk_kkkk   1_0101_kkkk_kkkk
xor       a,I       0001_1110_kkkk_kkkk   10_1110_kkkk_kkkk   1_0110_kkkk_kkkk
mov       a,I       0001_1111_kkkk_kkkk   10_1111_kkkk_kkkk   1_0111_kkkk_kkkk
t0sn      IO.n      0010_000b_bbpp_pppp   01_100b_bbpp_pppp   0_1100_bbbp_pppp
t1sn      IO.n      0010_001b_bbpp_pppp   01_101b_bbpp_pppp   0_1101_bbbp_pppp
set0      IO.n      0010_010b_bbpp_pppp   01_110b_bbpp_pppp   0_1110_bbbp_pppp
set1      IO.n      0010_011b_bbpp_pppp   01_111b_bbpp_pppp   0_1111_bbbp_pppp
tog       IO.n      0010_100b_bbpp_pppp
wait0     IO.n      0010_101b_bbpp_pppp
wait1     IO.n      0010_110b_bbpp_pppp
swapc     IO.n      0010_111b_bbpp_pppp   00_010b_bbpp_pppp
nmov      M,a       0011_000m_mmmm_mmmm
nmov      a,M       0011_001m_mmmm_mmmm
nadd      M,a       0011_010m_mmmm_mmmm   00_0111_1mmm_mmmm
nadd      a,M       0011_011m_mmmm_mmmm   00_0111_0mmm_mmmm
ceqsn     M,a       0011_100m_mmmm_mmmm
ceqsn     a,M       0011_101m_mmmm_mmmm   01_0111_0mmm_mmmm   0_1011_10mm_mmmm
comp      M,a       0011_110m_mmmm_mmmm   00_0110_1mmm_mmmm
comp      a,M       0011_111m_mmmm_mmmm   00_0110_0mmm_mmmm
add       M,a       0100_000m_mmmm_mmmm   00_1000_0mmm_mmmm   0_0100_00mm_mmmm
add       a,M       0100_001m_mmmm_mmmm   00_1100_0mmm_mmmm   0_0110_00mm_mmmm
sub       M,a       0100_010m_mmmm_mmmm   00_1000_1mmm_mmmm   0_0100_01mm_mmmm
sub       a,M       0100_011m_mmmm_mmmm   00_1100_1mmm_mmmm   0_0110_01mm_mmmm
addc      M,a       0100_100m_mmmm_mmmm   00_1001_0mmm_mmmm   0_0100_10mm_mmmm
addc      a,M       0100_101m_mmmm_mmmm   00_1101_0mmm_mmmm   0_0110_10mm_mmmm
subc      M,a       0100_110m_mmmm_mmmm   00_1001_1mmm_mmmm   0_0100_11mm_mmmm
subc      a,M       0100_111m_mmmm_mmmm   00_1101_1mmm_mmmm   0_0110_11mm_mmmm
and       M,a       0101_000m_mmmm_mmmm   00_1010_0mmm_mmmm   0_0101_00mm_mmmm
and       a,M       0101_001m_mmmm_mmmm   00_1110_0mmm_mmmm   0_0111_00mm_mmmm
or        M,a       0101_010m_mmmm_mmmm   00_1010_1mmm_mmmm   0_0101_01mm_mmmm
or        a,M       0101_011m_mmmm_mmmm   00_1110_1mmm_mmmm   0_0111_01mm_mmmm
xor       M,a       0101_100m_mmmm_mmmm   00_1011_0mmm_mmmm   0_0101_10mm_mmmm
xor       a,M       0101_101m_mmmm_mmmm   00_1111_0mmm_mmmm   0_0111_10mm_mmmm
mov       M,a       0101_110m_mmmm_mmmm   00_1011_1mmm_mmmm   0_0101_11mm_mmmm
mov       a,M       0101_111m_mmmm_mmmm   00_1111_1mmm_mmmm   0_0111_11mm_mmmm
addc      M         0110_000m_mmmm_mmmm   01_0000_0mmm_mmmm   0_1000_00mm_mmmm
subc      M         0110_001m_mmmm_mmmm   01_0000_1mmm_mmmm   0_1000_01mm_mmmm
izsn      M         0110_010m_mmmm_mmmm   01_0001_0mmm_mmmm   0_1000_10mm_mmmm
dzsn      M         0110_011m_mmmm_mmmm   01_0001_1mmm_mmmm   0_1000_11mm_mmmm
inc       M         0110_100m_mmmm_mmmm   01_0010_0mmm_mmmm   0_1001_00mm_mmmm
dec       M         0110_101m_mmmm_mmmm   01_0010_1mmm_mmmm   0_1001_01mm_mmmm
clear     M         0110_110m_mmmm_mmmm   01_0011_0mmm_mmmm   0_1001_10mm_mmmm
xch       M         0110_111m_mmmm_mmmm   01_0011_1mmm_mmmm   0_1001_11mm_mmmm
not       M         0111_000m_mmmm_mmmm   01_0100_0mmm_mmmm   0_1010_00mm_mmmm
neg       M         0111_001m_mmmm_mmmm   01_0100_1mmm_mmmm   0_1010_01mm_mmmm
sr        M         0111_010m_mmmm_mmmm   01_0101_0mmm_mmmm   0_1010_10mm_mmmm
sl        M         0111_011m_mmmm_mmmm   01_0101_1mmm_mmmm   0_1010_11mm_mmmm
src       M         0111_100m_mmmm_mmmm   01_0110_0mmm_mmmm   0_1011_00mm_mmmm
slc       M         0111_101m_mmmm_mmmm   01_0110_1mmm_mmmm   0_1011_01mm_mmmm
swap      M         0111_110m_mmmm_mmmm
delay     M         0111_111m_mmmm_mmmm
t0sn      M.n       1000_bbbm_mmmm_mmmm   10_000b_bbmm_mmmm   0_0010_bbb0_mmmm
t1sn      M.n       1001_bbbm_mmmm_mmmm   10_001b_bbmm_mmmm   0_0010_bbb1_mmmm
set0      M.n       1010_bbbm_mmmm_mmmm   10_010b_bbmm_mmmm   0_0011_bbb0_mmmm
set1      M.n       1011_bbbm_mmmm_mmmm   10_011b_bbmm_mmmm   0_0011_bbb1_mmmm
goto      label     110a_aaaa_aaaa_aaaa   11_0aaa_aaaa_aaaa   1_10aa_aaaa_aaaa
call      label     111a_aaaa_aaaa_aaaa   11_1aaa_aaaa_aaaa   1_11aa_aaaa_aaaa


Comparison sorted by mnemonic
Code: [Select]
add       a,I       0001_1000_kkkk_kkkk   10_1000_kkkk_kkkk   1_0000_kkkk_kkkk
add       a,M       0100_001m_mmmm_mmmm   00_1100_0mmm_mmmm   0_0110_00mm_mmmm
add       M,a       0100_000m_mmmm_mmmm   00_1000_0mmm_mmmm   0_0100_00mm_mmmm
addc      a         0000_0000_0001_0000   00_0000_0110_0000   0_0000_0001_0000
addc      a,M       0100_101m_mmmm_mmmm   00_1101_0mmm_mmmm   0_0110_10mm_mmmm
addc      M         0110_000m_mmmm_mmmm   01_0000_0mmm_mmmm   0_1000_00mm_mmmm
addc      M,a       0100_100m_mmmm_mmmm   00_1001_0mmm_mmmm   0_0100_10mm_mmmm
and       a,I       0001_1100_kkkk_kkkk   10_1100_kkkk_kkkk   1_0100_kkkk_kkkk
and       a,M       0101_001m_mmmm_mmmm   00_1110_0mmm_mmmm   0_0111_00mm_mmmm
and       M,a       0101_000m_mmmm_mmmm   00_1010_0mmm_mmmm   0_0101_00mm_mmmm
call      label     111a_aaaa_aaaa_aaaa   11_1aaa_aaaa_aaaa   1_11aa_aaaa_aaaa
ceqsn     a,I       0001_1010_kkkk_kkkk   10_1010_kkkk_kkkk   1_0010_kkkk_kkkk
ceqsn     a,M       0011_101m_mmmm_mmmm   01_0111_0mmm_mmmm   0_1011_10mm_mmmm
ceqsn     M,a       0011_100m_mmmm_mmmm
clear     M         0110_110m_mmmm_mmmm   01_0011_0mmm_mmmm   0_1001_10mm_mmmm
cneqsn    a,I       0000_0001_kkkk_kkkk   10_1011_kkkk_kkkk   1_0011_kkkk_kkkk
cneqsn    a,M       0001_011m_mmmm_mmmm   01_0111_1mmm_mmmm   0_1011_11mm_mmmm
cneqsn    M,a       0001_010m_mmmm_mmmm
comp      a,I       0001_1011_kkkk_kkkk
comp      a,M       0011_111m_mmmm_mmmm   00_0110_0mmm_mmmm
comp      M,a       0011_110m_mmmm_mmmm   00_0110_1mmm_mmmm
dec       M         0110_101m_mmmm_mmmm   01_0010_1mmm_mmmm   0_1001_01mm_mmmm
delay     a         0000_0000_0001_1111
delay     I         0000_1110_kkkk_kkkk
delay     M         0111_111m_mmmm_mmmm
disgint             0000_0000_0011_1001   00_0000_0111_1001   0_0000_0011_1001
dzsn      a         0000_0000_0001_0011   00_0000_0110_0011   0_0000_0001_0011
dzsn      M         0110_011m_mmmm_mmmm   01_0001_1mmm_mmmm   0_1000_11mm_mmmm
engint              0000_0000_0011_1000   00_0000_0111_1000   0_0000_0011_1000
goto      label     110a_aaaa_aaaa_aaaa   11_0aaa_aaaa_aaaa   1_10aa_aaaa_aaaa
icall     word      0000_011w_wwww_www1
idxm      a,index   0000_100w_wwww_www1   00_0011_1www_www1   0_0000_111w_www1
idxm      index,a   0000_100w_wwww_www0   00_0011_1www_www0   0_0000_111w_www0
igoto     word      0000_011w_wwww_www0
inc       M         0110_100m_mmmm_mmmm   01_0010_0mmm_mmmm   0_1001_00mm_mmmm
izsn      a         0000_0000_0001_0010   00_0000_0110_0010   0_0000_0001_0010
izsn      M         0110_010m_mmmm_mmmm   01_0001_0mmm_mmmm   0_1000_10mm_mmmm
ldspth                                    00_0000_0000_0111
ldsptl                                    00_0000_0000_0110
ldt16     word      0000_001w_wwww_www1   00_0011_0www_www1   0_0000_110w_www1
ldtabh    word      0000_101w_wwww_www1
ldtabl    word      0000_101w_wwww_www0
mov       a,I       0001_1111_kkkk_kkkk   10_1111_kkkk_kkkk   1_0111_kkkk_kkkk
mov       a,IO      0000_0000_11pp_pppp   00_0001_11pp_pppp   0_0000_101p_pppp
mov       a,M       0101_111m_mmmm_mmmm   00_1111_1mmm_mmmm   0_0111_11mm_mmmm
mov       IO,a      0000_0000_10pp_pppp   00_0001_10pp_pppp   0_0000_100p_pppp
mov       M,a       0101_110m_mmmm_mmmm   00_1011_1mmm_mmmm   0_0101_11mm_mmmm
mul                 0000_0000_0011_1100   00_0000_0111_1100
nadd      a,M       0011_011m_mmmm_mmmm   00_0111_0mmm_mmmm
nadd      M,a       0011_010m_mmmm_mmmm   00_0111_1mmm_mmmm
neg       a         0000_0000_0001_1001   00_0000_0110_1001   0_0000_0001_1001
neg       M         0111_001m_mmmm_mmmm   01_0100_1mmm_mmmm   0_1010_01mm_mmmm
nmov      a,M       0011_001m_mmmm_mmmm
nmov      M,a       0011_000m_mmmm_mmmm
nop                 0000_0000_0000_0000   00_0000_0000_0000   0_0000_0000_0000
not       a         0000_0000_0001_1000   00_0000_0110_1000   0_0000_0001_1000
not       M         0111_000m_mmmm_mmmm   01_0100_0mmm_mmmm   0_1010_00mm_mmmm
or        a,I       0001_1101_kkkk_kkkk   10_1101_kkkk_kkkk   1_0101_kkkk_kkkk
or        a,M       0101_011m_mmmm_mmmm   00_1110_1mmm_mmmm   0_0111_01mm_mmmm
or        M,a       0101_010m_mmmm_mmmm   00_1010_1mmm_mmmm   0_0101_01mm_mmmm
pcadd     a         0000_0000_0001_0111   00_0000_0110_0111   0_0000_0001_0111
pmode     n         0000_0000_010k_kkkk
popaf               0000_0000_0011_0011   00_0000_0111_0011   0_0000_0011_0011
popw      pcN       0000_0000_0110_tttt
popw      word      0000_010w_wwww_www0
pushaf              0000_0000_0011_0010   00_0000_0111_0010   0_0000_0011_0010
pushw     pcN       0000_0000_0111_tttt
pushw     word      0000_010w_wwww_www1
reset               0000_0000_0011_0101   00_0000_0111_0101   0_0000_0011_0101
ret                 0000_0000_0011_1010   00_0000_0111_1010   0_0000_0011_1010
ret       I         0000_1111_kkkk_kkkk   00_0010_kkkk_kkkk   0_0001_kkkk_kkkk
reti                0000_0000_0011_1011   00_0000_0111_1011   0_0000_0011_1011
set0      IO.n      0010_010b_bbpp_pppp   01_110b_bbpp_pppp   0_1110_bbbp_pppp
set0      M.n       1010_bbbm_mmmm_mmmm   10_010b_bbmm_mmmm   0_0011_bbb0_mmmm
set1      IO.n      0010_011b_bbpp_pppp   01_111b_bbpp_pppp   0_1111_bbbp_pppp
set1      M.n       1011_bbbm_mmmm_mmmm   10_011b_bbmm_mmmm   0_0011_bbb1_mmmm
sl        a         0000_0000_0001_1011   00_0000_0110_1011   0_0000_0001_1011
sl        M         0111_011m_mmmm_mmmm   01_0101_1mmm_mmmm   0_1010_11mm_mmmm
slc       a         0000_0000_0001_1101   00_0000_0110_1101   0_0000_0001_1101
slc       M         0111_101m_mmmm_mmmm   01_0110_1mmm_mmmm   0_1011_01mm_mmmm
sr        a         0000_0000_0001_1010   00_0000_0110_1010   0_0000_0001_1010
sr        M         0111_010m_mmmm_mmmm   01_0101_0mmm_mmmm   0_1010_10mm_mmmm
src       a         0000_0000_0001_1100   00_0000_0110_1100   0_0000_0001_1100
src       M         0111_100m_mmmm_mmmm   01_0110_0mmm_mmmm   0_1011_00mm_mmmm
stopexe             0000_0000_0011_0111   00_0000_0111_0111   0_0000_0011_0111
stopsys             0000_0000_0011_0110   00_0000_0111_0110   0_0000_0011_0110
stt16     word      0000_001w_wwww_www0   00_0011_0www_www0   0_0000_110w_www0
sub       a,I       0001_1001_kkkk_kkkk   10_1001_kkkk_kkkk   1_0001_kkkk_kkkk
sub       a,M       0100_011m_mmmm_mmmm   00_1100_1mmm_mmmm   0_0110_01mm_mmmm
sub       M,a       0100_010m_mmmm_mmmm   00_1000_1mmm_mmmm   0_0100_01mm_mmmm
subc      a         0000_0000_0001_0001   00_0000_0110_0001   0_0000_0001_0001
subc      a,M       0100_111m_mmmm_mmmm   00_1101_1mmm_mmmm   0_0110_11mm_mmmm
subc      M         0110_001m_mmmm_mmmm   01_0000_1mmm_mmmm   0_1000_01mm_mmmm
subc      M,a       0100_110m_mmmm_mmmm   00_1001_1mmm_mmmm   0_0100_11mm_mmmm
swap      a         0000_0000_0001_1110   00_0000_0110_1110   0_0000_0001_1110
swap      M         0111_110m_mmmm_mmmm
swapc     IO.n      0010_111b_bbpp_pppp   00_010b_bbpp_pppp
t0sn      IO.n      0010_000b_bbpp_pppp   01_100b_bbpp_pppp   0_1100_bbbp_pppp
t0sn      M.n       1000_bbbm_mmmm_mmmm   10_000b_bbmm_mmmm   0_0010_bbb0_mmmm
t1sn      IO.n      0010_001b_bbpp_pppp   01_101b_bbpp_pppp   0_1101_bbbp_pppp
t1sn      M.n       1001_bbbm_mmmm_mmmm   10_001b_bbmm_mmmm   0_0010_bbb1_mmmm
tog       IO.n      0010_100b_bbpp_pppp
wait0     IO.n      0010_101b_bbpp_pppp
wait1     IO.n      0010_110b_bbpp_pppp
wdreset             0000_0000_0011_0000   00_0000_0111_0000   0_0000_0011_0000
xch       M         0110_111m_mmmm_mmmm   01_0011_1mmm_mmmm   0_1001_11mm_mmmm
xor       a,I       0001_1110_kkkk_kkkk   10_1110_kkkk_kkkk   1_0110_kkkk_kkkk
xor       a,IO      0001_0000_01pp_pppp
xor       a,M       0101_101m_mmmm_mmmm   00_1111_0mmm_mmmm   0_0111_10mm_mmmm
xor       IO,a      0001_0000_00pp_pppp   00_0000_11pp_pppp   0_0000_011p_pppp
xor       M,a       0101_100m_mmmm_mmmm   00_1011_0mmm_mmmm   0_0101_10mm_mmmm

 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #155 on: November 28, 2018, 06:18:11 am »
Thanks for the code. I seem to have an endianess problem somewhere.
I am using linux, but the IDE doesnt work with wine.
So I used windows to make and convert the file. Somehow bytes got swapped  :palm:
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #156 on: November 28, 2018, 06:49:57 am »
[…]
If I counted correctly there are only these instruction set families
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
.Assembly   INSTRUMENT   SYM_82A
.Assembly   INSTRUMENT   SYM_83A
.Assembly   INSTRUMENT   SYM_86A

I suspect that INSTRUMENT means same for ASM and ICE

I had noticed those SYM_ whatever things in the files before, but didn't see their relation to the instruction sets. ASM_INSTR SYM_85A is found in files for devices both with (e.g. PMS130) and without (e.g. PFS154) the mul instruction. ASM_INSTR SYM_83A is found in files for devices with pushw (e.g. PMC884) without pushw (e.g. PMS232).

Philipp
 
The following users thanked this post: oPossum

Offline westfw

  • Super Contributor
  • ***
  • Posts: 2794
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #157 on: November 28, 2018, 08:04:54 pm »
(Wow.   I just want to throw in a compliment.  This has been REALLY IMPRESSIVE!  Great work; excellent collaboration!)
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #158 on: November 29, 2018, 07:47:40 am »
Maybe the Symbol Files have to be seen in conjuction with the inc files.
SYM_85A does not include the mul instruction.
The inc file for the pfs154 doesnt have anything related to mul and the ide complains that "mul not be supported at pfs154"

The inc file for the pms130 does have to registers defined
   MULOP      IO_RW      0x08
   MULRH      IO_RO      0x09
for the multiplication.

I couldnt find the device ids in the symbol files so that must be stored somewhere else.

So I guess the symbol files are templates for the ide that then get modified for the specific ic.

Edit: if I change the SYM in the INC file, instructions missing in the other family are no longer recognized. (syntax error)
« Last Edit: November 29, 2018, 07:50:24 am by DocBen »
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #159 on: November 30, 2018, 11:21:26 pm »
For all the people interested in ordering PADAUK parts and tools.

I ordered some stuff from lcsc.com with standard shipping. Payment was done using Paypal, delivery cost was around 7 USD. After 15 days my order arrived without any problems (direct shipping from China to my place).


Here is a list of ICs and tools from PADAUK I use.

Please consider to use the AFFILIATE LINKS from below when you order from lcsc.com. This will give me some credits there and I can order more PADAUK parts to investigate.

THANK YOU!

---

ICs I use:

Flash based ICs (1000 erase/write cycles possible):
PFS154-S08  (14 bit opcodes)
PFS154-S14 (14 bit opcodes)

OTP ICs (One Time Programmable):
PMS154B-S14 (14 bit opcodes)
PMS150C-S08 (13 bit opcodes)

---

My Programmer: PDK 3S-P-002 !!!OLD VERSION, DOES NOT SUPPORT PFS154 Flash based IC!!!!

Alternative Programmer: PDK 5S-P-003

My ICE: PDK 5S-I-S01 !!! SUPPORTS ALL SINGLE CORE VARIANTS!!!

Alternative ICE: PDK 3S-I-003 !!!OLD PRODUCT, ONLY FOR SOME MULTICORE VARIANTS!!!

---

Have fun,

JS
« Last Edit: December 01, 2018, 09:18:30 am by js_12345678_55AA »
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #160 on: December 01, 2018, 02:56:21 am »
Do we have any idea if the Padauk Programmer supports on-target debugging in any way?

Philipp
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #161 on: December 01, 2018, 03:49:27 am »
Do we have any idea if the Padauk Programmer supports on-target debugging in any way?

Philipp

Hi,

the programmer is just for writing to the IC. Usually the IDE inserts some "INIT-CODE" for IC testing and calibrating clock. This init code steals some valuable code space. It uses bit bang protocol on 3 IO pins to communicate with WRITER.

-> WRITER can not debug anything from your user program.
-> PADAUK CPU do not have any debug features (e.g. breakpoints) built in

Your best choice is to use the ICE. Then you get breakpoints and memory inspection from the IDE directly.

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #162 on: December 01, 2018, 11:51:12 am »
Disassembler for all Padauk MCUs.

Usage: pdisasm pdk [io_symbols [mem_symbols]]

To show instruction set: pdisasm 13 | 14 | 16 | all
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #163 on: December 01, 2018, 09:32:01 pm »
Disassembler for all Padauk MCUs.

Usage: pdisasm pdk [io_symbols [mem_symbols]]

To show instruction set: pdisasm 13 | 14 | 16 | all


Great job!
I've modified it so that it compiles under linux (none of those ms dependencies any more and a Makefile), hope thats ok (+ some whitespace changes)
You can look at the attached patch files to see what I did.
just 'make' it.
 
The following users thanked this post: oPossum

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #164 on: December 01, 2018, 11:35:31 pm »
I've modified main so that it will load the io symbols automagically, because that was irritating me to no end ;)

Code: [Select]
--- original/padauk_disasm.cpp 2018-12-01 11:25:20.595205297 +0100
+++ padauk_disasm.cpp 2018-12-01 13:31:07.148535905 +0100
@@ -1,11 +1,11 @@
-
-#include "stdafx.h"
+#include <string.h>
+#include <stdlib.h>
 #include "pdk.h"
 #include "disasm.h"
 
 
-int main(int argc, char **argv)
-{
+int
+main(int argc, char **argv) {
  if (argc < 2) {
  printf("Usage: pdisasm pdk [ io_symbols [ mem_symbols] ]\n");
  return 0;
@@ -30,10 +30,17 @@
  auto d = CPadaukDisasm::New(pdk.bits);
  if (!d) { printf("Unsupported core (%i bits)\n", pdk.bits);  return -2; }
 
- if (argc > 2) d->io_symbols.ReadFile(argv[2]);
+ if (argc > 2) {
+ d->io_symbols.ReadFile(argv[2]);
+ } else {
+ char fname[17] = {};
+ sprintf(fname, "sym_io_%d.txt", pdk.bits);
+ d->io_symbols.ReadFile(fname);
+ }
+
  if (argc > 3) d->mem_symbols.ReadFile(argv[3]);
 
  d->disasm(pdk);
  }
-    return 0;
+ return 0;
 }
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #165 on: December 01, 2018, 11:57:14 pm »
Here is the precompiled ready to run binary and support files for linux. I use Ubuntu 18.04 LTS so should be fine for any current distribution ( I hope ;)

small_possum is the same but with debug symbols stripped so its only about 45k in size ready to run.
« Last Edit: December 02, 2018, 12:06:16 am by DocBen »
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #166 on: December 03, 2018, 03:40:25 am »
Today, I made a first step to inefficently compiling a small subset of C to Padauk asm code. The current version is very restricted and generates very inefficient code; it is untested.

There is no assembler / linker support, so the resulting .asm file has to be assembled in other ways.

Particularly noticeable restrictions:

* The only data types supported are the basic integer types. No pointers, arrays, struct, union, float, etc.
* Functions cannot have parameters.
* Functions can return at most 1 byte (i.e. only void, bool, char, signed char, unsigned char are allowed).
* Bitwise operations and shifts are no supported.
* Multiplicative operators are not supported.
* Functions are not reentrant.

Code in svn at https://svn.code.sf.net/p/sdcc/code/branches/pdk/sdcc, use -mpdk14 to target Padauk (despite the name, the set of instructions emitted is part of the common subset of the Padauk instruction sets).

Philipp

P.S.: The only allowed comparisons are for equality, i.e. == and !=, while <,<=, >, >= don't work. Fortunately, most attempts to use non-supported functionality result in compile-time errors.
« Last Edit: December 03, 2018, 03:46:01 am by spth »
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #167 on: December 03, 2018, 07:44:39 pm »
I have a startup file for the pfs154 that doesnt dissasemble correctly using the current sets, I suspect that 85A is still different from the others

Has this been resolved? Do we know if there are encoding differences within the individual 13-Bit / 14-Bit / 16_ Bit instruction sets (apart from differences in the supported subset of instructions)?

In particular: Can we be reasonably sure that the 14-Bit instruction set at https://free-pdk.github.io/PADAUK_FPPA_14_bit_instruction_set.html reflects the actual encoding for the PFS154?

Philipp
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #168 on: December 03, 2018, 11:53:43 pm »
I have a startup file for the pfs154 that doesnt dissasemble correctly using the current sets, I suspect that 85A is still different from the others

Has this been resolved? Do we know if there are encoding differences within the individual 13-Bit / 14-Bit / 16_ Bit instruction sets (apart from differences in the supported subset of instructions)?

In particular: Can we be reasonably sure that the 14-Bit instruction set at https://free-pdk.github.io/PADAUK_FPPA_14_bit_instruction_set.html reflects the actual encoding for the PFS154?

Philipp


Just checked again. Yes.
Startup code for the PFS154 (dissassembled with opossum on linux):

Code: [Select]
PDK version: 20
PDK data size:  2048 words
Free data size: 2016 words
MCU: PFS154 [ID: 0x2AA1]
Compiler version: 0.83B17
14 bit core
0000  0070  wdreset   
0001  2F00  mov       a, 0x00
0002  0182  mov       SP, a
0003  3FED  call      0x07ED
0004  018B  mov       IHRCR, a
0005  3FEE  call      0x07EE
0006  019A  mov       BGTR, a
0007  2F20  mov       a, 0x20
0008  019B  mov       MISC_LVR, a
0009  2F34  mov       a, 0x34
000A  0183  mov       CLKCMD, a
000B  3FFE  call      0x07FE
000C  2AFF  ceqsn     a, 0xFF
000D  3054  goto      0x0054
000E  3FED  call      0x07ED
000F  0B81  mov       M1, a
0010  1F91  set1      PAC.6
0011  2F20  mov       a, 0x20
0012  0B80  mov       M0, a
0013  1AD0  t1sn      PA.3
0014  3013  goto      0x0013
0015  1F90  set1      PA.6
0016  0063  dzsn      a
0017  3016  goto      0x0016
0018  1180  dzsn      M0
0019  3016  goto      0x0016
001A  1D90  set0      PA.6
001B  18D0  t0sn      PA.3
001C  301B  goto      0x001B
001D  2F01  mov       a, 0x01
001E  1950  t0sn      PA.5
001F  2FFF  mov       a, 0xFF
0020  0C01  add       a, M1
0021  018B  mov       IHRCR, a
0022  0B81  mov       M1, a
0023  1AD0  t1sn      PA.3
0024  3023  goto      0x0023
0025  1B50  t1sn      PA.5
0026  304F  goto      0x004F
0027  2F04  mov       a, 0x04
0028  0188  mov       MISC, a
0029  18D0  t0sn      PA.3
002A  3029  goto      0x0029
002B  2F02  mov       a, 0x02
002C  0182  mov       SP, a
002D  1304  clear     M4
002E  1305  clear     M5
002F  2F5E  mov       a, 0x5E
0030  0B82  mov       M2, a
0031  2F00  mov       a, 0x00
0032  0B83  mov       M3, a
0033  0006  ldsptl   
0034  0B04  xor       M4, a
0035  0007  ldspth   
0036  0805  add       M5, a
0037  1584  sl        M4
0038  1685  slc       M5
0039  1004  addc      M4
003A  1282  dec       M2
003B  1083  subc      M3
003C  1A40  t1sn      FLAG.C
003D  3033  goto      0x0033
003E  1F90  set1      PA.6
003F  1AD0  t1sn      PA.3
0040  303F  goto      0x003F
0041  1584  sl        M4
0042  1685  slc       M5
0043  0590  swapc     PA.6
0044  18D0  t0sn      PA.3
0045  3044  goto      0x0044
0046  1950  t0sn      PA.5
0047  303F  goto      0x003F
0048  1D90  set0      PA.6
0049  1AD0  t1sn      PA.3
004A  3049  goto      0x0049
004B  18D0  t0sn      PA.3
004C  304B  goto      0x004B
004D  1B50  t1sn      PA.5
004E  302B  goto      0x002B
004F  18D0  t0sn      PA.3
0050  304F  goto      0x004F
0051  1B50  t1sn      PA.5
0052  3011  goto      0x0011
0053  3053  goto      0x0053
0054  018B  mov       IHRCR, a
0055  0000  nop       // here a nop/wdreset pattern starts so that I can recognize my code
0056  0070  wdreset   
0057  0000  nop       
0058  0070  wdreset   
0059  0000  nop       
005A  0070  wdreset   
005B  0000  nop       
005C  0070  wdreset   
005D  0000  nop       
005E  3055  goto      0x0055 
....    // all other locations are 3FFF
07EF  1FFE  set1      GPCC.7
07F0  3FFF  call      0x07FF
07F1  3FFF  call      0x07FF
07F2  3FFF  call      0x07FF
07F3  3FFF  call      0x07FF
07F4  3FFF  call      0x07FF
07F5  3FFF  call      0x07FF
07F6  3FFF  call      0x07FF
07F7  3FFF  call      0x07FF
07F8  0000  nop       
07F9  0000  nop       
07FA  3FFF  call      0x07FF
07FB  3FFF  call      0x07FF
07FC  3FFF  call      0x07FF
07FD  3FFF  call      0x07FF
07FE  3FFF  call      0x07FF
07FF  3DFD  call      0x05FD

Edit: It's actually slightly different from the one posted above, but only single instructions and coherent with the encoding.
Probably the options I chose?
« Last Edit: December 04, 2018, 12:08:17 am by DocBen »
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #169 on: December 04, 2018, 12:19:38 am »
I think the only family missing is for these chips:

grep -Rlsi SYM_86B

PMS134.INC
MCU371.INC
PMS132K.INC
PMS133.INC
PFS173.INC

---

The differences I can spot are minimal: 86B also includes the NMOV instruction but lacks the (explicit?) description of LDSPTL/LDSPTH but instead has LDTABL/LDTABH.
Also the order of the instructions in the symbol file is slightly different.

The datasheet claims that the pfs173 has 89 instructions (I count 88) while the pfs154 has 82.

The actual devices are thus slightly different: the PFS154 misses the NADD and COMP instructions as per datasheet. Dont know if the IDE will accept them anyway. And LDSPTL/LDSPTH is in the Symbol file but not documented.
« Last Edit: December 04, 2018, 01:00:02 am by DocBen »
 
The following users thanked this post: oPossum

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #170 on: December 04, 2018, 01:05:20 am »
And trying to dissassemble the PFS173 startup code we get this:

PDK version: 20
PDK data size:  3072 words
Free data size: 3040 words
MCU: PFS173 [ID: 0x2AA2]
Compiler version: 0.83B17
15 bit core
Unsupported core (15 bits)

So I was almost right: there is a different encoding (but not for the pfs154) :-DD
« Last Edit: December 04, 2018, 01:07:51 am by DocBen »
 
The following users thanked this post: oPossum

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #171 on: December 04, 2018, 01:15:02 am »
So the 15-Bit encoding actually exists. Interesting. I hope it gets documented, too.

Philipp
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #172 on: December 04, 2018, 02:00:07 am »
Just noticed a small error I made in the linux sources that cuts off the first three bits of the printed opcode.
Corrected source below (also includes startupcode for pfs154 and 173) and precompiled binary.

Just a reminder to myself:
the amount of addressable memory is (core size in bits - 3)
16 -> 13 -> 8192 words, Family 83A
15 -> 12 -> 4096 words, Family 86B
14 -> 11 -> 2048 words, Family 85A
13 -> 10 -> 1024 words, Family 84B
« Last Edit: December 04, 2018, 06:16:38 am by DocBen »
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #173 on: December 04, 2018, 02:16:20 am »
15 bit instruction set confirmed. I thought it existed but the chips with 4 kW memory used the 16 bit instruction set, so I stopped looking.
Working on complete decode and updated disassembler.

Code: [Select]
6000   goto  0x0000
6FFF   goto  0x0FFF
7000   call  0x0000
7FFF   call  0x0FFF

12 bit program address
Probably 8 bit memory address.
IO address TBD.

 
The following users thanked this post: DocBen

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #174 on: December 04, 2018, 06:17:57 am »
Today, I made a first step to inefficently compiling a small subset of C to Padauk asm code. The current version is very restricted and generates very inefficient code; it is untested.

There is no assembler / linker support, so the resulting .asm file has to be assembled in other ways.

[…]

Code in svn at https://svn.code.sf.net/p/sdcc/code/branches/pdk/sdcc, use -mpdk14 to target Padauk (despite the name, the set of instructions emitted is part of the common subset of the Padauk instruction sets).

On the second day, wrt. completeness of implementation of the C standard, this has now far surpassed Mini-C.

Noticeable remaining restrictions:

* Variables can only reside in RAM, not in code space
* Global and static variables are not initialized.
* No floating-point or bit-fields.
* Functions can return at most 2 bytes (i.e. no long or long long).
* Multiplicative operators are not supported.
* Functions are not reentrant.
* No support for variable arguments.
* No standard library.
* struct / union cannot be assigned, passed as arguments or returned.
* No compoundliterals.
* No access to I/O from C.

There is no glue to connect this to assembler / linker yet, so the only useable output is asm code.
The generated asm code is still very inefficient. I will look into improving that a bit soon.

Philipp
 
The following users thanked this post: oPossum, DocBen, js_12345678_55AA

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 104
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #175 on: December 04, 2018, 06:27:53 am »
Has this been resolved? Do we know if there are encoding differences within the individual 13-Bit / 14-Bit / 16_ Bit instruction sets (apart from differences in the supported subset of instructions)?
In particular: Can we be reasonably sure that the 14-Bit instruction set at https://free-pdk.github.io/PADAUK_FPPA_14_bit_instruction_set.html reflects the actual encoding for the PFS154?

Philipp

I updated the instruction set pages (13,14,16 bit) with all known stuff gathered from the contributors of this forum:

https://free-pdk.github.io/

JS
Please support me by using the AFFILIATE link to LCSC when you order PADAUK parts or tools. With the rewards I can order more PADAUK components for research.

THANK YOU!
 
The following users thanked this post: oPossum

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #176 on: December 04, 2018, 06:43:54 am »
15 bit instruction set

Used by PMS132K, PMS133, PMS134, PFS173, MCU371

Code: [Select]
0x0000  000_0000_0000_0000  nop
0x0001  000_0000_0000_0001
0x0002  000_0000_0000_001-
0x0004  000_0000_0000_01--
0x0008  000_0000_0000_1---
0x0010  000_0000_0001_----
0x0020  000_0000_001-_----
0x0040  000_0000_010-_----
0x0050  000_0000_0101_----
0x0060  000_0000_0110_0000  addc     a
0x0061  000_0000_0110_0001  subc     a
0x0062  000_0000_0110_0010  izsn     a
0x0063  000_0000_0110_0011  dzsn     a
0x0064  000_0000_0110_0100
0x0065  000_0000_0110_0101
0x0066  000_0000_0110_0110
0x0067  000_0000_0110_0111  pcadd    a
0x0068  000_0000_0110_1000  not      a
0x0069  000_0000_0110_1001  neg      a
0x006A  000_0000_0110_1010  sr       a
0x006B  000_0000_0110_1011  sl       a
0x006C  000_0000_0110_1100  src      a
0x006D  000_0000_0110_1101  slc      a
0x006E  000_0000_0110_1110  swap     a
0x006F  000_0000_0110_1111
0x0070  000_0000_0111_0000  wdreset
0x0071  000_0000_0111_0001
0x0072  000_0000_0111_0010  pushaf
0x0073  000_0000_0111_0011  popaf
0x0074  000_0000_0111_0100
0x0075  000_0000_0111_0101  reset
0x0076  000_0000_0111_0110  stopsys
0x0077  000_0000_0111_0111  stopexe
0x0078  000_0000_0111_1000  engint
0x0079  000_0000_0111_1001  disgint
0x007A  000_0000_0111_1010  ret
0x007B  000_0000_0111_1011  reti
0x007C  000_0000_0111_1100  mul
0x007D  000_0000_0111_1101
0x007E  000_0000_0111_1110
0x007F  000_0000_0111_1110
0x0080  000_0000_1ppp_pppp  xor      a,IO
0x0100  000_0001_0ppp_pppp  mov      IO,a
0x0180  000_0001_1ppp_pppp  mov      a,IO
0x0200  000_0010_kkkk_kkkk  ret      I
0x0300  000_0011_----_----
0x0400  000_0100_----_----
0x0500  000_0101_wwww_www0  ldtabl   word
0x0501  000_0101_wwww_www1  ldtabh   word
0x0600  000_0110_wwww_www0  stt16    word
0x0601  000_0110_wwww_www1  ldt16    word
0x0700  000_0111_wwww_www0  idxm     index,a
0x0701  000_0111_wwww_www1  idxm     a,index
0x0800  000_10--_----_----
0x0C00  000_1100_mmmm_mmmm  comp     a,M
0x0D00  000_1101_mmmm_mmmm  comp     M,a
0x0E00  000_1110_mmmm_mmmm  nadd     a,M
0x0F00  000_1111_mmmm_mmmm  nadd     M,a
0x1000  001_0000_mmmm_mmmm  add      M,a
0x1100  001_0001_mmmm_mmmm  sub      M,a
0x1200  001_0010_mmmm_mmmm  addc     M,a
0x1300  001_0011_mmmm_mmmm  subc     M,a
0x1400  001_0100_mmmm_mmmm  and      M,a
0x1500  001_0101_mmmm_mmmm  or       M,a
0x1600  001_0110_mmmm_mmmm  xor      M,a
0x1700  001_0111_mmmm_mmmm  mov      M,a
0x1800  001_1000_mmmm_mmmm  add      a,M
0x1900  001_1001_mmmm_mmmm  sub      a,M
0x1A00  001_1010_mmmm_mmmm  addc     a,M
0x1B00  001_1011_mmmm_mmmm  subc     a,M
0x1C00  001_1100_mmmm_mmmm  and      a,M
0x1D00  001_1101_mmmm_mmmm  or       a,M
0x1E00  001_1110_mmmm_mmmm  xor      a,M
0x1F00  001_1111_mmmm_mmmm  mov      a,M
0x2000  010_0000_mmmm_mmmm  addc     M
0x2100  010_0001_mmmm_mmmm  subc     M
0x2200  010_0010_mmmm_mmmm  izsn     M
0x2300  010_0011_mmmm_mmmm  dzsn     M
0x2400  010_0100_mmmm_mmmm  inc      M
0x2500  010_0101_mmmm_mmmm  dec      M
0x2600  010_0110_mmmm_mmmm  clear    M
0x2700  010_0111_mmmm_mmmm  xch      M
0x2800  010_1000_mmmm_mmmm  not      M
0x2900  010_1001_mmmm_mmmm  neg      M
0x2A00  010_1010_mmmm_mmmm  sr       M
0x2B00  010_1011_mmmm_mmmm  sl       M
0x2C00  010_1100_mmmm_mmmm  src      M
0x2D00  010_1101_mmmm_mmmm  slc      M
0x2E00  010_1110_mmmm_mmmm  ceqsn    a,M
0x2F00  010_1111_mmmm_mmmm  cneqsn   a,M
0x3000  011_00bb_bppp_pppp  t0sn     IO.n
0x3400  011_01bb_bppp_pppp  t1sn     IO.n
0x3800  011_10bb_bppp_pppp  set0     IO.n
0x3C00  011_11bb_bppp_pppp  set1     IO.n
0x4000  100_00bb_bmmm_mmmm  t0sn     M.n
0x4400  100_01bb_bmmm_mmmm  t1sn     M.n
0x4800  100_10bb_bmmm_mmmm  set0     M.n
0x4C00  100_11bb_bmmm_mmmm  set1     M.n
0x5000  101_0000_kkkk_kkkk  add      a,I
0x5100  101_0001_kkkk_kkkk  sub      a,I
0x5200  101_0010_kkkk_kkkk  ceqsn    a,I
0x5300  101_0011_kkkk_kkkk  cneqsn   a,I
0x5400  101_0100_kkkk_kkkk  and      a,I
0x5500  101_0101_kkkk_kkkk  or       a,I
0x5600  101_0110_kkkk_kkkk  xor      a,I
0x5700  101_0111_kkkk_kkkk  mov      a,I
0x5800  101_10--_----_----
0x5C00  101_11bb_bppp_pppp  swapc    IO.n
0x6000  110_aaaa_aaaa_aaaa  goto     label
0x7000  111_aaaa_aaaa_aaaa  call     label

 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #177 on: December 04, 2018, 07:00:00 am »
Edit: It's actually slightly different from the one posted above, but only single instructions and coherent with the encoding.
Probably the options I chose?

Yes, I think so. Different .ADJUST_IC options and different code size.
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #178 on: December 04, 2018, 07:09:57 am »
Just a reminder to myself:
the amount of addressable memory is (core size in bits - 3)
16 -> 13 -> 8192 words, Family 83A
15 -> 12 -> 4096 words, Family 86B
14 -> 11 -> 2048 words, Family 85A
13 -> 10 -> 1024 words, Family 84B

Also...

16 -> 13 -> 8192 words, Family 82A  [PMC882 PDK22C13 PDK22C13A PDK22C58 PDK22C58A PDK82C12 PDK82C13 PDK82S_EV]
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #179 on: December 04, 2018, 07:23:58 am »
16/15/14/13 bit instruction encoding sorted by 16 bit opcode
Code: [Select]
nop                 0000_0000_0000_0000   000_0000_0000_0000   00_0000_0000_0000   0_0000_0000_0000
ldsptl                                                         00_0000_0000_0110
ldspth                                                         00_0000_0000_0111
addc      a         0000_0000_0001_0000   000_0000_0110_0000   00_0000_0110_0000   0_0000_0001_0000
subc      a         0000_0000_0001_0001   000_0000_0110_0001   00_0000_0110_0001   0_0000_0001_0001
izsn      a         0000_0000_0001_0010   000_0000_0110_0010   00_0000_0110_0010   0_0000_0001_0010
dzsn      a         0000_0000_0001_0011   000_0000_0110_0011   00_0000_0110_0011   0_0000_0001_0011
pcadd     a         0000_0000_0001_0111   000_0000_0110_0111   00_0000_0110_0111   0_0000_0001_0111
not       a         0000_0000_0001_1000   000_0000_0110_1000   00_0000_0110_1000   0_0000_0001_1000
neg       a         0000_0000_0001_1001   000_0000_0110_1001   00_0000_0110_1001   0_0000_0001_1001
sr        a         0000_0000_0001_1010   000_0000_0110_1010   00_0000_0110_1010   0_0000_0001_1010
sl        a         0000_0000_0001_1011   000_0000_0110_1011   00_0000_0110_1011   0_0000_0001_1011
src       a         0000_0000_0001_1100   000_0000_0110_1100   00_0000_0110_1100   0_0000_0001_1100
slc       a         0000_0000_0001_1101   000_0000_0110_1101   00_0000_0110_1101   0_0000_0001_1101
swap      a         0000_0000_0001_1110   000_0000_0110_1110   00_0000_0110_1110   0_0000_0001_1110
delay     a         0000_0000_0001_1111
wdreset             0000_0000_0011_0000   000_0000_0111_0000   00_0000_0111_0000   0_0000_0011_0000
pushaf              0000_0000_0011_0010   000_0000_0111_0010   00_0000_0111_0010   0_0000_0011_0010
popaf               0000_0000_0011_0011   000_0000_0111_0011   00_0000_0111_0011   0_0000_0011_0011
reset               0000_0000_0011_0101   000_0000_0111_0101   00_0000_0111_0101   0_0000_0011_0101
stopsys             0000_0000_0011_0110   000_0000_0111_0110   00_0000_0111_0110   0_0000_0011_0110
stopexe             0000_0000_0011_0111   000_0000_0111_0111   00_0000_0111_0111   0_0000_0011_0111
engint              0000_0000_0011_1000   000_0000_0111_1000   00_0000_0111_1000   0_0000_0011_1000
disgint             0000_0000_0011_1001   000_0000_0111_1001   00_0000_0111_1001   0_0000_0011_1001
ret                 0000_0000_0011_1010   000_0000_0111_1010   00_0000_0111_1010   0_0000_0011_1010
reti                0000_0000_0011_1011   000_0000_0111_1011   00_0000_0111_1011   0_0000_0011_1011
mul                 0000_0000_0011_1100   000_0000_0111_1100   00_0000_0111_1100
pmode     n         0000_0000_010k_kkkk
popw      pcN       0000_0000_0110_tttt
pushw     pcN       0000_0000_0111_tttt
mov       IO,a      0000_0000_10pp_pppp   000_0001_0ppp_pppp   00_0001_10pp_pppp   0_0000_100p_pppp
mov       a,IO      0000_0000_11pp_pppp   000_0001_1ppp_pppp   00_0001_11pp_pppp   0_0000_101p_pppp
cneqsn    a,I       0000_0001_kkkk_kkkk   101_0011_kkkk_kkkk   10_1011_kkkk_kkkk   1_0011_kkkk_kkkk
stt16     word      0000_001w_wwww_www0   000_0110_wwww_www0   00_0011_0www_www0   0_0000_110w_www0
ldt16     word      0000_001w_wwww_www1   000_0110_wwww_www1   00_0011_0www_www1   0_0000_110w_www1
popw      word      0000_010w_wwww_www0
pushw     word      0000_010w_wwww_www1
igoto     word      0000_011w_wwww_www0
icall     word      0000_011w_wwww_www1
idxm      index,a   0000_100w_wwww_www0   000_0111_wwww_www0   00_0011_1www_www0   0_0000_111w_www0
idxm      a,index   0000_100w_wwww_www1   000_0111_wwww_www1   00_0011_1www_www1   0_0000_111w_www1
ldtabl    word      0000_101w_wwww_www0   000_0101_wwww_www0
ldtabh    word      0000_101w_wwww_www1   000_0101_wwww_www1
delay     I         0000_1110_kkkk_kkkk
ret       I         0000_1111_kkkk_kkkk   000_0010_kkkk_kkkk   00_0010_kkkk_kkkk   0_0001_kkkk_kkkk
xor       IO,a      0001_0000_00pp_pppp   000_0000_1ppp_pppp   00_0000_11pp_pppp   0_0000_011p_pppp
xor       a,IO      0001_0000_01pp_pppp
cneqsn    M,a       0001_010m_mmmm_mmmm
cneqsn    a,M       0001_011m_mmmm_mmmm   010_1111_mmmm_mmmm   01_0111_1mmm_mmmm   0_1011_11mm_mmmm
add       a,I       0001_1000_kkkk_kkkk   101_0000_kkkk_kkkk   10_1000_kkkk_kkkk   1_0000_kkkk_kkkk
sub       a,I       0001_1001_kkkk_kkkk   101_0001_kkkk_kkkk   10_1001_kkkk_kkkk   1_0001_kkkk_kkkk
ceqsn     a,I       0001_1010_kkkk_kkkk   101_0010_kkkk_kkkk   10_1010_kkkk_kkkk   1_0010_kkkk_kkkk
comp      a,I       0001_1011_kkkk_kkkk
and       a,I       0001_1100_kkkk_kkkk   101_0100_kkkk_kkkk   10_1100_kkkk_kkkk   1_0100_kkkk_kkkk
or        a,I       0001_1101_kkkk_kkkk   101_0101_kkkk_kkkk   10_1101_kkkk_kkkk   1_0101_kkkk_kkkk
xor       a,I       0001_1110_kkkk_kkkk   101_0110_kkkk_kkkk   10_1110_kkkk_kkkk   1_0110_kkkk_kkkk
mov       a,I       0001_1111_kkkk_kkkk   101_0111_kkkk_kkkk   10_1111_kkkk_kkkk   1_0111_kkkk_kkkk
t0sn      IO.n      0010_000b_bbpp_pppp   011_00bb_bppp_pppp   01_100b_bbpp_pppp   0_1100_bbbp_pppp
t1sn      IO.n      0010_001b_bbpp_pppp   011_01bb_bppp_pppp   01_101b_bbpp_pppp   0_1101_bbbp_pppp
set0      IO.n      0010_010b_bbpp_pppp   011_10bb_bppp_pppp   01_110b_bbpp_pppp   0_1110_bbbp_pppp
set1      IO.n      0010_011b_bbpp_pppp   011_11bb_bppp_pppp   01_111b_bbpp_pppp   0_1111_bbbp_pppp
tog       IO.n      0010_100b_bbpp_pppp
wait0     IO.n      0010_101b_bbpp_pppp
wait1     IO.n      0010_110b_bbpp_pppp
swapc     IO.n      0010_111b_bbpp_pppp   101_11bb_bppp_pppp   00_010b_bbpp_pppp
nmov      M,a       0011_000m_mmmm_mmmm
nmov      a,M       0011_001m_mmmm_mmmm
nadd      M,a       0011_010m_mmmm_mmmm   000_1111_mmmm_mmmm   00_0111_1mmm_mmmm
nadd      a,M       0011_011m_mmmm_mmmm   000_1110_mmmm_mmmm   00_0111_0mmm_mmmm
ceqsn     M,a       0011_100m_mmmm_mmmm
ceqsn     a,M       0011_101m_mmmm_mmmm   010_1110_mmmm_mmmm   01_0111_0mmm_mmmm   0_1011_10mm_mmmm
comp      M,a       0011_110m_mmmm_mmmm   000_1101_mmmm_mmmm   00_0110_1mmm_mmmm
comp      a,M       0011_111m_mmmm_mmmm   000_1100_mmmm_mmmm   00_0110_0mmm_mmmm
add       M,a       0100_000m_mmmm_mmmm   001_0000_mmmm_mmmm   00_1000_0mmm_mmmm   0_0100_00mm_mmmm
add       a,M       0100_001m_mmmm_mmmm   001_1000_mmmm_mmmm   00_1100_0mmm_mmmm   0_0110_00mm_mmmm
sub       M,a       0100_010m_mmmm_mmmm   001_0001_mmmm_mmmm   00_1000_1mmm_mmmm   0_0100_01mm_mmmm
sub       a,M       0100_011m_mmmm_mmmm   001_1001_mmmm_mmmm   00_1100_1mmm_mmmm   0_0110_01mm_mmmm
addc      M,a       0100_100m_mmmm_mmmm   001_0010_mmmm_mmmm   00_1001_0mmm_mmmm   0_0100_10mm_mmmm
addc      a,M       0100_101m_mmmm_mmmm   001_1010_mmmm_mmmm   00_1101_0mmm_mmmm   0_0110_10mm_mmmm
subc      M,a       0100_110m_mmmm_mmmm   001_0011_mmmm_mmmm   00_1001_1mmm_mmmm   0_0100_11mm_mmmm
subc      a,M       0100_111m_mmmm_mmmm   001_1011_mmmm_mmmm   00_1101_1mmm_mmmm   0_0110_11mm_mmmm
and       M,a       0101_000m_mmmm_mmmm   001_0100_mmmm_mmmm   00_1010_0mmm_mmmm   0_0101_00mm_mmmm
and       a,M       0101_001m_mmmm_mmmm   001_1100_mmmm_mmmm   00_1110_0mmm_mmmm   0_0111_00mm_mmmm
or        M,a       0101_010m_mmmm_mmmm   001_0101_mmmm_mmmm   00_1010_1mmm_mmmm   0_0101_01mm_mmmm
or        a,M       0101_011m_mmmm_mmmm   001_1101_mmmm_mmmm   00_1110_1mmm_mmmm   0_0111_01mm_mmmm
xor       M,a       0101_100m_mmmm_mmmm   001_0110_mmmm_mmmm   00_1011_0mmm_mmmm   0_0101_10mm_mmmm
xor       a,M       0101_101m_mmmm_mmmm   001_1110_mmmm_mmmm   00_1111_0mmm_mmmm   0_0111_10mm_mmmm
mov       M,a       0101_110m_mmmm_mmmm   001_0111_mmmm_mmmm   00_1011_1mmm_mmmm   0_0101_11mm_mmmm
mov       a,M       0101_111m_mmmm_mmmm   001_1111_mmmm_mmmm   00_1111_1mmm_mmmm   0_0111_11mm_mmmm
addc      M         0110_000m_mmmm_mmmm   010_0000_mmmm_mmmm   01_0000_0mmm_mmmm   0_1000_00mm_mmmm
subc      M         0110_001m_mmmm_mmmm   010_0001_mmmm_mmmm   01_0000_1mmm_mmmm   0_1000_01mm_mmmm
izsn      M         0110_010m_mmmm_mmmm   010_0010_mmmm_mmmm   01_0001_0mmm_mmmm   0_1000_10mm_mmmm
dzsn      M         0110_011m_mmmm_mmmm   010_0011_mmmm_mmmm   01_0001_1mmm_mmmm   0_1000_11mm_mmmm
inc       M         0110_100m_mmmm_mmmm   010_0100_mmmm_mmmm   01_0010_0mmm_mmmm   0_1001_00mm_mmmm
dec       M         0110_101m_mmmm_mmmm   010_0101_mmmm_mmmm   01_0010_1mmm_mmmm   0_1001_01mm_mmmm
clear     M         0110_110m_mmmm_mmmm   010_0110_mmmm_mmmm   01_0011_0mmm_mmmm   0_1001_10mm_mmmm
xch       M         0110_111m_mmmm_mmmm   010_0111_mmmm_mmmm   01_0011_1mmm_mmmm   0_1001_11mm_mmmm
not       M         0111_000m_mmmm_mmmm   010_1000_mmmm_mmmm   01_0100_0mmm_mmmm   0_1010_00mm_mmmm
neg       M         0111_001m_mmmm_mmmm   010_1001_mmmm_mmmm   01_0100_1mmm_mmmm   0_1010_01mm_mmmm
sr        M         0111_010m_mmmm_mmmm   010_1010_mmmm_mmmm   01_0101_0mmm_mmmm   0_1010_10mm_mmmm
sl        M         0111_011m_mmmm_mmmm   010_1011_mmmm_mmmm   01_0101_1mmm_mmmm   0_1010_11mm_mmmm
src       M         0111_100m_mmmm_mmmm   010_1100_mmmm_mmmm   01_0110_0mmm_mmmm   0_1011_00mm_mmmm
slc       M         0111_101m_mmmm_mmmm   010_1101_mmmm_mmmm   01_0110_1mmm_mmmm   0_1011_01mm_mmmm
swap      M         0111_110m_mmmm_mmmm
delay     M         0111_111m_mmmm_mmmm
t0sn      M.n       1000_bbbm_mmmm_mmmm   100_00bb_bmmm_mmmm   10_000b_bbmm_mmmm   0_0010_bbb0_mmmm
t1sn      M.n       1001_bbbm_mmmm_mmmm   100_01bb_bmmm_mmmm   10_001b_bbmm_mmmm   0_0010_bbb1_mmmm
set0      M.n       1010_bbbm_mmmm_mmmm   100_10bb_bmmm_mmmm   10_010b_bbmm_mmmm   0_0011_bbb0_mmmm
set1      M.n       1011_bbbm_mmmm_mmmm   100_11bb_bmmm_mmmm   10_011b_bbmm_mmmm   0_0011_bbb1_mmmm
goto      label     110a_aaaa_aaaa_aaaa   110_aaaa_aaaa_aaaa   11_0aaa_aaaa_aaaa   1_10aa_aaaa_aaaa
call      label     111a_aaaa_aaaa_aaaa   111_aaaa_aaaa_aaaa   11_1aaa_aaaa_aaaa   1_11aa_aaaa_aaaa


16/15/14/13 bit instruction encoding sorted by mnemonic
Code: [Select]
add       a,I       0001_1000_kkkk_kkkk   101_0000_kkkk_kkkk   10_1000_kkkk_kkkk   1_0000_kkkk_kkkk
add       a,M       0100_001m_mmmm_mmmm   001_1000_mmmm_mmmm   00_1100_0mmm_mmmm   0_0110_00mm_mmmm
add       M,a       0100_000m_mmmm_mmmm   001_0000_mmmm_mmmm   00_1000_0mmm_mmmm   0_0100_00mm_mmmm
addc      a         0000_0000_0001_0000   000_0000_0110_0000   00_0000_0110_0000   0_0000_0001_0000
addc      a,M       0100_101m_mmmm_mmmm   001_1010_mmmm_mmmm   00_1101_0mmm_mmmm   0_0110_10mm_mmmm
addc      M         0110_000m_mmmm_mmmm   010_0000_mmmm_mmmm   01_0000_0mmm_mmmm   0_1000_00mm_mmmm
addc      M,a       0100_100m_mmmm_mmmm   001_0010_mmmm_mmmm   00_1001_0mmm_mmmm   0_0100_10mm_mmmm
and       a,I       0001_1100_kkkk_kkkk   101_0100_kkkk_kkkk   10_1100_kkkk_kkkk   1_0100_kkkk_kkkk
and       a,M       0101_001m_mmmm_mmmm   001_1100_mmmm_mmmm   00_1110_0mmm_mmmm   0_0111_00mm_mmmm
and       M,a       0101_000m_mmmm_mmmm   001_0100_mmmm_mmmm   00_1010_0mmm_mmmm   0_0101_00mm_mmmm
call      label     111a_aaaa_aaaa_aaaa   111_aaaa_aaaa_aaaa   11_1aaa_aaaa_aaaa   1_11aa_aaaa_aaaa
ceqsn     a,I       0001_1010_kkkk_kkkk   101_0010_kkkk_kkkk   10_1010_kkkk_kkkk   1_0010_kkkk_kkkk
ceqsn     a,M       0011_101m_mmmm_mmmm   010_1110_mmmm_mmmm   01_0111_0mmm_mmmm   0_1011_10mm_mmmm
ceqsn     M,a       0011_100m_mmmm_mmmm
clear     M         0110_110m_mmmm_mmmm   010_0110_mmmm_mmmm   01_0011_0mmm_mmmm   0_1001_10mm_mmmm
cneqsn    a,I       0000_0001_kkkk_kkkk   101_0011_kkkk_kkkk   10_1011_kkkk_kkkk   1_0011_kkkk_kkkk
cneqsn    a,M       0001_011m_mmmm_mmmm   010_1111_mmmm_mmmm   01_0111_1mmm_mmmm   0_1011_11mm_mmmm
cneqsn    M,a       0001_010m_mmmm_mmmm
comp      a,I       0001_1011_kkkk_kkkk
comp      a,M       0011_111m_mmmm_mmmm   000_1100_mmmm_mmmm   00_0110_0mmm_mmmm
comp      M,a       0011_110m_mmmm_mmmm   000_1101_mmmm_mmmm   00_0110_1mmm_mmmm
dec       M         0110_101m_mmmm_mmmm   010_0101_mmmm_mmmm   01_0010_1mmm_mmmm   0_1001_01mm_mmmm
delay     a         0000_0000_0001_1111
delay     I         0000_1110_kkkk_kkkk
delay     M         0111_111m_mmmm_mmmm
disgint             0000_0000_0011_1001   000_0000_0111_1001   00_0000_0111_1001   0_0000_0011_1001
dzsn      a         0000_0000_0001_0011   000_0000_0110_0011   00_0000_0110_0011   0_0000_0001_0011
dzsn      M         0110_011m_mmmm_mmmm   010_0011_mmmm_mmmm   01_0001_1mmm_mmmm   0_1000_11mm_mmmm
engint              0000_0000_0011_1000   000_0000_0111_1000   00_0000_0111_1000   0_0000_0011_1000
goto      label     110a_aaaa_aaaa_aaaa   110_aaaa_aaaa_aaaa   11_0aaa_aaaa_aaaa   1_10aa_aaaa_aaaa
icall     word      0000_011w_wwww_www1
idxm      a,index   0000_100w_wwww_www1   000_0111_wwww_www1   00_0011_1www_www1   0_0000_111w_www1
idxm      index,a   0000_100w_wwww_www0   000_0111_wwww_www0   00_0011_1www_www0   0_0000_111w_www0
igoto     word      0000_011w_wwww_www0
inc       M         0110_100m_mmmm_mmmm   010_0100_mmmm_mmmm   01_0010_0mmm_mmmm   0_1001_00mm_mmmm
izsn      a         0000_0000_0001_0010   000_0000_0110_0010   00_0000_0110_0010   0_0000_0001_0010
izsn      M         0110_010m_mmmm_mmmm   010_0010_mmmm_mmmm   01_0001_0mmm_mmmm   0_1000_10mm_mmmm
ldspth                                                         00_0000_0000_0111
ldsptl                                                         00_0000_0000_0110
ldt16     word      0000_001w_wwww_www1   000_0110_wwww_www1   00_0011_0www_www1   0_0000_110w_www1
ldtabh    word      0000_101w_wwww_www1   000_0101_wwww_www1
ldtabl    word      0000_101w_wwww_www0   000_0101_wwww_www0
mov       a,I       0001_1111_kkkk_kkkk   101_0111_kkkk_kkkk   10_1111_kkkk_kkkk   1_0111_kkkk_kkkk
mov       a,IO      0000_0000_11pp_pppp   000_0001_1ppp_pppp   00_0001_11pp_pppp   0_0000_101p_pppp
mov       a,M       0101_111m_mmmm_mmmm   001_1111_mmmm_mmmm   00_1111_1mmm_mmmm   0_0111_11mm_mmmm
mov       IO,a      0000_0000_10pp_pppp   000_0001_0ppp_pppp   00_0001_10pp_pppp   0_0000_100p_pppp
mov       M,a       0101_110m_mmmm_mmmm   001_0111_mmmm_mmmm   00_1011_1mmm_mmmm   0_0101_11mm_mmmm
mul                 0000_0000_0011_1100   000_0000_0111_1100   00_0000_0111_1100
nadd      a,M       0011_011m_mmmm_mmmm   000_1110_mmmm_mmmm   00_0111_0mmm_mmmm
nadd      M,a       0011_010m_mmmm_mmmm   000_1111_mmmm_mmmm   00_0111_1mmm_mmmm
neg       a         0000_0000_0001_1001   000_0000_0110_1001   00_0000_0110_1001   0_0000_0001_1001
neg       M         0111_001m_mmmm_mmmm   010_1001_mmmm_mmmm   01_0100_1mmm_mmmm   0_1010_01mm_mmmm
nmov      a,M       0011_001m_mmmm_mmmm
nmov      M,a       0011_000m_mmmm_mmmm
nop                 0000_0000_0000_0000   000_0000_0000_0000   00_0000_0000_0000   0_0000_0000_0000
not       a         0000_0000_0001_1000   000_0000_0110_1000   00_0000_0110_1000   0_0000_0001_1000
not       M         0111_000m_mmmm_mmmm   010_1000_mmmm_mmmm   01_0100_0mmm_mmmm   0_1010_00mm_mmmm
or        a,I       0001_1101_kkkk_kkkk   101_0101_kkkk_kkkk   10_1101_kkkk_kkkk   1_0101_kkkk_kkkk
or        a,M       0101_011m_mmmm_mmmm   001_1101_mmmm_mmmm   00_1110_1mmm_mmmm   0_0111_01mm_mmmm
or        M,a       0101_010m_mmmm_mmmm   001_0101_mmmm_mmmm   00_1010_1mmm_mmmm   0_0101_01mm_mmmm
pcadd     a         0000_0000_0001_0111   000_0000_0110_0111   00_0000_0110_0111   0_0000_0001_0111
pmode     n         0000_0000_010k_kkkk
popaf               0000_0000_0011_0011   000_0000_0111_0011   00_0000_0111_0011   0_0000_0011_0011
popw      pcN       0000_0000_0110_tttt
popw      word      0000_010w_wwww_www0
pushaf              0000_0000_0011_0010   000_0000_0111_0010   00_0000_0111_0010   0_0000_0011_0010
pushw     pcN       0000_0000_0111_tttt
pushw     word      0000_010w_wwww_www1
reset               0000_0000_0011_0101   000_0000_0111_0101   00_0000_0111_0101   0_0000_0011_0101
ret                 0000_0000_0011_1010   000_0000_0111_1010   00_0000_0111_1010   0_0000_0011_1010
ret       I         0000_1111_kkkk_kkkk   000_0010_kkkk_kkkk   00_0010_kkkk_kkkk   0_0001_kkkk_kkkk
reti                0000_0000_0011_1011   000_0000_0111_1011   00_0000_0111_1011   0_0000_0011_1011
set0      IO.n      0010_010b_bbpp_pppp   011_10bb_bppp_pppp   01_110b_bbpp_pppp   0_1110_bbbp_pppp
set0      M.n       1010_bbbm_mmmm_mmmm   100_10bb_bmmm_mmmm   10_010b_bbmm_mmmm   0_0011_bbb0_mmmm
set1      IO.n      0010_011b_bbpp_pppp   011_11bb_bppp_pppp   01_111b_bbpp_pppp   0_1111_bbbp_pppp
set1      M.n       1011_bbbm_mmmm_mmmm   100_11bb_bmmm_mmmm   10_011b_bbmm_mmmm   0_0011_bbb1_mmmm
sl        a         0000_0000_0001_1011   000_0000_0110_1011   00_0000_0110_1011   0_0000_0001_1011
sl        M         0111_011m_mmmm_mmmm   010_1011_mmmm_mmmm   01_0101_1mmm_mmmm   0_1010_11mm_mmmm
slc       a         0000_0000_0001_1101   000_0000_0110_1101   00_0000_0110_1101   0_0000_0001_1101
slc       M         0111_101m_mmmm_mmmm   010_1101_mmmm_mmmm   01_0110_1mmm_mmmm   0_1011_01mm_mmmm
sr        a         0000_0000_0001_1010   000_0000_0110_1010   00_0000_0110_1010   0_0000_0001_1010
sr        M         0111_010m_mmmm_mmmm   010_1010_mmmm_mmmm   01_0101_0mmm_mmmm   0_1010_10mm_mmmm
src       a         0000_0000_0001_1100   000_0000_0110_1100   00_0000_0110_1100   0_0000_0001_1100
src       M         0111_100m_mmmm_mmmm   010_1100_mmmm_mmmm   01_0110_0mmm_mmmm   0_1011_00mm_mmmm
stopexe             0000_0000_0011_0111   000_0000_0111_0111   00_0000_0111_0111   0_0000_0011_0111
stopsys             0000_0000_0011_0110   000_0000_0111_0110   00_0000_0111_0110   0_0000_0011_0110
stt16     word      0000_001w_wwww_www0   000_0110_wwww_www0   00_0011_0www_www0   0_0000_110w_www0
sub       a,I       0001_1001_kkkk_kkkk   101_0001_kkkk_kkkk   10_1001_kkkk_kkkk   1_0001_kkkk_kkkk
sub       a,M       0100_011m_mmmm_mmmm   001_1001_mmmm_mmmm   00_1100_1mmm_mmmm   0_0110_01mm_mmmm
sub       M,a       0100_010m_mmmm_mmmm   001_0001_mmmm_mmmm   00_1000_1mmm_mmmm   0_0100_01mm_mmmm
subc      a         0000_0000_0001_0001   000_0000_0110_0001   00_0000_0110_0001   0_0000_0001_0001
subc      a,M       0100_111m_mmmm_mmmm   001_1011_mmmm_mmmm   00_1101_1mmm_mmmm   0_0110_11mm_mmmm
subc      M         0110_001m_mmmm_mmmm   010_0001_mmmm_mmmm   01_0000_1mmm_mmmm   0_1000_01mm_mmmm
subc      M,a       0100_110m_mmmm_mmmm   001_0011_mmmm_mmmm   00_1001_1mmm_mmmm   0_0100_11mm_mmmm
swap      a         0000_0000_0001_1110   000_0000_0110_1110   00_0000_0110_1110   0_0000_0001_1110
swap      M         0111_110m_mmmm_mmmm
swapc     IO.n      0010_111b_bbpp_pppp   101_11bb_bppp_pppp   00_010b_bbpp_pppp
t0sn      IO.n      0010_000b_bbpp_pppp   011_00bb_bppp_pppp   01_100b_bbpp_pppp   0_1100_bbbp_pppp
t0sn      M.n       1000_bbbm_mmmm_mmmm   100_00bb_bmmm_mmmm   10_000b_bbmm_mmmm   0_0010_bbb0_mmmm
t1sn      IO.n      0010_001b_bbpp_pppp   011_01bb_bppp_pppp   01_101b_bbpp_pppp   0_1101_bbbp_pppp
t1sn      M.n       1001_bbbm_mmmm_mmmm   100_01bb_bmmm_mmmm   10_001b_bbmm_mmmm   0_0010_bbb1_mmmm
tog       IO.n      0010_100b_bbpp_pppp
wait0     IO.n      0010_101b_bbpp_pppp
wait1     IO.n      0010_110b_bbpp_pppp
wdreset             0000_0000_0011_0000   000_0000_0111_0000   00_0000_0111_0000   0_0000_0011_0000
xch       M         0110_111m_mmmm_mmmm   010_0111_mmmm_mmmm   01_0011_1mmm_mmmm   0_1001_11mm_mmmm
xor       a,I       0001_1110_kkkk_kkkk   101_0110_kkkk_kkkk   10_1110_kkkk_kkkk   1_0110_kkkk_kkkk
xor       a,IO      0001_0000_01pp_pppp
xor       a,M       0101_101m_mmmm_mmmm   001_1110_mmmm_mmmm   00_1111_0mmm_mmmm   0_0111_10mm_mmmm
xor       IO,a      0001_0000_00pp_pppp   000_0000_1ppp_pppp   00_0000_11pp_pppp   0_0000_011p_pppp
xor       M,a       0101_100m_mmmm_mmmm   001_0110_mmmm_mmmm   00_1011_0mmm_mmmm   0_0101_10mm_mmmm

 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #180 on: December 04, 2018, 07:30:32 am »

On the second day, wrt. completeness of implementation of the C standard, this has now far surpassed Mini-C.


Well done! Seems to be doing its job.

Code: [Select]
unsigned int a = 15;
unsigned int b = 23;
unsigned int c;

void
main( void ) {
while (c < a * b) {
c += a;
}
}

Weird: The compiler doesnt seem to realize that a*b will always be constant (even if I declare both variables as const and they land in the const segment).
Is that an optimization step?

Code: [Select]
...
_main:
; test.c: 7: while (c < a * b) {
00101$:
mov a, _a+0
mov __mulint_PARM_1+0, a
mov a, _a+1
mov __mulint_PARM_1+1, a
mov a, _b+0
mov __mulint_PARM_2+0, a
mov a, _b+1
mov __mulint_PARM_2+1, a
call __mulint
mov _main_sloc0_1_0+0, a
mov a, p
mov _main_sloc0_1_0+1, a
mov a, _c+0
sub a, _main_sloc0_1_0+0
mov a, _c+1
subc a, _main_sloc0_1_0+1
mov a, #0x00
slc a
mov _main_sloc1_1_0+0, a
mov a, _main_sloc1_1_0+0
cneqsn a, #0x00
goto 00104$
; test.c: 8: c += a;
mov a, _c+0
add a, _a+0
mov _c+0, a
mov a, _c+1
addc a, _a+1
mov _c+1, a
goto 00101$
00104$:
; test.c: 10: }
ret
...
__xinit__a:
.dw #0x000f
__xinit__b:
.dw #0x0017

Although init code seems to be missing and I get lot of this:

Code: [Select]
test.asm:60: Error: <a> machine specific addressing or addressing mode error
test.asm:61: Error: <a> machine specific addressing or addressing mode error
test.asm:62: Error: <a> machine specific addressing or addressing mode error
test.asm:63: Error: <a> machine specific addressing or addressing mode error
test.asm:64: Error: <a> machine specific addressing or addressing mode error
test.asm:65: Error: <a> machine specific addressing or addressing mode error
test.asm:66: Error: <a> machine specific addressing or addressing mode error
test.asm:67: Error: <a> machine specific addressing or addressing mode error
test.asm:69: Error: <a> machine specific addressing or addressing mode error
test.asm:70: Error: <a> machine specific addressing or addressing mode error
test.asm:71: Error: <a> machine specific addressing or addressing mode error
test.asm:72: Error: <a> machine specific addressing or addressing mode error
test.asm:74: Error: <a> machine specific addressing or addressing mode error
test.asm:75: Error: <o> .org in REL area or directive / mnemonic error
test.asm:76: Error: <a> machine specific addressing or addressing mode error
test.asm:77: Error: <o> .org in REL area or directive / mnemonic error
test.asm:78: Error: <a> machine specific addressing or addressing mode error
test.asm:79: Error: <a> machine specific addressing or addressing mode error
test.asm:80: Error: <o> .org in REL area or directive / mnemonic error
test.asm:81: Error: <q> missing or improper operators, terminators, or delimiters
test.asm:83: Error: <a> machine specific addressing or addressing mode error
test.asm:85: Error: <a> machine specific addressing or addressing mode error
test.asm:86: Error: <a> machine specific addressing or addressing mode error
test.asm:87: Error: <o> .org in REL area or directive / mnemonic error
test.asm:88: Error: <a> machine specific addressing or addressing mode error
test.asm:89: Error: <q> missing or improper operators, terminators, or delimiters
removing test.rel
« Last Edit: December 04, 2018, 07:47:57 am by DocBen »
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #181 on: December 04, 2018, 03:14:49 pm »
PFS173 startup code

Edit: fixed disassembler bug that caused IO addresses > 63 to be incorrect, and all bit addresses to be incorrect

Code: [Select]
PDK version: 20
PDK data size:  3072 words
Free data size: 3040 words
MCU: PFS173 [ID: 0x2AA2]
Compiler version: 0.84
15 bit core
0000  5700  mov       a, 0x00
0001  0102  mov       SP, a
0002  7BED  call      0x0BED
0003  010B  mov       IHRCR, a
0004  7BEE  call      0x0BEE
0005  0163  mov       BGTR, a
0006  5770  mov       a, 0x70
0007  0128  mov       MISC_LVR, a
0008  573C  mov       a, 0x3C
0009  0103  mov       CLKCMD, a
000A  57F9  mov       a, 0xF9
000B  010D  mov       PADIER, a
000C  57FF  mov       a, 0xFF
000D  010E  mov       PBDIER, a
000E  570F  mov       a, 0x0F
000F  010F  mov       PCDIER, a
0010  5700  mov       a, 0x00
0011  0167  mov       ROP, a
0012  7BFE  call      0x0BFE
0013  52FF  ceqsn     a, 0xFF
0014  6059  goto      0x0059
0015  7BED  call      0x0BED
0016  1701  mov       M1, a
0017  3F11  set1      PAC.6
0018  5709  mov       a, 0x09
0019  1700  mov       M0, a
001A  3590  t1sn      PA.3
001B  601A  goto      0x001A
001C  3F10  set1      PA.6
001D  0063  dzsn      a
001E  601D  goto      0x001D
001F  2300  dzsn      M0
0020  601D  goto      0x001D
0021  3B10  set0      PA.6
0022  3190  t0sn      PA.3
0023  6022  goto      0x0022
0024  5701  mov       a, 0x01
0025  3290  t0sn      PA.5
0026  57FF  mov       a, 0xFF
0027  1801  add       a, M1
0028  010B  mov       IHRCR, a
0029  1701  mov       M1, a
002A  3590  t1sn      PA.3
002B  602A  goto      0x002A
002C  3690  t1sn      PA.5
002D  6054  goto      0x0054
002E  5704  mov       a, 0x04
002F  0126  mov       MISC, a
0030  3190  t0sn      PA.3
0031  6030  goto      0x0030
0032  2604  clear     M4
0033  2605  clear     M5
0034  575A  mov       a, 0x5A
0035  1702  mov       M2, a
0036  5700  mov       a, 0x00
0037  1703  mov       M3, a
0038  0502  ldtabl    M2
0039  1604  xor       M4, a
003A  0503  ldtabh    M2
003B  1005  add       M5, a
003C  2B04  sl        M4
003D  2D05  slc       M5
003E  2004  addc      M4
003F  2502  dec       M2
0040  2103  subc      M3
0041  3480  t1sn      FLAG.C
0042  6038  goto      0x0038
0043  3F10  set1      PA.6
0044  3590  t1sn      PA.3
0045  6044  goto      0x0044
0046  2B04  sl        M4
0047  2D05  slc       M5
0048  5F10  swapc     PA.6
0049  3190  t0sn      PA.3
004A  6049  goto      0x0049
004B  3290  t0sn      PA.5
004C  6044  goto      0x0044
004D  3B10  set0      PA.6
004E  3590  t1sn      PA.3
004F  604E  goto      0x004E
0050  3190  t0sn      PA.3
0051  6050  goto      0x0050
0052  3690  t1sn      PA.5
0053  6032  goto      0x0032
0054  3190  t0sn      PA.3
0055  6054  goto      0x0054
0056  3690  t1sn      PA.5
0057  6018  goto      0x0018
0058  6058  goto      0x0058
0059  010B  mov       IHRCR, a
005A  605A  goto      0x005A
005B  7FFF  call      0x0FFF
005C  7FFF  call      0x0FFF
005D  7FFF  call      0x0FFF
005E  7FFF  call      0x0FFF
005F  7FFF  call      0x0FFF
0060  7FFF  call      0x0FFF
...
0BE0  7FFF  call      0x0FFF
0BE1  7FFF  call      0x0FFF
0BE2  7FFF  call      0x0FFF
0BE3  7FFF  call      0x0FFF
0BE4  7FFF  call      0x0FFF
0BE5  7FFF  call      0x0FFF
0BE6  7FFF  call      0x0FFF
0BE7  7FFF  call      0x0FFF
0BE8  7FFF  call      0x0FFF
0BE9  7FFF  call      0x0FFF
0BEA  7FFF  call      0x0FFF
0BEB  7FFF  call      0x0FFF
0BEC  7FFF  call      0x0FFF
0BED  7FFF  call      0x0FFF
0BEE  7FFF  call      0x0FFF
0BEF  3FFE  set1      io.126.7
0BF0  7FFF  call      0x0FFF
0BF1  7FFF  call      0x0FFF
0BF2  7FFF  call      0x0FFF
0BF3  7FFF  call      0x0FFF
0BF4  7FFF  call      0x0FFF
0BF5  7FFF  call      0x0FFF
0BF6  7FFF  call      0x0FFF
0BF7  7FFF  call      0x0FFF
0BF8  0000  nop
0BF9  0000  nop
0BFA  7FFF  call      0x0FFF
0BFB  7FFF  call      0x0FFF
0BFC  7FFF  call      0x0FFF
0BFD  7FFF  call      0x0FFF
0BFE  7FFF  call      0x0FFF
0BFF  7AFC  call      0x0AFC
« Last Edit: December 05, 2018, 02:41:04 pm by oPossum »
 
The following users thanked this post: DocBen

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #182 on: December 04, 2018, 06:16:17 pm »
Now that the software side seems on track, how about some hardware engineering?

It should be possible to program the chips with xFFF so they stay fresh and useable.
Just for a quick peek at what the programmer does.
We should now be able to distinguish between the programming phase and the bit-banged calibration.
Maybe start with the PFS154 (dont have a programmer, I do have an arduino ;)? I have some of those and I suspect that reprogrammable chips are most interesting at this stage.

Or maybe analyse the bitstream from the Cypress chip to the FPGA on the ICE so we can understand what chip is being used?
Or even simpler: take the FPGA out and see whether the ICE even notices ;)

Anyone?
« Last Edit: December 04, 2018, 08:45:11 pm by DocBen »
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #183 on: December 04, 2018, 08:58:45 pm »
Although init code seems to be missing and I get lot of this:

Code: [Select]
test.asm:60: Error: <a> machine specific addressing or addressing mode error
[…]

You can compile to asm using -S to avoid those error messages (without -S, SDCC tries to invoke an Assembler, which currently happens to be one for STM8).

Philipp
 
The following users thanked this post: DocBen

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #184 on: December 04, 2018, 11:51:04 pm »
Ok, with that the error messages are now

Code: [Select]


Nice  :)
 

Offline FrankBuss

  • Supporter
  • ****
  • Posts: 2087
  • Country: de
    • Frank Buss
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #185 on: December 04, 2018, 11:54:14 pm »
Now that the software side seems on track, how about some hardware engineering?

It should be possible to program the chips with xFFF so they stay fresh and useable.
Just for a quick peek at what the programmer does.
We should now be able to distinguish between the programming phase and the bit-banged calibration.

Currently I'm designing a 4 channel (optionally 8 channel) ADC with at least 10 MHz sample rate and 1 GB RAM:

http://www.eevblog.com/forum/projects/4-channel-adc-10-mhz-8-bit-design/

Parts are ordered, I just need to layout it and order the PCB, then write the software for the DE10 Nano for it. Might need a few weeks, but then I can sample a full programming cycle with all pins in parallel. This should make it much easier to reverse engineer the exact protocol and to reproduce it. The software should be no problem, I've done this before.
So Long, and Thanks for All the Fish
 
The following users thanked this post: DocBen

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #186 on: December 05, 2018, 12:38:17 am »
I ran the regression tests in sdcc/src/regression and most of them seem to run fine.
Sometimes there are "FATAL Compiler Internal Error" that are specfic to the pdk14 backend

find -iname \*\.c -exec sh -c "echo {} ; sdcc -S -mpdk14 {}" \;

Code: [Select]
./switch1.c
./rotate6.c
./rotate6.c:86: warning 94: comparison is always true due to limited range of data type
./rotate6.c:84: warning 158: overflow in implicit constant conversion
./rotate6.c:121: warning 158: overflow in implicit constant conversion
./compare3.c
./compare3.c:151: warning 94: comparison is always false due to limited range of data type
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:173: warning 94: comparison is always false due to limited range of data type
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./rotate1.c
./compare7.c
In file included from ./compare7.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./compare5.c
./compare5.c:219: warning 94: comparison is always false due to limited range of data type
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:242: warning 94: comparison is always false due to limited range of data type
./compare5.c:271: warning 94: comparison is always false due to limited range of data type
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare6.c
Backtrace:
sdcc(+0xa4bce)[0x55b8eaabbbce]
sdcc(+0x1d73a7)[0x55b8eabee3a7]
sdcc(+0x1d7946)[0x55b8eabee946]
sdcc(+0x1d9c1e)[0x55b8eabf0c1e]
sdcc(+0x1d671e)[0x55b8eabed71e]
sdcc(+0x3c35c)[0x55b8eaa5335c]
sdcc(+0x568b0)[0x55b8eaa6d8b0]
sdcc(+0x1fe9f)[0x55b8eaa36e9f]
sdcc(+0x1be86)[0x55b8eaa32e86]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x7fde56ffdb97]
sdcc(+0x1d7aa)[0x55b8eaa347aa]
./compare6.c:165: error 9: FATAL Compiler Internal Error in file 'gen.c' line number '265' : code generator internal error
Contact Author with source code
Caught signal 11: SIGSEGV
./bool2.c
./nestfor.c
In file included from ./nestfor.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./pcodeopt.c
./struct1.c
./compare8.c
In file included from ./compare8.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./rotate3.c
./ptrarg.c
./add3.c
./add3.c:64: warning 94: comparison is always true due to limited range of data type
./rotate2.c
./call1.c
./bool1.c
./compare4.c
./compare4.c:63: warning 94: comparison is always false due to limited range of data type
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:93: warning 94: comparison is always false due to limited range of data type
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:250: warning 94: comparison is always true due to limited range of data type
./compare4.c:294: warning 158: overflow in implicit constant conversion
./compare4.c:304: warning 158: overflow in implicit constant conversion
./compare4.c:313: warning 158: overflow in implicit constant conversion
./rotate4.c
./rotate4.c:30: error 9: FATAL Compiler Internal Error in file 'gen.c' line number '1520' : Unimplemented iCode
Contact Author with source code
./add2.c
./compare10.c
In file included from ./compare10.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./inline.c
In file included from ./inline.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./rotate5.c
./rotate5.c:179: warning 158: overflow in implicit constant conversion
./rotate5.c:205: warning 158: overflow in implicit constant conversion
./rotate5.c:206: warning 158: overflow in implicit constant conversion
./rotate5.c:209: warning 158: overflow in implicit constant conversion
./rotate5.c:210: warning 158: overflow in implicit constant conversion
./rotate5.c:213: warning 158: overflow in implicit constant conversion
./rotate5.c:216: warning 158: overflow in implicit constant conversion
./rotate5.c:219: warning 158: overflow in implicit constant conversion
./rotate5.c:222: warning 158: overflow in implicit constant conversion
./rotate5.c:225: warning 158: overflow in implicit constant conversion
./rotate5.c:228: warning 158: overflow in implicit constant conversion
./rotate5.c:229: warning 158: overflow in implicit constant conversion
./bool3.c
./string1.c
In file included from ./string1.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./xor.c
./compare.c
./compare9.c
In file included from ./compare9.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./for.c
./for.c:37: error 226: no type specifier for '(cast)'
./add4.c
./add.c
./pointer1.c
./and1.c
./and2.c
./b.c
./ptrfunc.c
./ptrfunc.c:47: error 9: FATAL Compiler Internal Error in file 'gen.c' line number '516' : Unimplemented call through function pointer
Contact Author with source code
./compare2.c
./mult1.c
./sub.c
./rotate7.c
./rotate7.c:206: warning 158: overflow in implicit constant conversion
./rotate7.c:212: warning 158: overflow in implicit constant conversion
./rotate7.c:218: warning 158: overflow in implicit constant conversion
./rotate7.c:224: warning 158: overflow in implicit constant conversion
./rotate7.c:230: warning 158: overflow in implicit constant conversion
./rotate7.c:236: warning 158: overflow in implicit constant conversion
./rotate7.c:242: warning 158: overflow in implicit constant conversion
./rotate7.c:248: warning 158: overflow in implicit constant conversion
./rotate7.c:254: warning 158: overflow in implicit constant conversion
./rotate7.c:260: warning 158: overflow in implicit constant conversion
./rotate7.c:266: warning 158: overflow in implicit constant conversion
./rotate7.c:272: warning 158: overflow in implicit constant conversion
./rotate7.c:278: warning 158: overflow in implicit constant conversion
./rotate7.c:284: warning 158: overflow in implicit constant conversion
./rotate7.c:290: warning 158: overflow in implicit constant conversion
./rotate7.c:297: warning 158: overflow in implicit constant conversion
./rotate7.c:303: warning 158: overflow in implicit constant conversion
./rotate7.c:309: warning 158: overflow in implicit constant conversion
./rotate7.c:315: warning 158: overflow in implicit constant conversion
./rotate7.c:321: warning 158: overflow in implicit constant conversion
./rotate7.c:327: warning 158: overflow in implicit constant conversion
./rotate7.c:333: warning 158: overflow in implicit constant conversion
./rotate7.c:339: warning 158: overflow in implicit constant conversion
./rotate7.c:345: warning 158: overflow in implicit constant conversion
./rotate7.c:351: warning 158: overflow in implicit constant conversion
./rotate7.c:357: warning 158: overflow in implicit constant conversion
./rotate7.c:363: warning 158: overflow in implicit constant conversion
./rotate7.c:369: warning 158: overflow in implicit constant conversion
./rotate7.c:375: warning 158: overflow in implicit constant conversion
./rotate7.c:381: warning 158: overflow in implicit constant conversion
./init0.c
./init0.c:43: error 9: FATAL Compiler Internal Error in file 'gen.c' line number '516' : Unimplemented call through function pointer
Contact Author with source code
./while.c
./empty.c
./arrays.c
./or1.c
./sub2.c
./sub2.c:162: warning 158: overflow in implicit constant conversion
./configword.c
In file included from ./configword.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./bank1.c
./bank1.c:20: error 9: FATAL Compiler Internal Error in file 'SDCCmem.c' line number '385' : code generator internal error
Contact Author with source code
Caught signal 11: SIGSEGV


find -iname \*\.c -exec sh -c "echo {} ; sdcc -S -mmcs51 {}" \;

Code: [Select]
./switch1.c
./rotate6.c
./rotate6.c:86: warning 94: comparison is always true due to limited range of data type
./rotate6.c:84: warning 158: overflow in implicit constant conversion
./rotate6.c:121: warning 158: overflow in implicit constant conversion
./compare3.c
./compare3.c:151: warning 94: comparison is always false due to limited range of data type
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:173: warning 94: comparison is always false due to limited range of data type
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./rotate1.c
./compare7.c
In file included from ./compare7.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./compare5.c
./compare5.c:219: warning 94: comparison is always false due to limited range of data type
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:242: warning 94: comparison is always false due to limited range of data type
./compare5.c:271: warning 94: comparison is always false due to limited range of data type
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare6.c
./bool2.c
./nestfor.c
In file included from ./nestfor.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./pcodeopt.c
./struct1.c
./compare8.c
In file included from ./compare8.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./rotate3.c
./ptrarg.c
./add3.c
./add3.c:64: warning 94: comparison is always true due to limited range of data type
./rotate2.c
./call1.c
./bool1.c
./compare4.c
./compare4.c:63: warning 94: comparison is always false due to limited range of data type
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:93: warning 94: comparison is always false due to limited range of data type
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:250: warning 94: comparison is always true due to limited range of data type
./compare4.c:294: warning 158: overflow in implicit constant conversion
./compare4.c:304: warning 158: overflow in implicit constant conversion
./compare4.c:313: warning 158: overflow in implicit constant conversion
./rotate4.c
./add2.c
./compare10.c
In file included from ./compare10.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./inline.c
In file included from ./inline.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./rotate5.c
./rotate5.c:179: warning 158: overflow in implicit constant conversion
./rotate5.c:205: warning 158: overflow in implicit constant conversion
./rotate5.c:206: warning 158: overflow in implicit constant conversion
./rotate5.c:209: warning 158: overflow in implicit constant conversion
./rotate5.c:210: warning 158: overflow in implicit constant conversion
./rotate5.c:213: warning 158: overflow in implicit constant conversion
./rotate5.c:216: warning 158: overflow in implicit constant conversion
./rotate5.c:219: warning 158: overflow in implicit constant conversion
./rotate5.c:222: warning 158: overflow in implicit constant conversion
./rotate5.c:225: warning 158: overflow in implicit constant conversion
./rotate5.c:228: warning 158: overflow in implicit constant conversion
./rotate5.c:229: warning 158: overflow in implicit constant conversion
./bool3.c
./string1.c
In file included from ./string1.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./xor.c
./compare.c
./compare9.c
In file included from ./compare9.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./for.c
./for.c:37: error 226: no type specifier for '(cast)'
./add4.c
./add.c
./pointer1.c
./and1.c
./and2.c
./b.c
./ptrfunc.c
./compare2.c
./mult1.c
./sub.c
./rotate7.c
./rotate7.c:206: warning 158: overflow in implicit constant conversion
./rotate7.c:212: warning 158: overflow in implicit constant conversion
./rotate7.c:218: warning 158: overflow in implicit constant conversion
./rotate7.c:224: warning 158: overflow in implicit constant conversion
./rotate7.c:230: warning 158: overflow in implicit constant conversion
./rotate7.c:236: warning 158: overflow in implicit constant conversion
./rotate7.c:242: warning 158: overflow in implicit constant conversion
./rotate7.c:248: warning 158: overflow in implicit constant conversion
./rotate7.c:254: warning 158: overflow in implicit constant conversion
./rotate7.c:260: warning 158: overflow in implicit constant conversion
./rotate7.c:266: warning 158: overflow in implicit constant conversion
./rotate7.c:272: warning 158: overflow in implicit constant conversion
./rotate7.c:278: warning 158: overflow in implicit constant conversion
./rotate7.c:284: warning 158: overflow in implicit constant conversion
./rotate7.c:290: warning 158: overflow in implicit constant conversion
./rotate7.c:297: warning 158: overflow in implicit constant conversion
./rotate7.c:303: warning 158: overflow in implicit constant conversion
./rotate7.c:309: warning 158: overflow in implicit constant conversion
./rotate7.c:315: warning 158: overflow in implicit constant conversion
./rotate7.c:321: warning 158: overflow in implicit constant conversion
./rotate7.c:327: warning 158: overflow in implicit constant conversion
./rotate7.c:333: warning 158: overflow in implicit constant conversion
./rotate7.c:339: warning 158: overflow in implicit constant conversion
./rotate7.c:345: warning 158: overflow in implicit constant conversion
./rotate7.c:351: warning 158: overflow in implicit constant conversion
./rotate7.c:357: warning 158: overflow in implicit constant conversion
./rotate7.c:363: warning 158: overflow in implicit constant conversion
./rotate7.c:369: warning 158: overflow in implicit constant conversion
./rotate7.c:375: warning 158: overflow in implicit constant conversion
./rotate7.c:381: warning 158: overflow in implicit constant conversion
./init0.c
./while.c
./empty.c
./arrays.c
./or1.c
./sub2.c
./sub2.c:162: warning 158: overflow in implicit constant conversion
./configword.c
In file included from ./configword.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./bank1.c
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #187 on: December 05, 2018, 02:08:49 am »
Might need a few weeks, but then I can sample a full programming cycle with all pins in parallel.

Yeah, I was rather hoping someone would be in for something quick & dirty   :-DD
(Just so you get me right I think its great and well worth it in the long run, but to keep things moving something more light weight might be what we need right now)

My theory (as pointed out by others as well and assuming the chip is reasonably akin to something like the old pics is that:

The first voltage spike + shoulder selects a programming mode of some sort.
Then you would send a short command/address and maybe some data.

Code: [Select]
         |\
         |  \
         |   \______   _______
         |          | |       |
         |          |_|       | .........

         |- select -||-----command / data-----   
             mode

My hope is that no very long duration is needed for signal analysis but just the very few first cycles.
That would be enough to start getting an arduino to do the same and see what happens  :popcorn:
« Last Edit: December 05, 2018, 02:31:17 am by DocBen »
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #188 on: December 05, 2018, 03:26:09 am »
A good starting point to see what I mean might be this datasheet for old PIC16C7XX OTPs
(although the padauks will probably behave differently I guess its reasonable to assume for now that their approach is similar)

http://ww1.microchip.com/downloads/en/DeviceDoc/30298d.pdf
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #189 on: December 05, 2018, 07:03:34 am »
The remark "Please notice that bit 0 should be kept 0 due to program counter is 16 bits" in the datasheets seems odd to me. Any idea, what this could be about? Would anything break if I place the stack at an odd address? Do push / pop / call / ret require the stack pointer to be aligned?

Philipp
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #190 on: December 05, 2018, 07:42:37 am »
The remark "Please notice that bit 0 should be kept 0 due to program counter is 16 bits" in the datasheets seems odd to me. Any idea, what this could be about? Would anything break if I place the stack at an odd address? Do push / pop / call / ret require the stack pointer to be aligned?

Philipp


Well it says "should be" not "must be". Hard to tell without an actual device or the ICE.

Depends on how they implemented the actual logic.
If it just takes the MSBs and toggles the last bit, then placing it an odd address will give you the byte in front of it.
Could make sense if you dont want to add the one. Probably makes sense because it saves space on the die (you'd have to do some arithmetic to get the result right otherwise)

consider this: you place sp at 0x3f then sp+1 is 0x40
You need to add an 7 bit adder for that (if I counted that right) thats significantly more computationally intensive (ie more die space) than toggle bit 0. Can all be done, by utilising the ALU for example but then speed is an issue, so I guess they dont.

looking at the datasheets again they might actually do a single cycle 16-bit access ie. ignore the lowest bit entirely
« Last Edit: December 05, 2018, 07:58:19 am by DocBen »
 

Offline oPossum

  • Frequent Contributor
  • **
  • Posts: 511
  • Country: us
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #191 on: December 05, 2018, 10:44:36 am »
I interpret this to mean that the RAM is word accessible only on word boundaries. Bit 0 of SP must be 0 to ensure word alignment. This implies that push/pop af will use a word of stack instead of a byte.
 

Offline ali_asadzadeh

  • Frequent Contributor
  • **
  • Posts: 655
  • Country: ir
    • ASiD Designer
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #192 on: December 05, 2018, 04:54:09 pm »
I think if you could revers the programmer too, it would be like heaven! ;) ;)

Guys Thanks for the great work and collaboration. :) :-+ :-+ :-+
You can order parts from www.ASiDesigner.com
we are a wire-based company
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #193 on: December 05, 2018, 06:01:41 pm »
I interpret this to mean that the RAM is word accessible only on word boundaries. Bit 0 of SP must be 0 to ensure word alignment. This implies that push/pop af will use a word of stack instead of a byte.

pushaf/popaf always use a word hence the +2

Result:        [sp] ← {flag, ACC};
sp ← sp + 2 ;

I guess they optimized this for call/ret which need 16/15/14/13 bit and not just a byte.
And other instructions then just use the same mechanism that is already in place.
 

Offline spth

  • Contributor
  • Posts: 47
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #194 on: December 05, 2018, 07:20:13 pm »
Another question on push af  would be which one of a and f goes into the lower address.

Philipp
 

Offline DocBen

  • Regular Contributor
  • *
  • Posts: 109
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #195 on: December 05, 2018, 08:04:03 pm »
Another question on push af  would be which one of a and f goes into the lower address.

Philipp


Doesnt really matter does it?

If you implement pushaf and popaf symetrically for an emulator there will be no difference.
A isn't used as return value (thats the whole point of pushing it).
Unless youre trying to expicitly modify A or the flags on the stack there is absolutely no difference. They are designed to be atomic operations.