Replies: 12 comments 18 replies
-
And yet, I have now found some examples where the disassembler does correctly adjust the value of XK, YK, ZK. See below example. In this example the value of YK is set to 0xf using <context_data> in the cspec file (with no address restrictions) : Strange. It seems it is possible to get the right values for XK, YK, ZK. How do I get it to do this consistently? Is it to do with immediate values -vs- values from pointers?
|
Beta Was this translation helpful? Give feedback.
-
Can you copy your cspec and pspec here as well? Are the |
Beta Was this translation helpful? Give feedback.
-
Hi, thanks for helping out! cspec and pspec shown below. When the cspec has no settings for XK, YK, ZK the disassembler seems to keep their value at zero (I haven't checked this exhaustively) The examples in the first two posts are consistent with the settings shown below in the cspec (ie) YK set to 0xf and ZK set to 2 for all addresses .cspec (note that I don't know the proper default function prototype - this is just a guess)
.pspec
|
Beta Was this translation helpful? Give feedback.
-
Hi, I've started looking at the decompilation now. The PSHM and PULM instructions always result in an error such as "WARNING: Removing unreachable block (RAM,0x001c4c)". Not sure why? |
Beta Was this translation helpful? Give feedback.
-
Thanks, I've had a look at the pcode. I can see how PULM from the slaspec file is reflected in the pcode. If I understand the syntax correctly, perhaps the problem is where LOAD is attempting to put 8 bytes into a 2 byte register (eg: CCR). I don't know where it is getting 8 bytes from? pcode and regsiter definitions below. PULM definition and associated macros are earlier in the thread.
The space and register definitions are...
|
Beta Was this translation helpful? Give feedback.
-
It's the pcode from a single PULM instruction. This pcode at the start...
...correlates to... ...and the following pcode...
...correlates to... ...which, via the macro, expands to...
The value being put in register 0x30 ( |
Beta Was this translation helpful? Give feedback.
-
By playing around with it, I have figured out why the "WARNING: Removing unreachable block" error is displayed. It is saying that because there are some of the PSHM / PULM conditional branches that are not executed based on the immediate operand. For example, if I reduce the instruction to:
Then wherever there is a PULM #0x01 instruction no WARNING occurs. If there is a PULM #0x02 instruction then the WARNING occurs. So, bottom line, it's not really an error. That's solved the WARNINGs. Still puzzling over how to handle these extension registers and their impact on addresses... |
Beta Was this translation helpful? Give feedback.
-
Next mystery, it seems like the decomplier somehow cuts out branches of the code even though those branches could occur. Example:
The LDX loads the value at RAM location 0x0ffe18 (uninitialised) into the IX register. The address 0xffe18 came from YK being 0x0f, IY being 0xfe00 and the instruction offset of 0x18 giving 0xffe18. If the value at 0xffe18 is nil, the LDX would set the Z flag. The BNE then branches based on the value of the Z flag. However, the decompiler says "WARNING: Removing unreachable block (RAM,0x0078ba)" and the decompiled function doesn't reflect the code from 0x0078ba onwards. Why does the decompiler cut out this code when it can't know the value of the Z flag? pcode of the LDX and BNE follows...
Thanks! |
Beta Was this translation helpful? Give feedback.
-
Any thoughts on the current questions?
A new question, why does the disassembler simplify an address, but the decompiler keeps it shown in its various pieces? For example, disassembler expresses the address succinctly like this... while the decompiler turns the address into this...
|
Beta Was this translation helpful? Give feedback.
-
Did you mean have the <context_data> in both the cspec and the pspec files? I now have that. The disassembly has changed, but now instead of a reference to the incorrect address of 0x1638 (should be 0x21638 with value of ZK of 0x02), there is now an unreferenced immediate value of 0x1638. Latest disassembly follows (compare to snip in the first post): |
Beta Was this translation helpful? Give feedback.
-
The default constant propagation should follow the registers values of ZK and IZ and produce a reference. You need to move <context_data> from your .cspec file to your .pspec file.
An analyzer can be made to propagate the EK, XK, YK, ZK registers if they are globally set, or set before calling a function. In the .cspec file, the decompiler will assume the EK, XK, YK, ZK are unknown after a call unless they are in the unaffected list The stack params/locals are not set correctly. I believe this .cspec will work much better. I'm still seeing other issues.
|
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Hoping for help with an issue that has me stumped. Have written a processor language for the HC16. First time writing a language. Have used HCS08 as a starting point. Language is written, compiles ok & disassembles ok. The decompilation looks quite messy, but I haven't turned my mind to decompilation yet.
The HC16 (20 bit) is backward compatible with the HC11 (16 bit). Manual here: https://www.nxp.com/docs/en/reference-manual/CPU16RM.pdf. The HC16 constructs 20 bit addresses by a combination of 16 bit index registers (IX, IY, IZ) and 4 bit prepended extension registers (XK, YK, ZK). In the language spec I have modelled the 4 bit extension registers as 1 byte registers.
My problem boils down to what values the disassembler uses for XK, YK, ZK. If I don't specify a value, the disassembler assumes a nil value which means it gets most RAM references wrong because the processor RAM is in addresses 0x020000 to 0x028000. If I use <context_data> (in the cspec file) to set a value of 2, the disassembler uses the specified value for a little while and gets the addresses correct. But the diassembler then seems to 'forget' the value of 2 and reverts back to a value of zero after any operation on that extension register.
See below example for the value of ZK... In this example, <context_data> has specified ZK to be 2 at all addresses. At 0x34cc, in the LDAB instruction, the disassembler uses the 16 bit immediate value of 0x1628 with the ZK value of 0x02 to get the correct reference at 0x021628, which is in RAM. However, lower down, at 0x34e4 in the BSET instruction, the disassembler uses the immediate value of 0x1638 with a ZK value of 0x00 to get the incorrect reference 0x001638 which is in ROM, not RAM.
The only intervening operation on ZK is the PULM instruction which pulls the value of ZK (and other registers) from the stack, but the value of ZK is unchanged from when it was pushed onto the stack by the PSHM instruction at 0x34c2.
My understanding is that Ghidra is a 'static' view of the code and does not track the values of the registers. "Set Register Value" may help, but I am assuming this has the same effect as <context_data> (ie) the setting will be 'forgotten'. I have tried "Set Register Value" but weirdly it doesn't seem to change the disassembled address. But, even if "Set Register Value" worked, this seems like a very manual approach. Hence, I am wondering if there is some way to systematically help the disassembler get the correct value for XK, YK, ZK, and therefore get the correct address references?
I am using Ghidra 10.1 if that has any impact.
Relevant excerpts from the slaspec file:
Disassembly...
Beta Was this translation helpful? Give feedback.
All reactions