Logic analyzer for Motorola 68000 asynchronous bus - Page 1
Forum section: electronics / projects

author: zappedy
author_rank: Regular Contributor
timestamp: July 24, 2016, 02:46:44 pm
content: I need to analyze a computer board, to see which instructions are executed. Extensive static analysis of the program ROM has not lead to a conclusion. The easiest way seems to put a logic analyzer on the 23-bit external address bus, but I have never used a logic analyzer.Can I just clock the analyzer with the Address Strobe from the 68k? There's a lot of other things connected to the bus, and I don't really know what all the implications of an asynchronous bus are.The system runs from an 8Mhz clock. Is an 8Mhz analyzer enough?

author: MosherIV
author_rank: Super Contributor
timestamp: July 24, 2016, 04:08:50 pm
content: QuoteNo, any logic analyser inspecting a cpu bus would either need to be clocked at the bus/cpu clock rate or higher.I would say no, an 8MHz logic analyser is not good enough.23 bits is not enough.Just looking at the address lines is not going to decode what the instructions are. The address bus only shows what address the cpu is accessing NOT what the data (or instructions) are.The other lines that you talk about are also critical for identifying what device is being accessed and what mode (read or write)In short, you need and old fashioned full 'Logic State Analyser' with something like 96 or more channels. They even have special pods for 68000 cpus so they can do full program instruction decode. They can be had for around £300 on ebay for the bare LSA, not sure how much the 68K pod goes for.Without the pod, the LSA only shows you what the state of each bit is doing. It can be made to decode addresses, and data but without the pod they cannot decode the cpu instructions.

author: zappedy
author_rank: Regular Contributor
timestamp: July 24, 2016, 05:30:59 pm
content: I'm on a shoe string budget, of course a 96 channel analyzer would be ideal but I've had to brainstorm to keep costs down.In this particular case, the program is in ROM and I have a dump of it, so I can figure out what instructions are being executed, if only I know the addresses. There are a few branches that are taken or not taken because of external interrupts. If I know which, I can simulate the circuit and figure it out from that.

author: C
author_rank: Super Contributor
timestamp: July 24, 2016, 06:44:54 pm
content: Try guessingYou know some facts from 68000 doc's, see if they match up with rom information.ResetStack address at location 0 and should point to ram.this is followed by program counter address which should point to valid code.The easy startup code is to have rom starting at 0. If rom stays at this address then other vectors will be fixed or startup code will setup a table in ram and the rom vectors will then use the ram table.If running system ends up having ram at 0, you might see a loop that reads and then writes from same address. On reset a read=Rom & write=Ram. A write to an address changes this to read & write ram.It is also easy to have Rom appear more than one time in memory space.An interrupt is like a separate program that runs at any time, it does not change a branch instruction. The startup code will enable interrupts at some point in startup code.Note that while 68000 has a 24 bit address buss, 32 is inside the chip. So a 32 bit address of all 1's would be the top of 24 bit external address.So do some guessing and see if your guesses are correct for the disassembly of rom.

author: woodchips
author_rank: Frequent Contributor
timestamp: July 24, 2016, 07:22:07 pm
content: Don't say where you are but someone posted an auction in the UK that I noticed had 68k disassembler.

author: zappedy
author_rank: Regular Contributor
timestamp: July 24, 2016, 07:32:17 pm
content: Thanks guys, but I've already disassembled and analyzed the ROM, and dealt with the 24/32 addressing and other issues. From analyzing the code, I know that I would be able to see which interrupt is triggered just from seeing where the PC goes.Believe me, I've tried everything when it comes to trying to solve this problem just with static analysis. It just won't do without analyzing what the hardware is actually doing.If I connect an analyzer to the 23 address pins and clock it from the Address Strobe, do I really need a faster analyzer than the system clock, and why?

author: Kilrah
author_rank: Unknown
timestamp: July 24, 2016, 07:49:35 pm
content: If you've got an LA that accepts an external clock it's fine, but that's not all of them. Those that run on their own clock obviously need significant oversampling not to miss something.What kind of interrupts are you dealing with? wouldn't it easier to look at the interrupt lines/sources if what you're after is which interrupts are triggered?

author: C
author_rank: Super Contributor
timestamp: July 24, 2016, 08:24:31 pm
content: Would help to know what type of 68000 system this is.It is a very large span from a dumb processor to a multi-user, multi-tasking with many 68000's in the system.Was common to have memory management where many different memory addresses respond to one CPU address.

author: zappedy
author_rank: Regular Contributor
timestamp: July 24, 2016, 08:25:57 pm
content: Yes it would be easier, if it worked, but I'm not after which interrupts are triggered, but which ones and in what order, and what routes the code takes. I have run into a dead end (literally weeks of work into static analysis), and can not progress further without analyzing what is going on in the actual hardware. It's not like I didn't try first.How does the asynchronous bus of the 68k affect things?

author: zappedy
author_rank: Regular Contributor
timestamp: July 24, 2016, 08:45:08 pm
content: It is a basic late 1980's embedded system with a 68000, some glue logic decoding the address mapped peripherals, a DMA controller shifting data between RAM and the peripherals. An address mapped UART talks to a peripheral microcontroller and interrupts the main processor when you type on the keyboard, when the floppy controller needs attention, etc. There is no paged memory. The peripheral microcontroller is not connected directly the main data bus.The operating system is soft-threaded/multitasking via interrupts, but single user, no networking.All in all I think having the sequence of addresses that are executed would help figure out the last remaining pieces, and looking only at the addresses seems much less involved than using a full logic state analyzer.

author: C
author_rank: Super Contributor
timestamp: July 24, 2016, 08:49:23 pm
content: Quote from: zappedy on July 24, 2016, 08:25:57 pmIn simple terms a memory access can take all the time memory wants.It is like memory wait states on other CPU'sthe difference here is a signal (dtac) is required from memory. You can have a huge difference in speeds.old slow 6800 chips because dtac from that memory is slow compared to faster memory.For some systems dtac could be used to single step memory access.Best system test tool is a test program.

author: zappedy
author_rank: Regular Contributor
timestamp: July 24, 2016, 09:18:06 pm
content: Yes, I did try to write such test programs, but since I can not stop the clock, they crash the machine because interrupts are no longer handled correctly. This is the main reason why I need to see the execution path, so that I can write other test programs and do further analysis.With the asynchronous bus, how can the address strobe still be a square wave?Do I understand this correctly: the 68000 CPU will be the only thing pulling the 'Address Strobe line low (thus asserting it since it is inverted)?

author: C
author_rank: Super Contributor
timestamp: July 24, 2016, 09:33:28 pm
content: Quote from: zappedy on July 24, 2016, 09:18:06 pmThe Address Strobe says memory address is valid and not changing.So valid for full memory cycle.CPU & anything that can control the buss like DMA will use Address Strobe.With the logic analyzer connected to address bus and Address Strobe you would not know if it was CPU, DMA or something else.To tell this difference would need buss grant signals.

author: C
author_rank: Super Contributor
timestamp: July 24, 2016, 10:00:12 pm
content: Quote from: zappedy on July 24, 2016, 08:45:08 pmIf your thinking no memory management due to no Motorola memory management chip this could be wrong. Some back then were just a few logic chips. And you also have memory protection possible.Back then dual port memory was common thing built from standard memory. DMA Controller acts like a limited second 68000. Not hard to have 68000 use peripheral microcontroller memory or peripheral microcontroller act like or use a DMA controler to change 68000 memory.What do you have for memory chips in system?

author: zappedy
author_rank: Regular Contributor
timestamp: July 24, 2016, 10:27:48 pm
content: There are no such things in the system, there is a supervisor mode task switcher which is "called" at regular intervals from the microcontroller, but the tasks run user mode, that's it. The only memory management is chip-selects based on the addresses. No dual port stuff, just 62-series dram chips connected straight to the data bus. If I manage to borrow a professional logic analyzer it will be interesting to see what the DMA controller is doing, but from the disassembly it seems to only be shifting data to a display in the interleaving bus cycles, like an Amiga.It would be very surprising if the system did any of the "exotic" things you're suggesting because I have not found anything in the disassembled source that indicates it. In fact I think I have a pretty good grasp on how the system works, the only issue is that the execution path doesn't seem to follow what I think it would, or my simulation would be identical to the system, which it isn't.

author: tggzzz
author_rank: Super Contributor
timestamp: July 24, 2016, 10:30:32 pm
content: Don't forget that instruction prefetch means you will observe instructions on the busses that never get executed. That is a pain with sequential code. I don't know how works with interrupts, but I doubt it is pleasant.

author: zappedy
author_rank: Regular Contributor
timestamp: July 24, 2016, 11:00:00 pm
content: I thought about pre-fetch, but I think it will be okay in this system because the interrupt handlers are so far apart that I'll be able to tell what happened.Let's consider the approach of only listening to the address lines. What other lines do you suggest for determining when an instruction address is on the bus?Is the Bus Grant Acknowledge ('BGACK) enough?Or are the Function Code bits a better choice? I don't really understand what happens to them during CPU wait states.The 68000 User Manual from Motorola is a bit vague on the specifics, it really gives impression that the address strobe is only asserted by the processor, but it seems logical that it is like you are saying that it is asserted by any bus master.

author: tggzzz
author_rank: Super Contributor
timestamp: July 24, 2016, 11:04:10 pm
content: My last experience with this was in 1988 (gulp), so I'm afraid I can't help you!

author: gslick
author_rank: Frequent Contributor
timestamp: July 25, 2016, 12:03:57 am
content: If you are located in the US one option would be to pick up an old school HP 16500 series logic analyzer. I have one (well, actually too many) and a 10311B (64670A) 68000/68010 processor interface which plugs into the 64-pin 68000/68010 DIP socket on one end and connects to the logic analyzer pods on the other end. The logic analyzer runs in state capture mode and is clocked on the rising edge of /AddressStrobe. There is inverse assembler software that runs on the logic analyzer to decode the CPU cycles and instructions.I think you could do basically the same thing with an HP 16500 series logic analyzer without the 10311B (64670A) 68000/68010 processor interface if you hook up all of the logic analyzer inputs individually to the target system. The inverse assembler software expects to see 24 address lines, 16 data lines, and 8 state line inputs clocked on the rising edge of /AddressStrobe. The state inputs are R/W, LDS, UDS, VMA, FC0, FC1, FC2, BGACK. The state inputs are used by the inverse assembler to determine what types of bus cycles are occurring.The source code for the 68000/68010 inverse assembler is contained in the HP 10391B Inverse Assembler Development Package Reference Manual:http://cp.literature.agilent.com/litweb/pdf/10391-90903.pdfIf you're not located in the US or somewhere else where HP 16500 series logic analyzers can be picked up cheaply this is all probably not useful for you.

author: C
author_rank: Super Contributor
timestamp: July 25, 2016, 12:11:07 am
content: You might look at non standard stack changes.A call instruction (pushes PC to stack)data blockInstruction executed after call return.The called sub programpops PC from stack and uses it as a data pointer to data block above.Push updated pointer to stack to be used as return PC addressReturn from sub.A disassembly would show instructions for data block.Easy to miss something like this.The data block could even act like a switch statement in CWith vector interrupts, processing can get very simple.With out vector interrupts, where you would have to read a status register and branch, the vector does the branch for you.The TRS-80 Model 16 & Tandy 6000 used a complete Z80 computer for IO. The 68000 was a board with the 68000 & ram that plugged in to the Z80 buss. The Z80 ran part of OS and did IO for 68000.With this in mind, your peripheral microcontroller code and actions could be what you are missing.Note that a 68000 could almost do a virtual 68000. The virtual 68000 could figure out it was virtual with code. The 68010 could do this and instruction time for very few instructions was only way to detect being virtual. You could have virtual 68010 running on a virtual 68010.While you think "exotic" , it was very simple in code, and still simple in hardware. One or two writes to memory.QuoteBGACK = NOT the 68000 using buss, someone else.AS = address valid. could be anything.To know the address is for an instruction fetch you would need the FC codes(3 lines)Memory is simpleput address on buss, remember that A0 is broke out to UDS & LDS.delay and make AS active.If write put write data on buss, delay WR active.If read make RD active.Wait for DTACK which happens a short time before memory is done.If read then read data bussclear buss back to idle, AS,WR&RD go inactive.Memory removes DTACKkeep in mind that a 68000 like most better CPU's uses byte(8 bit) memory. In this case it is two 8 bit wide memory. This allows a read or write of a byte or two bytes. If memory was 16 bits the to change a byte would require a read, modify, write sequence(slower).

author: zappedy
author_rank: Regular Contributor
timestamp: July 25, 2016, 01:59:44 am
content: Thanks, I will not be getting an old HP logic analyzer unless I absolutely have to, I'm not in the US and the shipping and customs would be astronomical. I also don't need a "hardware" disassembler because I have already disassembled the ROM code and a snapshot of the RAM from a running system.None of the complicated mechanisms that you (C) mention are present in this system, it is pretty straight forward as far as I can see. If I understand you correctly you're talking about a form of supervisor-less cooperative multitasking where each task, before it returns, puts the the address of the next task on the return stack. That I can tell is not going on, the task switching is triggered by interrupts, and every ISR starts by disabling interrupts and enabling them before returning. The main loop of the processor spends most of it's time at a STOP instruction, waiting for interrupts.The problem is that there are many tasks running "at the same time" with individual stacks (switched by the supervisor interrupt handlers) so following the execution purely from the stack is not doable, especially since I'm not able to run anything except very basic test programs, not before I figure out how some stuff work so I can work with the task switcher / interrupts.The task system has several linked lists with pointers to stacks that gets swapped in and out when different tasks run, it looks like at least 32 kb of RAM is dedicated to stacks like this, some big and many small stacks. I'm sure it was simple to code, but it is difficult to follow in retrospect, at least when I can't see exactly what triggers the task switches.I would very much like the peripheral microcontroller code, but that is not possible without resorting to decapping the PROM, and the microcontroller is an unusual japanese one anyway, so even that wouldn't be sure to succeed as I have no datasheet (I have exhausted all options of finding one, too, it is just too old). Given the enormous complexity of reverse engineering a PROM microcontroller from a decapping, I'd rather try to figure it out by tracing the main CPU execution path.Anyway, I've traced the PCB and I can only see the 68000 and the DMA controller being connected to the bus arbitration pins, and the DMA is set by the boot code to cycle steal mode. I think that means it should not be too much trouble to sample the CPU program counter from the address bus.

author: C
author_rank: Super Contributor
timestamp: July 25, 2016, 04:49:25 am
content: My non standard stack use exampleAny code can do this. It is a quick and easy way to have data in-line with code. I have seen this used to output string prompts.Normal multi-taskinginterruptsave current current task's registers.load new task's registers.return from interrupt.In the process of doing this the stacks are swapped and task continues as if a swap never happened.The interrupt is normally triggered by time. You could have a bunch of different time interrupts working different lists(1s,10ms, ....).The lists could also have a priority to the tasks.Could be a hardware interrupt to process something like serial receive which just puts data in a buffer.In some cases you want to get out of interrupt, but still need to do more processing so start task X on exit from interrupt.Keep in mind that when a task can not do work it could call system to logwhy the stop and start next task early.Forget the stacks, for task 1 to talk to task 2 it will not be by stacks. look for a memory area that is common. A system call that puts data in a buffer that a different task can use a system call to read buffer.If you see a Test and set instruction this is a sign of this. An interrupt can not split this like a load instruction, modify instruction, save instruction.Using test & set would let system or task make a lot of changes before release for other task.just to make you day complete, many tasks could be running the same code with just stack and data different.Think of a floppy controller.You have Drive Select, Track, Sector & Command registers with a chunk of data sent or received.If you put this in a packet or structure, it becomes easy to send to a different CPU to do the work.All IO could be in form of packets with different packet ID'sAlso works for task to talk to other task or system.So look for shared memory, system lists for shared buffers or memory areas.You have not said how big your rom is.A PDP-11 could boot from many different devices with just 32 instructions. You could think boot the boot the boot. Each stage added code and checked more things with checksums.My best Z80 only has 512 bytes of rom in whole system. Boots from 3 1/2, 5 1/4 & 8 in SD,DD.SS,DS and hard drive with just 512 bytes.So just a little good code can do a lot.Look at what other data is with each task swap storage area.Each task needs a lot of data for system to function. If a task can read/write files there is a structure of data neededNano kernal.Keep in mind that your peripheral microcontroller prom makes that fixed and 68000 has work with it. A simple SCSI interface can be just 2 byte size read/write addresses and using 4 bytes makes code fast. You have command data, command status, read data & write data with no limits on amount of I/O or type.Boot process might not use a lot of Rom. Have you figured out what all areas do?Some of your tasks could be parts of the system.Great is very simple and powerful at a low level.Really do not see a logic analyzer helping much.For a test program I would think that many memory dumps of running system could help. Note that reading some memory could crash system.look at a intel 8212 a simple port that does handshake with interrupts with no programming.Something here might help, OR NOT

author: TerraHertz
author_rank: Super Contributor
timestamp: July 25, 2016, 06:12:26 am
content: If you already have the code from the ROMs extracted and disassembled, and really only need to know the order of execution of interrupt service routines, then a plain logic analyzer would do what you need. You can set up labels on addresses of interest, and trigger captures based on specific address events, so the state display will make more sense.You have not specified your country. Is it Australia (and Sydney)? Because I have a logic analyzer with 68000 series pods and built-in disassembler. Not loaning it out, but you could use it here if that's feasible.Oh, and surely you can find all the 68000 processor hardware manuals online? They explain the bus state function.If not I can dig out my 68000 data books and scan a few pages for you.

author: zappedy
author_rank: Regular Contributor
timestamp: July 25, 2016, 06:25:31 am
content: Quote from: C on July 25, 2016, 04:49:25 amYes, that might help, because this is probably what I am seeing the code. Indeed there are many places with the TAS instruction that is obvious they are used for "semaphores". Nice to get some confirmation! I got into computers when the 68000 was already considered obsolete, and the techniques used are rarely documented on the internet. They often look very strange to somebody like me who is only experienced in the x86.On this system, not only does there seem to be many tasks using the same stack(s), there seem to be several different task lists running at the same time.Simulation is likely the only way to make full sense of this, and luckily the system only seem to have standard components except for the keyboard / peripheral microcontroller, but before that, it is necessary to decipher how the system is loaded and boots.One thing I haven't been able to figure out is, in the task list, two bytes are loaded with the same value, and later, the execution checks the XOR value of those two bytes and if it is zero, some task is run. Was there any common 68000 technique involving this, like the TAS semaphore, that did this? I can only think of XOR being used for storing two linked list addresses in half the space, but this is not it. (Apart from XOR being used for XOR, or for zeroing on the x86) This is part of the task scheduling, the surrounding code has given me a feeling those XOR bytes are used to enforce "atomicity" of something.

author: Fungus
author_rank: Super Contributor
timestamp: July 25, 2016, 06:25:47 am
content: Quote from: MosherIV on July 24, 2016, 04:08:50 pmIf it's synched to the clock then it might be.

author: Fungus
author_rank: Super Contributor
timestamp: July 25, 2016, 06:28:29 am
content: Quote from: zappedy on July 24, 2016, 07:32:17 pmWhat,exactly, is the problem you need to solve?If it's just 68000 code execution and you have the ROM then use a 68000 emulator. There's plenty on the web that are easy to hack to add peripherals, etc.If it's random glitches in a PCB then a logic analyzer might not help.If you can modify the ROM then turn on the 68000's debug mode. It calls a function after every instruction executed (you can log the registers, etc.)

author: zappedy
author_rank: Regular Contributor
timestamp: July 25, 2016, 06:32:56 am
content: Quote from: TerraHertz on July 25, 2016, 06:12:26 amThanks, that's very generous! However, I'm in Sweden, quite the polar opposite of the world!I have all the manuals, Atari and Amiga freaks have made sure every 68000 document ever written has been put up online, but some of them are actually a bit ambiguous in key places. Probably not if you already know this stuff, but some phrases seem misleading if you read them literally. Like the address strobe, the User Manual says that it indicates that the processor has a valid address on the bus, but it only does if the processor is the only bus master. Little details like that, throws a newbie off.

author: Fungus
author_rank: Super Contributor
timestamp: July 25, 2016, 06:41:21 am
content: Quote from: zappedy on July 25, 2016, 06:32:56 amAtaris and Amigas both have to share the RAM with (eg.) the graphics chip. The graphics chip always has priority over the CPU on those machines.OTOH they won't normally be accessing the ROM.

author: zappedy
author_rank: Regular Contributor
timestamp: July 25, 2016, 06:49:42 am
content: Quote from: Fungus on July 25, 2016, 06:28:29 amI want to reverse engineer the computer, and in order to do that, I'm trying to do just what your suggesting, to modify an available emulator. That's why I mentioned it was a good thing the peripherals are mostly standard parts. To make it run, however, I need to understand how the system is booting, and to figure that out I need to run my own debugging code on the actual system, and to do that I need to understand how I can load my code as tasks. If I just run the emulator with the ROM code, things don't work, and I can't figure out why by debugging the emulated system because it just doesn't work like the real system. This I know because some obvious things would happen if the execution path just followed the obvious path in the ROM, but they don't happen. External interrupts from a different clock source than the CPU is the only logical explanation.I would love to use the debug mode, but first I need to load my own code for a debugger stub, and in any case, the external interrupt generators will still be triggering at full speed.I did a lot of static analysis, but ultimately was not able to figure out enough; when I inject my code, the system hangs within a second or two. There are some places where things must be happening from external interrupts which I can not analyze statically. This is why I want to use a logic analyzer on the address bus.

author: zappedy
author_rank: Regular Contributor
timestamp: July 25, 2016, 06:58:06 am
content: Quote from: Fungus on July 25, 2016, 06:41:21 amYes, I was just saying there's no need for TerraHertz to scan any manuals, although it was a generous offer, because Atari/Amiga people have already done that, and very thoroughly. Almost any 68xxx related document is available as a PDF, for free download. My system is not an Amiga or Atari. It only has a hd44780, so there are no "magical tricks" going on like in those graphic systems that were on the cutting edge at the time.

author: Fungus
author_rank: Super Contributor
timestamp: July 25, 2016, 07:05:30 am
content: Quote from: zappedy on July 25, 2016, 06:49:42 amMost 68000 systems overlaid 8 bytes of ROM over the first 8 bytes of RAM to set the reset address.If you can hack that mechanism (modify the ROM?) then you can make it start up using your own code.

author: zappedy
author_rank: Regular Contributor
timestamp: July 25, 2016, 07:19:10 am
content: Yes, but then the system code won't be running, so what is the point? Like I said, I tried the ROM code in an emulator, doesn't produce the same result, which is what I'm trying to figure out why.

author: Kilrah
author_rank: Unknown
timestamp: July 25, 2016, 07:20:24 am
content: I would maintain that you should maybe rather focus on the peripheral hardware rather than the CPU and its code.You'd likely learn more by probing the interrupt lines, seeing what peripheral triggers them, at which point by looking at what's connected to that peripheral and if applicable their own interrupt lines you could figure out what sends interrupts and why.Similarly, looking at the system level architecture could tell you more about how the system boots than analyzing the code. Disassembling the code you'll see a bunch of register configuration etc that mean nothing until you've carefully followed the doc of each peripheral etc. Start from the other end, look at what peripherals would make sense as boot devices, see if they support that, THEN check if there is code that matches their use as such, and eliminate those that don't so that you quickly know where to concentrate (and potentially get ideas to bypass the current behavior).Similarly by looking at the whole system you have a high chance of an "aha!" moment where it becomes obvious what the most "logical" way to make it work is even without looking at a single code byte, once you've figured that out that's probably how it was done so all you need is to confirm it.

author: zappedy
author_rank: Regular Contributor
timestamp: July 25, 2016, 07:40:44 am
content: I have done pretty much what you are suggesting, tracing out most of the pcb, pouring over every datasheet of every chip (those I could find anyway), spent an absurd amount of time disassembling half the lines of the ROM, injected my own code and dumped the RAM, thought long and hard about what makes sense for the boot, the running, the pretty much everything, traced the boot sequence instruction by instruction making notes of the contents of every register of ever peripheral chip, read countless documents on similar products in order to get a feel for the type of system, set up an emulator as best as I could, etc etc etc.It did not work, because some things are not executing at boot the way it looks from the ROM code. So not any "aha" moments as much as a number of of "wtf" ones.That is why I came to this forum for help.

author: C
author_rank: Super Contributor
timestamp: July 25, 2016, 08:33:40 am
content: What you may be missing is something like a 74ls273.A simple ttl chip that can be cleared at power-up and then make massive changes to hardware. When Clear boot rom in system at 0 and with one bit set replaced by ram.Note that power on reset of CPU can be different hardware reset of CPU which is different from instruction reset.TST test & set insturctionbyte = 0 before tst is freebyte = bit 7 set before tat is in use.One byte can software protect any thing or memory area(s)How large is the rom(s)?You said it has a floppy drive, does it load OS or run on power on?System mode vs user modeOne bit in status reg (s bit)System mode can change S and interrupt levelUser mode can not do this and only way to system mode is a trap.Interrupts happen in system mode.Only outside processor indication is change in FC codes.Your DMA could be DRAM refresh

author: zappedy
author_rank: Regular Contributor
timestamp: July 25, 2016, 08:39:29 am
content: The ROM is 128 kb and almost every bit of it is used. It is not just used for booting, it is filled with various routines that is called by other code also from RAM. The system can additionally load additional software from floppy. Thanks for your suggestions, but I don't think any of the other things you mention occurs; I would have noticed that in the code, and the emulation would not have worked at all. Right now the frustrating part is that emulation almost works, it just doesn't do what is expected.I'll try to get a logic analyzer now, and see what it says.

author: C
author_rank: Super Contributor
timestamp: July 25, 2016, 08:49:48 am
content: A rom of 128k can do a lotAn X86 is just a modified 8080While the 68000 takes a lot from PDP-11 & VAX mini computers while adding capability to have many 68000's on a buss.

author: TerraHertz
author_rank: Super Contributor
timestamp: July 25, 2016, 02:02:36 pm
content: Quote from: zappedy on July 25, 2016, 07:19:10 amIs the system you are trying to reverse engineer, something that may include measures against reverse engineering?Was it meant to be a secure system?I ask, because I once programmed a gambling game on a simple 6502 board, that succeeded very well in defeating serious attempts to reverse engineer it. By a university comp-sci professor, paid by the government, I was told by the game operators.If a programmer wants to, and knows the processor quirks and the board functions well, there are plenty of traps that can be laid to fool both software and hardware emulators. In my case I used a combination of a 6502 undocumented op code, a stack wrap-around bug, exact timing of a video V-sync NMI, and that the boot routine was setting up a custom hand-written byte-coded interpreter in which all the game code that mattered was written. If everything was correct the interpreter initialized properly. If anyone plugged in an emulator the timing changed subtly, the 'secret startup trick' didn't work, and the machine rambled off into thickets of ridiculous nonsense code.Which is to say, if you are up against something like that then you will actually need a logic analyzer. That would have defeated my trick, but they weren't so common back then.Btw, does your system have any kind of simple readout you can write to from injected debug code? Even just a LED you can blink, better a 7-segment LED, still better some kind of high speed serial port, or best of all a dual port RAM you can access from a 2nd computer. Either by manual mem dump, or implement a buffered message logging utility.If it doesn't, you could help yourself a lot by hacking it to add one.

author: zappedy
author_rank: Regular Contributor
timestamp: July 25, 2016, 03:40:20 pm
content: Clever! But then the gambling industry is obsessed with being ripped off, wonder why!This however is just an embedded system, no reason why they would protect the system at all. And it doesn't look like it, I can understand the disassembly just fine. But thanks for the tip.I have considered making a gdb stub, but since the serial communication routines takes place in the task system, it just seemed like too much work, and too likely to cause another endless cycle of debugging. It's a bit of a catch-22.

author: woodchips
author_rank: Frequent Contributor
timestamp: July 25, 2016, 06:30:56 pm
content: This all looks to be overly complicated.Assume the 68000 is just running ordinary code, nothing protected.Use a logic analyser clocked from the falling edge of DTACK, this means that the address, data and other signals are stable.For the LA something like a Tek 308 or 318 are perfectly ok. But only 8, or 16, channels! So what? Use one channel on the EPROM CS so you know it is running code, the other channels on A1 to A7, or similar. You know where it shoukd be in the address space so it is easy to narrow it down. These LA are now unwanted so cost peanuts, but I find them brilliant, so quick to get running and tracing.

author: C
author_rank: Super Contributor
timestamp: July 25, 2016, 06:45:07 pm
content: Back then you had a lot of parallel printers all connecting to parallel interface. All the same but differences in how to Bold, expand print, font size is change, you get the idea.Rom code would contain standard printer. When told to use a different printer, A module of code was hot loaded and hot patched in so new functions to handle difference. A function like Printer_Bold was always same to user while small function sent different data to printer. No C like select statement, used lists that were built in ram. Some functions for need changes were in ROM and others were in files.Build list, find match, replace pointers to standard functions with new functions.Have seen same idea used many places. Hot-swap hardware with plug & play would be todays example but also used for Hot-swap of software on a running computer. Your Rom code could be getting a Hot patch change.The language Erlang has some of this, but could be any language.I an surprised that normal tasks are not in user mode as this makes task swap easer. With no hardware protection or mapping you could see almost no code change. The benefit is a different stack register is used when in user mode that's different from other modes which share same stack register. Here you may or not see more use of instructions that use the vector exception table. You could be calling code in user mode and have it act one way when same code is called while in system mode it acts different.Note difference of STOP instruction. In user mode it is a Trap, a way to say end this code.For TSTis start of locked _____Unlock happens when byte is set to 0.On task swap how many resisters are changed?Think PC, SP and status is min but not very usable.Could be All and will be on big system for security.For less then this would be a way to pass data between sequential tasks or global pointers.When I give an example like printer above, it's just a way to explain what happens as an example, many ways to use basics.Hope you are having some fun doing this.Did something like this many times.One was 80's system that had option of 4 I/O & 4 dram cards. Not using an I/O allowed more dram cards. The 8 dram cards=$5000Later a new option to expand was by attaching expansion box with 8 I/O & 8 dram that acted like above at cost of one I/O. The 68000 Async buss made this possible, Same dram card but was slower due to distance.Pushing the limits adding 4 expansion boxes and you could have 68 dram cards or 32 I/O and 36 dram.The basics were very simple when you got them correct. Internal hardware was treated the same as adding cards. The same boot rom was used across a huge number of different systems.Think of you system, is what you have, is it the baby version or something larger. Number of tasks could change by size.Do you know how many tasks start and do tasks match up to the hardware in some logical way?Try to work back what you know to the simple level.Ethernet packet is simple, when you add TCP/IP on it and have not so simple.

author: Fungus
author_rank: Super Contributor
timestamp: July 25, 2016, 07:18:28 pm
content: Quote from: C on July 25, 2016, 06:45:07 pmYes, but we had EPSON Escape codes."Epson compatible" became a thing.

author: C
author_rank: Super Contributor
timestamp: July 25, 2016, 09:04:04 pm
content: Quote from: Fungus on July 25, 2016, 07:18:28 pmOnly later on and not on all."Epson compatible" a solution solves some problems and creates more problems.Few line printers back then had "Epson compatible", Some were PCL or postscript.Why would you want to wait on a slow "Epson compatible" when you have access to a 1200 line per minute printer.System that this was used on could use a 36 or 48 inch plotter as a printer.And today that system could be printing HTMLVery powerful while simple code.By using functions in place of fixed strings, you could do more.

author: C
author_rank: Super Contributor
timestamp: July 25, 2016, 10:36:58 pm
content: Quote from: zappedy on July 25, 2016, 06:25:31 amThink you will find that XOR of two bytes is 0 if the two bytes had the same value.The call would happen if task __ was waiting for ___ and some other task did the job, got the data so that task ___ can do more processing.Think bigger while being small, This could be any list type process.You could have a list of floppy sectors to read.You could have a list of floppy sectors to write.You could have a list of character strings to send to serial.There could be many reasons to use more than one TAS Byte.Task 1 wants a buffer a TAS byte shows it in use.Task 1 makes a request that another task fill buffer with ______Task 1 stops as it can do no more until buffer has data.Some task puts data in bufferuses second TAS byte to say done.Think of fine details of what is possible here.TAS1 Read byte2a sets status flag N if bit 7 of #1 set2b sets status flag Z if #1 = 03 Set bit 7 #14 Write byte.After TAS-1 to -127, no change Have flag for before0 changed to -128 have a flag for before1 to 127 changed to -1 to -127Three states can be found from status flags.Think of thisIf you had some very nice software to work with lists, would be dumb not to use it to work with a lot of lists.Think micro or nano tasks. A task's complete function could be just to initialize something ( grab some memory and create a new circular buffer, init this ___ chip.)Think of all kinds of listsThink along the lines of C++What C++ passes between functions on stack or in registers would be passed as a data structure on a list.The list could just be a pointer to the data structure.

author: zappedy
author_rank: Regular Contributor
timestamp: July 26, 2016, 02:58:40 am
content: Your posts are very interesting! All those old techniques. Indeed I think most of them are used at some points in the firmware!However, XOR-ing just to check for equality doesn't make sense, why not just use CMP? Same number of clocks and only flag Z (zero, equal) is used.It looks like this at one point in a routine that seems to be called to add a task/thread/nanothread to a list (only xor-relevant parts of the code presented here):Task_something_subroutine:bset.b d2move.b d2, 4(a1)......Other_subroutine:move.l #SomeStructAddress, a1move.b 4(a1), d2move.b 5(a1), d3eor.b d2, d3beq SomeBranchmove.l (SomeData), d3 # result of xor not usedclr.b 4(a1)......SomeBranch:move.l (SomeOtherData), d3# result of xor not used here eitherMy guess is that the eor-instruction was added by an assembler macro, like M_IF_STATE_X(d2,d3,SomeBranch), because the result of the eor (= xor) is used in other places.

author: C
author_rank: Super Contributor
timestamp: July 26, 2016, 04:16:35 am
content: Think of a multi-part thing that the task needs to continueXor says two bytes are equal.the two bytes could be part of a state machine.One byte says "wake this task at state "Second byte is task state that is updated not by this taskProgram just loops through task list fastif xor(A,B) then _______some times it's nice not to mess with other flags as they are in use.If A=B thenload Cjump or call Cthis would be very powerful as C could be any callable address.What might make sense in one case could break the universal use on other listsThink very little programming and process a lot of data.in stead of writing a bunch of code, make a lot of data fit the code.editsame code working on a list of buffers might bewhen character count = ______ run thisedit2From what I read xor gives you a zero in a register that could be used in what is called to prevent the call repeating.

author: C
author_rank: Super Contributor
timestamp: July 26, 2016, 05:27:43 am
content: when an outside program needs to talk to a program there can be all kinds of problems.Think of interrupts.External In can interrupt CPU.With CPU working with good hardware, writing to I/O the CS & WR can set a FF. Output of FF could cause interrupt to second CPU.In a user taskA trap instruction could be thought of task interrupt out.Task interrupt IN is a problem. System really does not know where the task is. Best System can do is set a flag at a specific location.A system call that lets you add a call back is a flag & data.Main task code needs to treat flag and optional data like an interrupt.To do this you might see at a lot of placesnormal codePush registers on stackcheck byte at ____ and call ____ if true.Pop regestersnormal codeAs flag would be changed external to task a TAS should be used.In a nano task world where a long running task is broken into small parts this might not be needed.Long running task would need to do test often.The called _____ would know about all external in interrupt's to taskand do what is needed safely.

author: DJohn
author_rank: Regular Contributor
timestamp: July 26, 2016, 04:34:38 pm
content: A 68000 bus transaction takes multiple clock cycles (a minimum of 4, from memory), so you don't need a very fast logic analyser. And there's a good chance you don't need many channels - unless the code is doing tricky things. 8 channels, used creatively, can go a long way.Since you have a simulator, you're 90% of the way there. As I understand it, you're trying to track down when and why the simulation differs from the real device?You want to look at the address bus when /AS goes low. If there are other devices on the bus that can do their own memory access, you'll need to qualify this with /BG high. A single AND gate will do that. FC0-FC2 will tell you what type of cycle this is - memory access, interrupt acknowledge, or whatever. There's a good chance you'll only need one or two, depending on what types are actually used.Use the rest of your samples to capture low address bits. Unless you're very unlucky, that will be enough to tell whether a branch is taken or not. Run the simulation in parallel with the capture, and if it starts fetching from an unexpected location, you know where to start looking.

author: zappedy
author_rank: Regular Contributor
timestamp: July 27, 2016, 01:44:37 am
content: Interesting, 4 clocks at 8Mhz is approaching raspberry-pi-able territory for a cheap 26 ch analyzer via GPIO. However, while the 68000 uses four cycles, I can't find any guarantee that the DMA controller will do the same.Yes, I'm trying to find the error in simulation to continue working the reverse engineering in the simulator, much easier!The variable instruction lengths of the 68000 instructions should give it away even with just the low bits. Every subroutine has it's own instruction length signature so to speak.Thanks, C, I think you are right, there seem to be routines broken down into fragments, so in effect there is a slower low-priority task system that runs almost like interpreted code, advancing their algorithms a few instructions here and there when the processor is idle. This system must have been quite daunting to fully understand even for the people who originally wrote it!The 68000 is fascinating. So perfectly made for writing assembler code. However, while that is very nice when doing reverse engineering, it seems quite silly today, because it is a huge waste of resources when running compiler-created binaries. All that orthogonality is super elegant, but the only one who will ever see the beauty is the assembler programmer! And the reverse engineer

author: C
author_rank: Super Contributor
timestamp: July 27, 2016, 03:55:52 am
content: Think of this as if you were designing it.If it was expandable with a lot of slots, you might need a memory board.Way back that meant jumpers to select the address. Better design used a dip switch. Then plug & play where set the latch that replaced the dip switch. To do this correct CPU needed memory board size. With a daisy chain logic this could be just one address to read and one address to set.Program would look dumb, read the same address a bunch of times, do some processing and then write the same address a bunch of times. Need to read all first so that 1M boards get set together followed by 256k & 64k. Now with this in place, not hard to add a second address to read a dip on an I/O board so that you can set the I/O card to match what the program needs. When you build a system with some boards built in, easy thing is to do same as if on separate board, you have the code and logic is very simple. Now when you make a new system with a difference. you just moved the parts from separate board to main board. Removing a few low cost parts could mean a separate rom for each system, more software work. Keeping those few parts lets you create a lot of different systems fast, you just leave out the card cage.It is hard to change a fixed rom that has an error. If system comes with removable storage, a rom patch from floppy could save the day. That is where again simple is simple, boot from rom, write to same address, disable rom and read from ram. The rom patch could even be in the rom. This also lets system add function(s).Think of your simulation, what does it do for above?In your simulation does it write to rom address?In your simulation does it read to one address many times?In your simulation does it write to one address many times?Remember that one address can be read only and write only.In fact one write can go many places at same time. While you normally see this as write to video memory and shadow video memory there are other uses.You might fine a lot of answers the better you understand the data structures used. Try to fill in the gaps.QuoteYou are forgetting the compiler writer here. How many times have you seen assembly used with a C program? Part of this is a language problem with the other half a code generation problem.Orthogonality can mean better code from high level language with less work. The less work then be used to make other parts even better.Low level simple makes high level simple. low level mess never stops causing problems.

author: tggzzz
author_rank: Super Contributor
timestamp: July 27, 2016, 07:55:21 am
content: Quote from: C on July 27, 2016, 03:55:52 amQuite right.Computer scientists can only easily deal with three numbers: 0, 1, many. Anything else implies running out of a limited resource.