Categories DWMC-16

DWMC-16: Instruction Set V0.3 & Opcodes

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.


RdDestination Register
Rs, Rs2Source Registers
PRProgram Counter
CConstant Number
AddrMemory Address
STStack Pointer
FFlag bit
MSBMost Significant Bit
LSBLeast Significent Bit

Data Transfer Operations

CommandMnemonicOperationOpcodeAffected Flags
Load Directld Rd, AddrRd <= Memory[Addr]0b00000000/0x00None
Load Indirectldi RdRd <= Memory[Z]0b00000001/0x01None
Load Constantldc Rd, CRd <= C (PC+1)0b00000010/0x02None
Store Directst Rs, AddrMemory[Addr] <= Rs0b00000100/0x04None
Store Indirectsti RsMemory[Z] <= Rs0b00000101/0x05None
Movemv Rd, RsRd <= Rs0b00001000/0x08None

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

CommandMnemonicOperationOpcodeAffected Flags
Addadd Rd, RsRd <= Rd + Rs0b01000101/0x45C, QC, HC, TC, Z, N, O
Incrementinc RdRd <= Rd + 10b01010101/0x55C, QC, HC, TC, Z, N, O
Substractsub Rd, RsRd <= Rd – Rs0b01100101/0x65C, QC, HC, TC, Z, N, O
Decrementdec RdRd <= Rd – 10b01110101/0x75C, QC, HC, TC, Z, N, O
Bitwise ANDand Rd, RsRd <= Rd & Rs0b01000010/0x42Z
Bitwise ORor Rd, RsRd <= Rd | Rs0b01000011/0x43Z
Bitwise XORxor Rd, RsRd <= Rd ^ Rs0b01000001/0x41Z
Bitwise NOTnot RdRd <= ~Rd0b01000000/0x40Z
Logical Shift Leftlsl RdRd <= Rd << 1
LSB <= Carry
Carry <= MSB
0b01000110/0x46C, Z
Logical Shift Rightlsr RdRd <= Rd >> 1
MSB <= Carry
Carry <= LSB
0b01000111/0x47C, Z
Logical Rotate Leftlrl RdRd <= Rd << 1
Logical Rotate Rightlrr RdRd <= Rd >> 1
Logical Switch Bytelsb RdRd[Low] <= Rd[High]
Rd[High] <= Rd[Low]

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

CommandMnemonicOperationOpcodeAffected Flags
Branch if Flagbf F, Addrif (F == 0): PC <= Addr0b10000000/0x80None
Branch if not Flagbnf F, Addrif (F != 0): PC <= Addr0b10000001/0x81None
Branch if Zero, Decrementbzd Rd, Addrif (Rd == 0): PC <= Addr
else Rd <= Rd – 1
0b10000010/0x82C, Z, N
Branch if not Zero, Decrementbnzd Rd, Addrif (Rd != 0): PC <= Addr
else Rd <= Rd – 1
0b10000011/0x83C, Z, N
Branch if Registers Equalbreq Rs, Rs2, Addr if (Rs == Rs2): PC <= Addr0b10000100/0x84C, Z, N
Branch if Registers not Equalbrne Rs, Rs2, Addrif (Rs != Rs2): PC <= Addr0b10000101/0x85C, Z, N
Branch if greater thenbgt Rs, Rs2, Addrif (Rs > Rs2): PC <= Addr0b10000110/0x86C, Z, N
Branch if greater then or equalbge Rs, Rs2, Addrif (Rs >= Rs2): PC <= Addr0b10000111/0x87C, Z, N

Other Operations

CommandMnemonicOperationOpcodeAffected Flags
Jump Directjmp AddrPC <= Addr0b11000000/0xC0None
Jump IndirectjmpiPC <= Z0b11000001/0xC1None
Jump to Subroutinejms AddrST <= PC + 1;
PC <= Addr
ReturnretPC <= ST0b11000011/0xC3None
Return from InterruptretiPC <= ST (see last post)0b11000100/0xC4Any
Push to Stackpush RsST <= Rs0b11000101/0xC5None, Any
Pop from Stackpop RdRd <= ST0b11000110/0xC6None, Any
Set Flagsf FF <= 10b11000111/0xC7Any
Reset Flagrf FF <= 00b11001000/0xC8Any
No operationnopNo operation0b11111111/0xFFNone

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


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.


Leave a Comment