Has anybody managed to get ZapMJE to compile with the DDE?
Rick Murray (539) 13841 posts |
It’s a PC alignment issue, not a data access alignment issue. It may be that older processors, out of Thumb mode, just ignored the lower two bits? … Yaaah! I think we just had some sort of power surge brownout (solar power hiccup?). It trashed my PC’s harddisc and the attached SD card. The main harddisc was able to be recovered with Hirren’s Boot CD (yay for a journalling filesystem) but the simpler (FAT32) on the SD card is just a lot of junk. Well, there goes most of my recordings of the eclipse off CNN. :-( At least the PC is back up now and seems to be behaving more or less like before. |
Chris Johnson (125) 825 posts |
Surely Rick is talking about the assembler directive ALIGN, which inserts null bytes so the next instruction is word-aligned – its address is a multiple of 4. |
Rick Murray (539) 13841 posts |
I should add for my tale of woe that the Pi/Vonets/HDMI→VGA/fans are powered from a big five way power supply unit which must have a fairly meaty capacitor inside it. That plus hardware that hardly consumes anything when in normal use. Power disurbance? What power disturbance! :-) |
Steve Pampling (1551) 8170 posts |
That was what I was thinking of. Could be wrong but I thought older processors could do half-word without going A over T |
Clive Semmens (2335) 3276 posts |
Some implementations ignored the bottom two bits of instruction addresses, but you could never have non-aligned instructions. The instructions themselves have always had to be aligned. |
Rick Murray (539) 13841 posts |
Repeat: This is not reading or writing at a halfword address, this is setting PC to an address that is not word aligned. Which is simply not supposed to happen in ARM32 mode. |
Clive Semmens (2335) 3276 posts |
Deleted Stupid Post. Brainslip. |
Rick Murray (539) 13841 posts |
Remember, in a 26 bit world, those were the MODE bits, so they would have co-existed with a Thumb capable processor in a 26 bit world. My ARM ARM (PDF of version circa ARMv6) doesn’t actually mention what happens if you try to set a non-word-aligned value into PC using MOV. It is likely that such a thing was simply ignored, which is why ZapObey has worked for so long in that state. |
Clive Semmens (2335) 3276 posts |
Of course, my memory is at fault. Were you allowed to change mode by loading the PC directly? I forget. |
Rick Murray (539) 13841 posts |
I’ve updated the zap_ultimate archive with the fixed ZapObey, so anybody who downloads it as of now won’t need to patch [that’s the idea! ;-)] |
Rick Murray (539) 13841 posts |
Sort of. You couldn’t directly change PC, but there was TEQP to let values be pushed into the flags bits. That said, you could quite easily mess around with R14, such as changing mode or setting the V flag by ORRing in the bits you wanted, and then MOV PC, R14 to push that to PC. |
Jeffrey Lee (213) 6048 posts |
Yes. Prior to ARMv6, unless it was a special Thumb interworking instruction (e.g. BX) the lower two bits should have just been ignored. But on ARMv7 and above, all branches are interworking. For Zap you’ll be falling into the “bottom two bits 10” case. On ARMv7 this is unpredictable, and since it’s been working so far I’d guess that most machines just round the address down (and execute whatever garbage instruction the last word of menu_file is). For ARMv8 / Cortex-A53 they’ve revised it to “constrained unpredictable”, which either means (a) it rounds the address down, or (b) generates a PC alignment fault. So I’m guessing the Pi 3 takes the latter behaviour. |
Clive Semmens (2335) 3276 posts |
Which is pretty much what I was trying to say in my Stupid Post above, and scrambled rather thoroughly. Scrambled brains… The clever behaviour would be to round the address UP, since any sensible assembler will insert up to three bytes to align the next instruction after any data bytes. And the extra logic required is trivial in today’s world. But faulting is better still, since it’s obviously wrong. |
Rick Murray (539) 13841 posts |
That would require extra logic, simpler to just make out the errant bits… |
Clive Semmens (2335) 3276 posts |
Indeed – but the days of worrying about two or three extra gates are long past. Faulting it requires even more logic, but it’s worth it – not faulting it could occasionally randomly cause absolute havoc. Usually such random walks do nothing important for at most a few instructions, then fault – but there’s no guarantee of that. |
Rick Murray (539) 13841 posts |
Nothing seemed to happen on my Pi 2. I do wonder what would have happened if it had switched the processor to Thumb mode… |
Jeffrey Lee (213) 6048 posts |
Try checking what the last word of the menu_file string disassembles to. I have a feeling it’ll be some form of ANDEQ, so whether it causes havoc or not will depend on the PSR flags on entry. “Nothing seemed to happen” isn’t the same as “nothing will happen”. |
Clive Semmens (2335) 3276 posts |
PC-8: |
Clive Semmens (2335) 3276 posts |
That was the report I got – I’m a little puzzled by the first instruction – I didn’t think ’puters did typos! |
Stephen Unwin (1516) 154 posts |
I may be completely wrong, but when it contains the text “Menus” followed by a 0, is it a message string that it is trying to execute and not a real instruction at all? |
Jeffrey Lee (213) 6048 posts |
Yes, it’s trying to execute this text. Rick has already released an updated version of the module, we’re just nattering about why it only crashes on the Pi 3 and not on other machines :-) |
Clive Semmens (2335) 3276 posts |
I think it’s only trying execute the final “s” of that text, together with the three nulls that take you up to the first actual instruction you’re supposed to be executing, no? Since it’s an ANDEQ, it’s a no-op unless the condition flags say EQ, so you’ve a fair chance of getting away with it. Even if it does the AND, if R0 doesn’t contain anything important at that point all will be well, or even you might be okay because whatever R3 and R0 contain happens to leave R0 unchanged, or not changed in an important way. Luck of the draw, and overall, very likely harmless. (Actually, R0 = 0000000D and R3 = 0002E91C – so if that D matters at all, AND R0,R0,R3 ROR R0 would be a right mess. So it’s the EQ test failing that saves the day.) |
Clive Semmens (2335) 3276 posts |
Er – hilariously, no it’s not a right mess at all. (&D AND (&2E91C ROR &D)) is &D… Edit: even more hilariously, that’s me making errors again. It’s not &D at all. It’s &5. |
Rick Murray (539) 13841 posts |
That’s why I said “nothing seemed to happen”, as opposed to “nothing did happen”. In other words, in my specific use case (which is important since I’m trying to find the bug!) there was no obvious side effects. My Obey files weren’t replaced with Nickelback lyrics, my monitor didn’t turn pink with yellow spots, and there was no message saying All your base are belong to us.
The init call is used a fair few times my Zap, it seems to be an entry point for “Zap wants something done or to notify you of something”. Thankfully the reason code is in R1, but R0 can carry data too… For Stephen – a pointer was set to point to the end of the menu string. Here’s how it is supposed to be: String "Menus", 0 Zero padding Initialise pointer Initialisation code starts here Here is how it actually turned out to be: String "Menus", 0 Initialise pointer Zero padding Initialisation code starts here Why? Because there was no specific “ALIGN” instruction to tell the assembler to insert the padding to word align after the string, the placement of the label (where the data block passed to Zap pointed to) was literally immediately after the string. However what followed was an instruction, not more data, so the assembler automatically added padding to correctly word align the code – but the label pointer remained where it was, at the end of the string. This address, when given to Zap, would be the one branched to. As the actual address is not divisible by four (it’s not a word address), the processor most likely discarded the bottom two bits and executed the end of the string, which turns out to look (to the processor) like an ANDEQ instruction, which may or may not have been executed (EQ conditional). The processor would then carry on to the correct location, so if there were no visible side effects, nobody would know anything is wrong. Fast forward to ARMv8 where the big stomping foot [editor: see this page about History Buff] comes down and says NO. And suddenly the problem is a lot more… visible. Kudos here to Clive Semmens for reporting the problem and persisting through various crashes to get me a register dump at the right point, highlighting the wonky value of PC; to Andrew McCarthy for the dump from Debugger which pointed me towards the “call_given_mode” function, indicating roughly where I should be looking; to Zap for bothering to include function names; and finally to Jeffrey Lee for making Debugger do more useful things. :-) |
Steve Pampling (1551) 8170 posts |
Oooh, echo’s of the zero page saga. |