To start off with understanding how registers work, you need to know what happens at the electrical level. There are several types of 'memory', meaning it can store a value, that a processor can use.

In order from fastest to slowest:

  • Registers
  • Internal RAM/ROM
  • External RAM/ROM on the address bus.
  • External RAM/ROM on a serial bus like SPI. Want to add memory to your ECM? Wire this sucker up!

This is a simple view, because modern processors can use hard drives, cdroms, and they also have ultra fast cache memory. But you can ignore that for our simple GM ECMs.

Registers are sets of latches or flip-flops that store voltages. The linked website is excellent, I recommend you read it over. Even if you don't understand it right away, try to let it absorb into your brain.

I don't know what the HC11 uses for its registers, all I know is that when I say LDAA #$F0, it sets a group of 8 latches or flip-flops to their correct voltages.

Now, why do we deal with registers, rather than just using RAM all the time. The answer is speed! In processor terms, it's slow to read, modify, write a byte in RAM. It's much, much faster to use a register.

For example, to increment an accumulator, it only takes 2 clock cycles. To increment a memory byte, it takes 6 cycles, or 7 if you are indexing from a Y register.

'''TODO''' Do people want more explanations here?

= 68HC11 Registers =

The 68HC11 has the following registers:

== Accumulators ==

  • Accumulator A:

As you can tell from it's name, it's used to accumulate numbers. It's basically a scratch pad area for you to use. It only holds one byte at a time. Don't let your numbers get bigger than 1 byte if you are working with this!

  • Accumulator B:

Another scratch pad for you to use. Instructions like LDAB or STAB set it.

  • Accumulator D:

This is a 16-bit register that is made up of accumulators A and B.

There are a bunch of commands that are associated with the accumulators, mostly for doing math stuff.

== Indexing Registers ==

  • X Register: A 16-bit register.
  • Y Register: A 16-bit register.

These are called indexing registers because they have special instructions to deal with doing stuff that depends on an index. Mostly branching operations.

The X register is faster than the Y register. Generally indexing operations with the Y register take an extra clock cycle, so use X if you have the choice.

'''TODO''' Need some code examples to show how to use an index register.

== The Stack Pointer ==

This register points to a memory location in RAM. The stack is used as a secondary work space when the A, B, X, Y registers aren't enough, or if the processor is doing special things like jumping to 68HC11Subroutines|subroutines? . This stack pointer needs to be initialized before you start using it. It should be the very first instructions you do!

LDS #$01FF ; Set the stack pointer to $01FF in RAM

You have to be careful that your stack pointer doesn't grow into your RAM that you are using. You should figure out how many stack positions you need, so you can tell how much RAM you can have.

The stack pointer grows down, so every time something is added to the stack, the stack pointer gets 1 subtracted from it.

It seems like the stack is set up to use from $1FF down to $100 in most masks.

The stack is used heavily in subroutines to make sure that subroutines are '68HC11Subroutines#Reentrant|reentrant? '. In plain English, that means that they can be called multiple times by a larger program.

== Program Counter ==

The Program Counter, or PC, keeps track of where your program is at all times. Normally it gets increased by small values, to step from instruction to the next instruction. '''Note:''' This is not a constant value, because instructions in machine code are not a contstant length! For example, look at the following code from the bua_hac:

LCBD9: CLRA ; Clr Minor loop counter LCBDA: STAA L0000 ; Save Minor Lp Count

The CLRA instruction does not take any prebytes, so the PC is only incremented by one to get to the next label, $CBDA.

But in this case:

LCCCC: LDX $0110 ; Get RAM Addr. LCCCF: SEI ; TURN OFF INTERUPTS

The PC changes from $CCCC to $CCCF. It's because of that $0110 address that was included in the instruction. We need to skip over those two bytes in the PROM, so the PC will be pointing to the correct position when it does the next instruction fetch.

In a perfect world, you wouldn't need to worry about this, but it's good to know in case you are doing any tricks!

== Condition Codes ==

The condition code register is where a lot of the magic happens in a program. The branch instructions use these heavily, and it really deserves it's own page? .

  • Bit 7: Stop Disable
  • Bit 6: X-Interrupt Mask
  • Bit 5: Half carry
  • Bit 4: I-Interrupt Mask
  • Bit 3: Negative Indicator
  • Bit 2: Zero Indicator
  • Bit 1: Two's Complement Overflow Indicator
  • Bit 0: Carry/borrow from MSB

There are tons of ways to set these bits, the strategy is to do something, then see what flags were set, and use that to determine how to continue the program.

For an example, turn to page A-10 of the Pink Book? , the AND instruction.

The description says that is performs a logical AND between ACCX (either ACCA or ACCB) and M (a memory location).

So lets say you want to check if a flag is set, and the flag is bit 5 in memory location $0035. You would do something like this:

LDAA $0035; Get the Mode Word 1 ANDA #$20; Mask it with %00100000 to get bit 5

The pink book says that the following conditions codes are set:

N = R7 Bit 3, the negative indicator, is simply the 7th bit of the result. This means that the number is negative. This doesn't affect us here, so we don't worry about it. It has something to do with binary math.

Z = 1 if any of the bits = 1, otherwise it is 0.

V = 0 It will always be cleared by an AND instruction.

Pretend this was a routine to check if the VATS error check is enabled. The rest of the code would read something like this:

BNE LvatsErrChk? ; The error check flag was not set, so skip the check routine. ; Start the VATS check

Is this the most efficient way of doing it? Maybe. Depends what you are doing afterwards, like will you be using the result stored accumulator A again? (Hint: Look at the BRSET instruction)

How do you figure out which instruction to use? Remember that the designers of the processor looked into all of the situations, and whatever seems right to you probably does what you want.

-- AlexHarford - 30 Jun 2006

Topic revision: r1 - 30 Jun 2006 - 22:51:03 - AlexHarford
 
This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback