Page 1 of 3

KIL opcodes and such

Posted: Fri Aug 08, 2014 12:07 pm
by mikaelmoizt
This might be one of those questions that just could be answered theoretically, or just handled as "because it is so, dumbass."

But anyways.. *question got more complex as I began writing.. too much coffee*.

Since I started NES hacking about one year ago - and learning 6502 assembler - , I quickly found that certain "opcodes" would simply crash the cpu.
Yes, the KIL/HLT/DIE whatever you want to call them. Mostly "opcodes" with $*2. Mainly from branching to incorrect location, or forgetting to RTS from somewhere and end up in <wrong place>.. or from some datacollection.. you know how this could happen :wink:

The question is, WHY? I can see the reasoning behind stopping CPU by a BRK and having some control over the continued processing, but this just stops and halts until a reset. Was this intended as a forced stop or was it some kind of costcutting measure? I mean, there are a LOT of opcodes that crash the CPU instantly. Why have some potential programming error stop CPU irreversebly? Faulty design?

I watched some youtube movie about reverse engineering the 6502 where, if I remember correctly, this topic was adressed.
Still, I wonder why not have the CPU ignore opcodes like those and carry on? By software or hardware trapping buffer of some sort. For game consoles, this must have been a good idea? Maybe Nintendo REALLY trusted the individuals writing games for their console back in the days. A crashed game = unhappy player = the game itself and Nintendo gets bad publicity.

Like who cares? It worked, didn´t it?

Re: KIL opcodes and such

Posted: Fri Aug 08, 2014 12:10 pm
by lidnariq
mikaelmoizt wrote:was it some kind of costcutting measure?
You got it.
A crashed game = unhappy player = the game itself and Nintendo gets bad publicity.
By the time you're in danger of executing KIL, you're already trying to execute garbage and the game won't be able to recover to something reasonable anyway.
KIL might even be preferable to arbitrary execution, especially in games with battery-backed saves.

Re: KIL opcodes and such

Posted: Fri Aug 08, 2014 12:14 pm
by JRoatch
What happens with all the KIL opcodes is that a flag responsible for ending the instruction never gets reset, or as visual6502 puts it "KIL will put the T-state counter into an unrecoverable state". I like to think of them being infinite sized instructions.

Re: KIL opcodes and such

Posted: Fri Aug 08, 2014 12:20 pm
by tepples
Even the 65816 core in the Super NES's S-CPU has one ($DB), though this time it's intentional because it puts the processor into an extreme low-power state.

Re: KIL opcodes and such

Posted: Fri Aug 08, 2014 12:29 pm
by rainwarrior
There's no point in carrying on from a bad opcode anyway. The chances that the game recovers in a meaningful way are low.

But yeah, these aren't really intentionally designed that way. They just didn't implement anything for the bad opcode, and more or less what was already hooked up defined what it would do. This is why a lot of bad opcodes seem to perform combinations of things that valid opcodes do. All they really need to make sure of for bad opcodes is that using them doesn't damage the system. As long as that's taken care of they can let whatever happens happen.

Lately I've been filling unused space in my ROM with NOPs, which, by accident, happened to create a NOPslide directly into the initialization code which I was storing at the high end of the bank before the vector table, so execution from an empty error actually results in a "reset", more or less, tough maybe I should try to stick a diagnostic in there before the init code.

Protecting battery-backed saves is a good reason to use the halting instructions, I hadn't thought of that. Though, many carts with this feature had a write protect option built into the mapper.

Re: KIL opcodes and such

Posted: Fri Aug 08, 2014 12:59 pm
by koitsu
rainwarrior wrote:There's no point in carrying on from a bad opcode anyway. The chances that the game recovers in a meaningful way are low.
This. Though I would have rephrased it as: stop using undocumented opcodes. (How many times do I have to tell people this? :P Haha)

Re: KIL opcodes and such

Posted: Fri Aug 08, 2014 1:03 pm
by mikaelmoizt
lidnariq wrote:By the time you're in danger of executing KIL, you're already trying to execute garbage and the game won't be able to recover to something reasonable anyway.
KIL might even be preferable to arbitrary execution, especially in games with battery-backed saves.
Ah. I see that way of thinking. A loose cannon wrting into save data and such, both by running into undesired places of written code, and into garbage that just happens to do stupid stuff.. And when the stop comes, hopefully not much garbage execution has been done.

I thought of the possiblity of (somehow) treating KIL opcodes like BRK or forcing RESET, but it wouldn´t matter much to the player, right? :)
Lately I've been filling unused space in my ROM with NOPs, which, by accident, happened to create a NOPslide directly into the initialization code which I was storing at the high end of the bank before the vector table, so execution from an empty error actually results in a "reset", more or less, tough maybe I should try to stick a diagnostic in there before the init code.
Hrm. Yeah.. I know exactly what this means. I was trying to make an expanded SMB ROM hack some months ago and changed a large section with $EA instead of the prewritten $FF all the way to end of ROM. So, RESET it was.

Also, before I knew all about the vectors, I put a RTS at $FFFE "just in case we end up there".. That went wrong in so many ways.. :oops:
Even the 65816 core in the Super NES's S-CPU has one ($DB), though this time it's intentional because it puts the processor into an extreme low-power state.
Interesting. Does it trigger any flag or give some register change for the debugging purpose?

Re: KIL opcodes and such

Posted: Fri Aug 08, 2014 1:07 pm
by mikaelmoizt
koitsu wrote:
rainwarrior wrote:There's no point in carrying on from a bad opcode anyway. The chances that the game recovers in a meaningful way are low.
This. Though I would have rephrased it as: stop using undocumented opcodes. (How many times do I have to tell people this? :P Haha)
LAX seem to work just fine tho :wink:

Nah, jk

EDIT: cant find hex for it..

Re: KIL opcodes and such

Posted: Fri Aug 08, 2014 1:11 pm
by tepples
koitsu wrote:I would have rephrased it as: stop using undocumented opcodes. (How many times do I have to tell people this? :P Haha)
Why, when so many of them are so useful?

Re: KIL opcodes and such

Posted: Fri Aug 08, 2014 5:13 pm
by tokumaru
Undocumented instructions are really useful when you're under tight timing constraints, if they can do the job faster than the equivalent official instructions. They're often used in Atari 2600 homebrew, because on that system you have only 76 cycles per scanline to update playfield, players, missiles and ball. If an undocumented instruction can get you better graphics or more objects in an Atari 2600 game, I think they should be used.

Another good example are those amazing 3D polygon demos posted in this forum a while ago. IIRC, undocumented instructions were used to speed up the polygon filling, which is a very repetitive process, meaning that every cycle you can save will add up to a great deal of saved time. The smoothness of those real-time 3D animations is incredible.

Re: KIL opcodes and such

Posted: Fri Aug 08, 2014 7:02 pm
by Myask
I found http://www.pagetable.com/?p=39 most useful in terms of understanding what was going on for KIL/JAM/CIM/HLT.
koitsu wrote: Though I would have rephrased it as: stop using undocumented opcodes. (How many times do I have to tell people this? :P Haha)
One need not intend to use them for the processor to reach the second byte of your LDX #2. Or for your processor to jump into RAM which happens to have some twos in it.

Undocumented codes are also quite useful when you are only allowed to patch three bytes; sometimes you really do need that Branch Never DOP that doesn't muck with registers or status.
rainwarrior wrote:Lately I've been filling unused space in my ROM with NOPs, which, by accident, happened to create a NOPslide directly into the initialization code which I was storing at the high end of the bank before the vector table, so execution from an empty error actually results in a "reset", more or less, though maybe I should try to stick a diagnostic in there before the init code.
I ran into that on my Hello World hex implementations. Only NOPs (or anything that just lets you keep on going) means you always get somewhere. I wonder how many people actually use the "signature byte" of a BRK.
mikaelmoizt wrote: LAX
EDIT: cant find hex for it..

Code: Select all

    Air #   zp  z,X a   a,X a,Y (,X)(),Y alias |Notes
LAX _   AB* A7  _   AF  _   BF  A3  B3  ANX ATX|LAX z,Y: B7. Load both A/X.*AB somewhat unstable, aka OAL, LXA 

Re: KIL opcodes and such

Posted: Sat Aug 09, 2014 11:33 pm
by Omegamatrix
tokumaru wrote:Undocumented instructions are really useful when you're under tight timing constraints, if they can do the job faster than the equivalent official instructions. They're often used in Atari 2600 homebrew, because on that system you have only 76 cycles per scanline to update playfield, players, missiles and ball. If an undocumented instruction can get you better graphics or more objects in an Atari 2600 game, I think they should be used.
Yep, illegal opcodes can be useful. On the 2600 LAX, SBX, DCP, SAX, double, and triple NOP's are often used.

Re: KIL opcodes and such

Posted: Sun Aug 10, 2014 1:10 pm
by zzo38
Stable unofficial opcodes are really useful and I use them a lot; I just use them whenever I find them useful even if there aren't tight timing constraints; I still try to save bytes and cycles in the program. Unstable opcodes should not be used (KIL is one).

Here is an example:

Code: Select all

	sta <t0
	ror a
	arr #$FF
	bvs predicf
Using only official instructions, it is like this (and is one cycle longer):

Code: Select all

	sta <t0
	ror a
	eor <t0
	bmi predicf
(The value of the accumulator is not used after that point anyways; the value then used is loaded from the t0 variable.)
rainwarrior wrote:Protecting battery-backed saves is a good reason to use the halting instructions, I hadn't thought of that. Though, many carts with this feature had a write protect option built into the mapper.
Is there documentation on battery RAM protection and how all of that works? What kind of hardware protections are possible other than write-protect?
mikaelmoizt wrote:I thought of the possiblity of (somehow) treating KIL opcodes like BRK or forcing RESET, but it wouldn't matter much to the player, right?
As far as I am concerned probably an emulator should display an error message in such a case, followed by advancing the PPU to the next frame (without executing any more CPU instructions) and stopping execution (also displaying the debugger if it is enabled and implemented). Hardware implementations should probably just halt the CPU like they already do.

Re: KIL opcodes and such

Posted: Mon Aug 11, 2014 2:06 am
by Bregalad
stop using undocumented opcodes
I'm glad I'm not alone with this one. Everything that can be done with illegal opcodes can be done with legal ones. (hint : illegal opcodes are doccumented, so it makes no sense to call them "undoccumented". And yes I know they are "legal" in a law point of view, but at least it makes more sense to call them that)

I don't see. They're just like drugs, they're illegal and they're not cool. Anyone who think they're cool because they're illegal is just a rebel teenager and is plain wrong.

As for killing the CPU with legal opcode, just turn all interrupts off, and do a :
here : jmp here

It's equivalent, using normal opcodes.

Re: KIL opcodes and such

Posted: Mon Aug 11, 2014 5:16 am
by tokumaru
Bregalad wrote:Everything that can be done with illegal opcodes can be done with legal ones.
Mathematically, sure, but speedwise, not always. I certainly avoid illegal/undocumented instructions, but if using them in a tight loop can improve the graphics and/or frame rate, I'll definitely consider using them.
(hint : illegal opcodes are doccumented, so it makes no sense to call them "undoccumented".
They're not officially documented though, right? IMO "illegal" is just as bad as "undocumented", because there are absolutely no legal implications in using those opcodes. "Unofficial" sounds more appropriate I guess.
I don't see. They're just like drugs, they're illegal and they're not cool.
The legality of drugs varies from place to place. Alcohol is legal everywhere.
Anyone who think they're cool because they're illegal is just a rebel teenager and is plain wrong.
In programming it's not (or shouldn't be!) about being cool, but being useful. There's always a price though: when you use illegal/undocumented/unofficial opcodes to noticeably improve your program, you're risking compatibility with clones and such, which might not support said opcodes.