Wednesday, October 28, 2009

Software Interrupt Odyssey

So, I had a few nasty bugs while dealing with software interrupts.

The first one arose with my code triggering a data abort exception once the software interrupt handler was finished. It took me a little bit of thinking to figure this one out, but what was happening requires a bit of a technical and detailed explanation:

When you enter the software interrupt mode, your stack pointer changes. Each different mode that the CPU supports has their own stack pointer for security purposes. Therefore, when you are finished in the mode, you have to switch the mode back, but you also most likely have to manipulate your stack pointer (as all the registers are saved since they are modified in your mode handler). You need to do the mode switch and register restore in one operation, which basically reloads all the registers and jumps back to where you were before the mode handler was set off.

My implementation of this operation failed to take into account that the mode could be switched during the operation, and if so, the stack pointer cannot be modified. Therefore, what was happening was that the stack pointer was being returned in an incorrect state, and a "data abort exception" was happening as a result.

The other bug occurred in my rendering code; it was also data aborting because the stack pointer was invalid. What was happening in the end was that my rendering code was actually modifying an instruction that was to be executed, which was telling it to modify the stack pointer more than it needed to be modified! Another bug that took a few minutes to find, but once I saw the modified instruction, I knew exactly what the problem was.

However, my software interrupt handlers are still very up in the air. I'm not entirely sure what parameters each one take, how they take them, plus how they return their results. I'll figure this out somehow, but for now it's a bit hacked together, which isn't a good thing and needs to be taken care of.

When programming, odd bugs like the data aborts happen all the time. They're the type of bugs that can really throw off your tempo and rhythm and force you into a debugging session with an unclear understanding of when it will end. The best solution to this is to simply not let it disrupt your tempo, but rather adapt your tempo to the task at hand and just focus on solving it, solving it well, and being willing to change whatever needs to be changed.

I'm heading off to Europe in a few hours, so I'll most likely update this blog when I get back on November 14th.

Saturday, October 24, 2009

Much better progress

Had a much better session today. I implemented the symbol debugger and began work on the BIOS SWI routines. The symbol debugger was easy to finish off, and it's very useful already.

The SWI routines are an interesting batch. They are basically like what system calls are to an operating system. The average system has two modes of operation: user mode and kernel mode, which is also known as privileged mode. User mode is where your programs run, and privileged mode is where the operating system runs. Whenever your program wants to run an operation that the operating system can do; such as open a file, it makes a system call which passes control to the operating system, which then does its work.

The SWI's function in the same way; they are routines provided by the BIOS that do things such as divide (as the ARM has no native divide instruction) or wait for a vertical blank interrupt. Implementing them all is essential, but by their names, they are quite detailed.

Also, for some random reason, if you do an SWI through ARM code, you have to specify the number in the upper 16-bits of the expression, like:

SWI 0x00010000: Perform operation 1

Not quite sure why this is, but it was in one of the DS manuals I've been reading.

Thursday, October 22, 2009

Progress

I continued work on the symbol debugger today, but I wasn't feeling too well, so I left Starbucks a bit earlier than I wanted to.

I hashed out a few things; the loader within the emulator for the debugger file, as well as the command line option to enable/disable the debugger for each chip in the DS. I also put in a command line option to specify the BIOS image to load, as this serves its purpose right away for the debugger file format.

You really have to constantly stay on your toes when you're working on something. A common pitfall is to plan out exactly what you're gonna write code-wise then just write it. This is a pitfall because lots of people don't realize that writing code is like constructing a building; you can have a blueprint, but there are also challenges in using the hammer, saw, and other tools. You have to be on your toes as to the best way to write functions both in the short-term and the long-term, from optimization to cleanliness. The trick is to strike some sort of personal balance between thinking quickly and thinking slowly; a zen that creates confidence within you in the idea that you're doing it your own way.

Tuesday, October 20, 2009

Debugger progress

So it turns out it wasn't an incorrect shift. What was happening was that my count variable was getting set to zero right away as a result of the multiplication op, and therefore by the time that the loop was checking its status, it was already negative.

This was happening because there was a bug in my assembler that wasn't properly checking to see if I could load immediate operands into registers. The instruction to do so is a bit unique; you pass it an 8 bit number and a 4 bit rotate value; you then rotate the 8 bit number by twice the 4 bit rotate value. This means that you can get all powers of 2, but you also cannot get every possible number.

I was trying to load my registers with 0x00100010, which cannot be loaded. I have error checking code to make sure this reports an error, but the bug prevented this error from coming up. Once fixed, everything proceeded smoothly.

I also started on the symbol debugger today. I decided on the file format and wrote the code in the assembler to save to it if it's specified on the command line. However, I need to put more thought into how the emulator will handle this. How the emulator handles debugging currently is a bit of a hack, not very bad, but it needs to be polished up a little bit.

Debugger

So I ran into a bug yesterday where I believe a shift is being done incorrecly, and leaving a multiplication result negative. This occurs on a register that stores a count variable, so it never hits zero and I run into a loop which doesn't break until a data abort.

I could easily find the cause of this, but I decided to postpone it for the day to think about a feature I wanted to add to the emulator's debugger: symbol lookup. Currently, if I want to set a breakpoint I have to enter in the exact address, which is fine, but when I just want to jump to a function without having to go through anything else, I essentially have to run the program twice; once to get the address of the function, and the other to actually debug it. Now, I could calculate this just by looking at the binary, as that's just awesome and fun, but if I want this to be used, I don't think I want to force that.

Symbol tables in this case are complex. First of all, each binary has a number of different sections, and symbols are local to sections. Therefore, duplicate naming must be taken into account, so I need to probably prompt the user of the debugger for all possible choices if there are any, when they want to break at a symbol. Furthermore, there are many different binaries that are in use by the emulator. You have the BIOS, which loads the firmware, which can load the Pictochat program or a game. You can't just have one giant symbol table for all these binaries, but at the same time, you have to make some sort of distinction. I think what I'm going to do is just allow only one binary to be debugged for now...how that will be specified is a challenge for a later date. What needs to be done now is modifying my assembler/linker to place the symbols in the binary and classify it as a "debug" binary, instead of a raw one.

Monday, October 19, 2009

Rain and Starbucks

Had a coding session at Starbucks today, while it was pouring down rain outside (unusual for California during a drought). I spent most of my time continuing to dissect the Nintendo DS video architecture; it's definitely the biggest and most detailed challenge I've come up to so far while writing my emulator. It was more of a learning session to get myself totally up to speed on the architecture; all the registers, modes, settings, etc. but I was able to write a bit of code. The direct-framebuffer mode is the first mode I'm tackling, as it's the least complex and can get the ground running.

First

This is mostly just a journal of sorts to keep track of my development progress for the day. I have lots of things on my plate; Nintendo DS development, Facebook development, and Android development are the top three.