Instruction set

I mentioned in my last post that my intention is to design with a two-address instruction set. This means that my instructions will have zero, one or two operands. There is no important reason for this. I am familiar with 6502 (accumulator, one-address) and x86 instruction sets, and I am more used to the latter, where you use two operands to move data between register/memory locations. It is just the matter of taste, not an architectural constraint. If at any point I decide to implement a three address instruction (e.g. an atomic compare and branch) and my control module will allow for this, I will go for it.

Below is an initial list of instructions I want to implement in the machine. This should be treated as a starting point. I am more than certain that the list will start expanding the moment I start writing first test programs.

Data transfer instructions

Mnemonic Description Example
LD Load memory data to register. LD A, #01FF
ST Store register data to memory. ST ($0010h), B
PUSH Push value onto stack. PUSH #15
POP Remove value from stack. POP A
MOV Copy register values (not memory contents). MOV B, C

Data manipulation instructions – arithmetic

Mnemonic Description Example
ADD Add operand values. Store the result in the first operand. ADD A, #1
SUB Subtract operands. Store the results in the first operand. SUB B, A
ADC Add operand values and the value of carry flag. ADC B, (SP:5) or ADC B, 5(SP)
SBC Subtract operand values and the value of carry. SBC A, (B)

We probably need instructions to set and reset machine flags here (C, Z, V, N, plus some more machine status bits) – to be added later.

Data manipulation instructions – logic

Mnemonic Description Example
AND Bit-wise AND of two operands. Store result in the first operand. AND A, #0000h
OR Bit-wise OR of two operands. Store result in the first operand. OR BL, #00001111b
XOR Bit-wise XOR of two operands. Store result in the first operand. XOR C, C
NOT Bit negation. One operand. NOT B
SHL Binary shift left by one position. Least significant bit zero filled. SHL A
SHR Binary shift right by one position. Most significant bit zero filled. SHR A
ROL Binary rotate left by one position. Most significant bit value is pushed to the least significant position. ROL B
ROR Binary rotate right by one position. Least significant bit value is pushed to the most significant position. ROR B

Still to be decided if we need binary right shift keeping the sign bit value (most significant bit). Would that be called arithmetic right shift? If it turns out necessary, it will be added as well.

Program control

Mnemonic Description Example
CMP Compare two values. Store flags. CMP AL, #1F
BR Branch unconditionally BR label
BE Branch if equal. BE label
BNE Branch if not equal. BNE label
BG Branch if greater. BG label
BGE Branch if greater or equal. BGE label
BL Branch if less. BL label
BLE Branch if less or equal. BLE label
CALL Routine call. Push PC onto stack. CALL _printf
RET Return from routine. Pop PC. RET
NOP Do nothing. Skip to next instruction. NOP
HALT Halt the machine. Do not fetch the next instruction. HALT

All comparisons signed and based on two’s complement arithmetic. (Do I need unsigned comparisons?)

Traps/interrupts

I haven’t really thought about it too much but it looks like I need at least the following instructions:

Mnemonic Description Example
(IRQn) Jump to interrupt service routine. Store machine status. Pseudo-instruction not accessible for programmer.
(TRAPn) Execute trap handler. Restore machine status from before the trap-causing condition. Pseudo-instruction not accessible for programmer.
IRET Return from interrupt service routine. Restore machine status. IRET
SYSCALL Generate software trap – call operating system function. SYSCALL #05h

Note that (IRQ) and (TRAP) are pseudo instructions, and I will have as many of them as there are, respectively, interrupt lines and trap conditions supported by hardware.

Now I will write a couple of test microcode routines for most typical instructions in each of the functional group.  This should give me an idea how my microcode word struct should look like and how to organize the microcode sequencer. It is also a good moment to decide on addressing modes the instruction set will support and map them reasonably onto instructions, keeping in mind that I have 256 opcodes (one-byte opcode will be used) and that I don’t want to complicate the hardware too much. I believe this is going to be a trade-off between instruction set expressiveness and instruction set orthogonality. The examples provided below already indicate more or less what addressing modes I will be implementing. These are:

  • operand implied – operand is implicitly implied by the opcode
  • immediate – constant value
  • direct – explicit memory address (instruction address is given as direct memory location)
  • indirect – instruction address is the address stored in given memory location
  • register direct – instruction address is explicitly given register
  • register indirect – instruction address is memory location at the address stored in register
  • register indirect with offset – instruction address is memory location at the address stored in register, plus offset (8/16 bit?)
  • PC-relative – instruction address is the value of program counter, plus offset (8/16 bit?)

I’ll be posting on the details soon.

Leave a Reply

  

  

  

Time limit is exhausted. Please reload the CAPTCHA.