DWMC-16: Instruction Set V0.5 – Deprecated

Yes… I know that I’ve put up the V0.4 revision of the Instruction Set just yesterday, but over night, thank you brain, I’ve mentally gone over a discussion I’ve read on the Usagi Electric Discord that involved someone else making their own instruction set and emulator. And how they were splitting the opcode from the addressing modes.

And… With the instruction set having grown to over 40 instructions in the last revision, I thought that maybe I should change the instruction set to also split the opcode from the addressing modes…

Legend

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

Addressing Modes

Since I have eight bits of opcode available, I want to limit myself to just two bits for the addressing moves, leaving six bits for 64 instructions.

Adressing ModeExampleBitcode
Immediate (Constants)ld R00, 0x0F0F0b00
Direct Localld R00, [0x0F0F]0b01
Direct (Global)ld R00, [0x0F0F0F]0b10
Register/Indirectadd R00, R01
ld R00
0b11

I have lumped in the Indirect Addressing mode and the Register Addressing mode together. It depends on the operation, whether it will be Register or Indirect Addressing mode, which will be noted in the Operation List below. There is the possibility of an Indexed Address mode, but that will be only inside the Assembler, not in the actual operations. It will be in the form of ldi R00, 4 which will more or less just insert add ZL, 4 in front of ldi R00.

OpCode Encoding

With the addition of the addressing modes, I will need to change the OpCode Encoding as well. Depending on the Address Mode, there maybe one or two Words after the actual Opcode.

MSBLSB
15141312111009080706050403020100
Type 1: One word, no registers
Word 1Opcode0000000000
Type 2: One Word, one register
Word 1OpcodeAddress ModeRegister/Flag0000
Type 3: One Word, two registers
Word 1OpcodeAddress ModeDestination RegisterSource Register
Addressing Mode: Direct Local
Word 2Low Address Word (16 bit)
Addressing Mode: Direct (Global)
Word 200000000High Address Word (8 bit)
Word 3Low Address Word (16 bit)

Data Transfer Operations (3 Operations)

CommandMnemonicOperationOpcodeRgister ModesOpTypeAffected Flags
Loadld Rd, Adr/CRd <= Memory[Addr]/C0b0000100b00, 0b01, 0b10, 0b11 (Indirect)2None
Loadst Rs, Addr16Memory[Addr] <= Rs0b0001000b00, 0b01, 0b10, 0b11 (Indirect)2None
Movemv Rd, RsRd <= Rs0b001000N.A.3None

With the new addressing modes, I can easily reduce the eight Operations from V0.4 back down to just three, even getting rid of the Load Constant Operation and the Load Indirect Operation.

Arythmic Logical Operations (13 Operations)

CommandMnemonicOperationOpcodeRegister ModesOpTypeAffected Flags
Addadd Rd, Rs/CRd <= Rd + Rs/C0b0100010b00, 0b11 (Register)3C, QC, HC, TC, Z, N, O
Incrementinc RdRd <= Rd + 10b010010N.A.2C, QC, HC, TC, Z, N, O
Substractsub Rd, Rs/CRd <= Rd – Rs/C0b0100110b00, 0b11 (Register)3C, QC, HC, TC, Z, N, O
Decrementdec RdRd <= Rd – 10b010100N.A.2C, QC, HC, TC, Z, N, O
Bitwise ANDand Rd, Rs/CRd <= Rd & Rs/C0b0101010b00, 0b11 (Register)3Z
Bitwise ORor Rd, Rs/CRd <= Rd | Rs/C0b0101100b00, 0b11 (Register)3Z
Bitwise XORxor Rd, Rs/CRd <= Rd ^ Rs/C0b0101110b00, 0b11 (Register)3Z
Bitwise NOTnot RdRd <= ~Rd0b011000N.A.2Z
Logical Shift Leftlsl RdRd <= Rd << 1
LSB <= Carry
Carry <= MSB
0b011001N.A.2C, Z
Logical Shift Rightlsr RdRd <= Rd >> 1
MSB <= Carry
Carry <= LSB
0b011010N.A.2C, Z
Logical Rotate Leftlrl RdRd <= Rd << 1
LSB <= MSB
0b011011N.A.2None
Logical Rotate Rightlrr RdRd <= Rd >> 1
MSB <= LSB
0b011100N.A.2None
Logical Switch Bytelsb RdRd[Low] <= Rd[High]
Rd[High] <= Rd[Low]
0b011101N.A.2None

The number of OpCodes for the Arithmetic Operations does not change, but it allows me to add Constants to at least some of the Operations. I have also gotten rid of the specific OpCode Encoding, as I previously had hoped to directly shunt the selection of the ALU operation from the OpCode into the ALU. But I do not think that its possible anymore with the drop of Opcode Length from eight to six bits, and me using the two upper bits to denominate that type of Operation.

Conditional Branch Instructions (10 Operations)

CommandMnemonicOperationOpcodeRegister ModesOpTypeAffected Flags
Branch local if Flagblf F, Addrif (F == 0): PCL <= Addr/Z0b1000000b01, 0b10, 0b11 (Indirect)2None
Branch if not Flagbnf F, Addrif (F != 0): PCL <= Addr/Z0b1000010b01, 0b10, 0b11 (Indirect)2None
Branch if Bitbb B, Addrif (B == 0): PC <= Addr/Z0b1000100b01, 0b10, 0b11 (Indirect)2None
Branch if not Bitbnb B, Addrif (B !=0): PC <= Addr/Z0b1000110b01, 0b10, 0b11 (Indirect)2None
Branch if Zero, Decrementbzd Rd, Addrif (Rd == 0): PCL <= Addr/Z
else Rd <= Rd – 1
0b1001000b01, 0b10, 0b11 (Indirect)2C, Z, N
Branch if not Zero, Decrementbnzd Rd, Addrif (Rd != 0): PCL <= Addr/Z
else Rd <= Rd – 1
0b1001010b01, 0b10, 0b11 (Indirect)2C, Z, N
Branch if Registers Equalbreq Rs, Rs2, Addrif (Rs == Rs2): PCL <= Addr/Z0b1001100b01, 0b10, 0b11 (Indirect)3C, Z, N
Branch if Registers not Equalbrne Rs, Rs2, Addrif (Rs != Rs2): PCL <= Addr/Z0b1001110b01, 0b10, 0b11 (Indirect)3C, Z, N
Branch if greater thenbgt Rs, Rs2, Addrif (Rs > Rs2): PCL <= Addr/Z0b1010000b01, 0b10, 0b11 (Indirect)3C, Z, N
Branch if greater then or equalbge Rs, Rs2, Addrif (Rs >= Rs2): PCL <= Addr/Z0b1010010b01, 0b10, 0b11 (Indirect)3C, Z, N

Like with the Arithmetic Operations, there is not change in the number of operations here, but it now does allow to do more ‘global’ jumps if there is a branching operations. I will also allow indirect jumps through the Z Index Register.

Other Operations ( 11 Operations)

CommandMnemonicOperationOpcodeRegister ModesOpTypeAffected Flags
Jumpjp AddrPCL <= Addr/Z0b1100000b01, 0b10, 0b11 (Indirect)1None
Jump to Subroutinejls Addr16ST <= PC + 1;
PCL <= Addr
0b1100010b01, 0b101None
ReturnretPC <= ST0b110010N.A.1None
Return from InterruptretiPC <= ST (see post)0b110011N.A.1Any
Push to Stackpush RsST <= Rs0b110100N.A.2None, Any
Pop from Stackpop RdRd <= ST0b110101N.A.2None, Any
Set Flagsf FF <= 10b110101N.A.2Any
Reset Flagrf FF <= 00b110111N.A.2Any
Set Bitsb BR08[B] <= 10b111000N.A.2None
Reset Bitrb BR08[B] <= 00b111001N.A.2None
No operationnopNo operation0xFFN.A.1None

With the new Addressing Modes, I can reduce the number of other operations down to eleven, getting rid of the Indirect Jump, as well as the ‘local’ and ‘global’ jumps I added in V0.4. The other operations do not really change at all. I also decided to just give the nop a fixed 16 bit opcode, since… Why not? :p

Conclusions

Maybe I should have taken a bigger think for the last v0.4 revision of the Instruction Set, when I added local and global addresses, especially since the same discussion inspired that revision I noted earlier. But it took a while before the penny with the address modes dropped for me.

Maybe I should let things like this stew a little longer in the back of my mind to grow a little more, before committing them to paper/a post.

But, now I am back down to 37 operations, after v0.4 rose up to 45 from 37. A thought might be to see if I could drop the differences between the Flag and Bit Test/Set operations by abusing the Register modes. That way, I would safe another four operations. Potentially I could do the same with Return/Return from Subroutine. That way I could get down to a cool 32 instructions.

With the Address Modes, I can certainly put a lot of potential operations and hide them in the Assembler. I can still have ldi in the assembler, which would change the operation to an ld operation for the machine code.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.