Skip to content

DWMC-16: Instruction Set V0.3 & Opcodes - Deprecated

In my last post, I've taken a few initial thoughts regarding opcodes. Added to that come first inklings to wanting to try my hand at writing an assembler in Python. But, to do that, I think I need to add at least one new command to load constant values from memory into memory, without having to resort to playing around with specific addresses.

I am also thinking I am keeping the split between the four forms of operations and use the upper nibble to designate the command type. Practically, that will mean I can tell a store operation from an add operation just by the upper nibble of the machine code.

Legend

Rd Destination Register
Rs, Rs2 Source Registers
PR Program Counter
C Constant Number
Addr Memory Address
ST Stack Pointer
F Flag bit
MSB Most Significant Bit
LSB Least Significent Bit

Data Transfer Operations

Command Mnemonic Operation Opcode Affected Flags
Load Direct ld Rd, Addr Rd <= Memory[Addr] 0b00000000/0x00 None
Load Indirect ldi Rd Rd <= Memory[Z] 0b00000001/0x01 None
Load Constant ldc Rd, C Rd <= C (PC+1) 0b00000010/0x02 None
Store Direct st Rs, Addr Memory[Addr] <= Rs 0b00000100/0x04 None
Store Indirect sti Rs Memory[Z] <= Rs 0b00000101/0x05 None
Move mv Rd, Rs Rd <= Rs 0b00001000/0x08 None

The Load Constant is the new operation, meant to directly load any 16 bit constant into a register, allowing to get around any Z register shenanigans.

Arythmic Logical Operations

Command Mnemonic Operation Opcode Affected Flags
Add add Rd, Rs Rd <= Rd + Rs 0b01000101/0x45 C, QC, HC, TC, Z, N, O
Increment inc Rd Rd <= Rd + 1 0b01010101/0x55 C, QC, HC, TC, Z, N, O
Substract sub Rd, Rs Rd <= Rd - Rs 0b01100101/0x65 C, QC, HC, TC, Z, N, O
Decrement dec Rd Rd <= Rd - 1 0b01110101/0x75 C, QC, HC, TC, Z, N, O
Bitwise AND and Rd, Rs Rd <= Rd & Rs 0b01000010/0x42 Z
Bitwise OR or Rd, Rs Rd <= Rd Rs 0b01000011/0x43
Bitwise XOR xor Rd, Rs Rd <= Rd ^ Rs 0b01000001/0x41 Z
Bitwise NOT not Rd Rd <= ~Rd 0b01000000/0x40 Z
Logical Shift Left lsl Rd Rd <= Rd << 1
LSB <= Carry
Carry <= MSB 0b01000110/0x46 C, Z
Logical Shift Right lsr Rd Rd <= Rd >> 1
MSB <= Carry
Carry <= LSB 0b01000111/0x47 C, Z
Logical Rotate Left lrl Rd Rd <= Rd << 1
LSB <= MSB 0b01010110/0x56 None
Logical Rotate Right lrr Rd Rd <= Rd >> 1
MSB <= LSB 0b01010111/0x57 None
Logical Switch Byte lsb Rd Rd[Low] <= Rd[High]
Rd[High] <= Rd[Low] 0b01001000/0x48 None

The Opcodes for the Arythmic Logic Operations look a bit strange, but that is mostly because I want to push the lowest three bits of the Opcode directly into the ALU and the other three bits can then be used to distinguish between the other operations that are similar.

Like Addition, Sustraction making use of the same logic circuits, for example. I also just realised that I can use two of those bits to directly push into the ALU to set the type of 'addition'. Bit 5 for indicating whether or not the operation is a substractive operation , while Bit 4 indicated of the operation is an increment/decrement.

The same is true for the Shift and Rotate operations, as they make use of the same logic, with the only difference being whether the shift happens through the carry bit or not.

The Logic Switch Byte is new, meant to switch the two bytes of the 16 bit words used by the DWMC-16 quickly, an operation useful if a program needs to push/pul data from an 8 bit IO device.

Conditional Branch Instructions

Command Mnemonic Operation Opcode Affected Flags
Branch if Flag bf F, Addr if (F == 0): PC <= Addr 0b10000000/0x80 None
Branch if not Flag bnf F, Addr if (F != 0): PC <= Addr 0b10000001/0x81 None
Branch if Zero, Decrement bzd Rd, Addr if (Rd == 0): PC <= Addr
else Rd <= Rd - 1 0b10000010/0x82 C, Z, N
Branch if not Zero, Decrement bnzd Rd, Addr if (Rd != 0): PC <= Addr
else Rd <= Rd - 1 0b10000011/0x83 C, Z, N
Branch if Registers Equal breq Rs, Rs2, Addr if (Rs == Rs2): PC <= Addr 0b10000100/0x84 C, Z, N
Branch if Registers not Equal brne Rs, Rs2, Addr if (Rs != Rs2): PC <= Addr 0b10000101/0x85 C, Z, N
Branch if greater then bgt Rs, Rs2, Addr if (Rs > Rs2): PC <= Addr 0b10000110/0x86 C, Z, N
Branch if greater then or equal bge Rs, Rs2, Addr if (Rs >= Rs2): PC <= Addr 0b10000111/0x87 C, Z, N

Other Operations

Command Mnemonic Operation Opcode Affected Flags
Jump Direct jmp Addr PC <= Addr 0b11000000/0xC0 None
Jump Indirect jmpi PC <= Z 0b11000001/0xC1 None
Jump to Subroutine jms Addr ST <= PC + 1;
PC <= Addr 0b11000010/0xC2 None
Return ret PC <= ST 0b11000011/0xC3 None
Return from Interrupt reti PC <= ST (see last post) 0b11000100/0xC4 Any
Push to Stack push Rs ST <= Rs 0b11000101/0xC5 None, Any
Pop from Stack pop Rd Rd <= ST 0b11000110/0xC6 None, Any
Set Flag sf F F <= 1 0b11000111/0xC7 Any
Reset Flag rf F F <= 0 0b11001000/0xC8 Any
No operation nop No operation 0b11111111/0xFF None

The Return from Interrupt operation does what it says on the tin, and was discussed in my previous post.

Conclusion

With that, the number of instructions, for now, raises to 37 again, after my last modification of the initial instruction set by slashing four operations.