I thought some of you might appreciate hearing about the internals of my emulator. In this post I'm going to introduce the instruction set, and cover the emulated memory model and registers. This is just the first post in this series, and will cover miscellaneous instructions. I'm keeping each post small, for easy digestibility.
Prerequisites
There are a couple of prerequisites to fully understanding this post. It will assume you know what a stack is and that you have some knowledge of assembly language. But the content could still be interesting even without that knowledge. I'll leave it to you to decide.
Registers/Memories
Most instructions involve the 256-byte data stack. There's also a 256-byte return stack to allow for subroutine returns. These stacks each have a stack pointer register that is not user accessible.
Addressable memory consists of 64KB of RAM, divided into the direct-page's 256 bytes at the beginning of memory, and then the remaining 64KB - 256 byte memory.
There are two directly user-accessible registers, DP and X. These offer the only means of accessing RAM, through register indexed access.
DP is an 8-bit register meant to serve as an index into the direct page. It offers pre- and post-decrement on store/read, but can also be used as a general purpose, 8-bit register.
X is a 16-bit register meant to serve as an index into the entirety of the 64KB of memory. It offers pre- and post-decrement on store/read, but can also be used as a general purpose register.
The remaining registers, CC and PC, are the condition and program counter registers, respectively. They are not directly user accessible, but affect, and are affected by, the operation of certain instructions. This will be discussed in future posts.
Instruction Types
There are four types of instructions available to programmers:
- Stack instructions - instructions that add to or remove items from the stack, or otherwise manipulate the positions of items on the stack
- ALU instructions - instructions that perform operations on the items at the top of the stack, such as addition, subtraction, or logic operations
- Flow control instructions - instructions that affect the program counter to change the execution flow of a program
- Miscellaneous instructions - instructions not falling into the other three categories, and the subject of this post
Miscellaneous Instructions
There are two miscellaneous instructions, SYSCALL, which triggers a system call, specified by its single byte operand, and SYNC, which exits the instruction execution to synchronize with the rest of the emulator loop.
SYSCALLs often require parameters, which are passed on the stack. The list of system calls is available in the source tree, under source/include/syscall.h. I'll be writing up another post in the future on the parameters and operation of different syscalls.
SYNC will interrupt instruction execution and allow the rest of the emulator's main loop to process. This was mainly intended to update the bitmapped screen from the emulated memory to the SDL window displaying the image.
SYSCALL also interrupts instruction execution in order to execute the host-side code that implements the system call. In essence, SYNC acts as a NOP syscall, since it interrupts instruction execution, but doesn't execute any code.
Next Up
The next article will focus on stack instructions; that is, instructions which manipulate the items on the stack without arithmetic or logic operations. This includes adding to and removing from the stack, moving items around on the stack, and setting or saving the DP and X registers.
Comments