1

I recently saw a video that explains how to make a Custom Instruction Set (just the concept ... how it would work). This video was part of a series that in total would have 3 videos: "How to make a Custom Instruction Set", "How to make an Assembler for that Custom Intruction Set", and the third would be "How to emulate the Custom Instruction Set". Unfortunately the third video was never released, so I went to find out if I could do it myself. After my research, I was quite inconclusive. Is it feasible to make Custom Instruction Sets? How do I emulate them? Do I need specific hardware if I really want to run it? How do I get this hardware?

PS: The videos that I've watched: 1st video, 2nd video. (click on them)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 4
    MARIE is a custom instruction set for a machine that only exists in emulation. Emulating a custom instruction set is the same task as (but possibly easier than) emulating an *actual* instruction set. The point about emulations is that you *don't* need special hardware to run them. – Weather Vane Apr 21 '21 at 17:58

2 Answers2

2

Emulation can be done several ways:

  1. Interpreter loop

An interpreter loop for that processor would look something like this:

uint16_t memory [ 65536 ];
uint16_t registerFile [ 7 ];
uint16_t pc = 0;
for(;;) {
    uint32_t ix = (memory [ pc ] << 16) + memory [ pc + 1 ]; // instruction fetch (32-bits)
    pc += 2;  // advance two words worth for next instruction as default
    switch ( ix >> 24 ) {
    case 0x00 : // Load R, Immediate
        uint16_t imm = ix & 0xFFFF;
        int regNumber = (ix >> 16) & 0x7;
        registerFile [ regNumber ] = imm;
        break;
    // other opcodes handled by cases
        
    }
}

You would make adjustments for the custom processor, such as whether the processor is byte addressable vs. only word addressable; whether big endian or little endian, etc..

  1. Various forms of Translation

We can translate machine code of one form into machine code of another form, i.e. from a custom instruction set to an existing instruction set.  The actual translation requires a mapping of the stateful features of the custom instruction set into stateful features of the existing instruction set, along with mapping of machine code operations over those stateful resources.

Because machine code programs can do indirect branches, whose operations are difficult to predict statically, a translating solution may include mapping tables to find where to go in the translation given the simulated program counter.

Machine code programs may also load (indirectly) from code memory, so the original machine code program may also be kept in the translation.

Sometimes the translation is done more or less dynamically as well, which is probably necessary if the custom processor allows for writing to code memory and later executing that new code.

Erik Eidt
  • 23,049
  • 2
  • 29
  • 53
  • Notably, qemu uses dynamic translation (into x86 machine code) when emulating some other common existing ISAs on x86. It's open source so you can look at the details. See also https://bochs.sourceforge.io/ - this paper (http://bochs.sourceforge.net/Virtualization_Without_Hardware_Final.pdf) presents at a high level some of the tricks and design techniques BOCHS uses to emulate fast. (Including caching some decode results in an easier-to-interpret format.) It has to emulate x86 including virtual memory, so it needs to emulate a TLB; a toy ISA would often omit that and be easy to decode. – Peter Cordes Apr 22 '21 at 00:52
  • Hello, thank you very much for your help. You don't even know how much you helped me. But I still have a question: how do I run this hardware program on real hardware? I already realized that to be "custom", it means that there is no hardware that supports my instruction set. But is there any way to make my own hardware? (easily if possible :) – Miguel Carvalho Apr 22 '21 at 15:24
  • You can implement the processor in a hardware language like Verilog, and run it on an FPGA. Verilog is pretty readable but will be somewhat foreign to software engineers, so learning curve. I haven't used an FPGA myself, though, so don't know the level of difficulty. I imagine you'd have to have a fairly complete system, including some I/O devices. By contrast, software emulation is fairly easy as you can write it in C or Java or C#, and you can handle I/O through the C/Java/C# language runtime. – Erik Eidt Apr 22 '21 at 15:27
  • Another thing to consider is using RISC V system, since the hardware is open source (free Verilog source code) and the instruction set is designed for custom extensibility, so you can start with the open source code and add an instruction or two. Not the same as designing your own custom processor, but food for thought. – Erik Eidt Apr 22 '21 at 15:31
2

Is it feasible to make Custom Instruction Sets?

Yes, of course! You can make anything you like! (Seriously) :) I assume that you have specific definitions in mind for "custom" and "instruction set". By "custom," to me that implies it's an instruction set not implemented on a known piece of hardware. A custom instruction set probably really implies a custom CPU architecture. (This leads to the answer to your last question, which I'll get to.) If you have a different definition of "custom," then you should share it. By "instruction set" I assume you mean commands that are similar in function and scope to existing CPU instruction sets (as opposed to something more extremely different or exotic). But in either case, the answer is still "yes".

How do I emulate them?

Erik's very informative answer has offered verious perspectives on this question. I will focus on a specific aspect. Assuming you are thinking of a custom instruction set that operates in the context of a standard von Neumann architecture that runs in a linear array of memory with a program counter, then your emulate would be a piece of software that pretends to be the CPU. As such, you would:

  • Define variables that represent the state of the CPU: a PC (program counter), registers (if your custom instruction set supports them), CPU status bits (if your custom instruction set and architecture uses them - likely it would), stack pointer (if your instruction set and architecture has a stack), etc.
  • Simulate the operation of your instructions and architecture. To do this you have to think about how your instruction set gets started. For example, some CPUs start at a specific memory location when they power up. Maybe yours would do something similar. You would define an array in your emulation software that represents the memory of your custom CPU. When your emulation starts (your custom CPU powers on) you would initialize your program counter and other state variables to their initial condition (defined by you) and start accessing instructions from memory (your array) just like a CPU would (fetch/execute cycle).

Do I need specific hardware if I really want to run it? How do I get this hardware?

If it's a custom instruction set, then I would think the hardware to execute it directly doesn't exist, at least by my definition of "custom" (otherwise, in what way is it custom?). My definition of "instruction set" is that it consists of instructions that are "close to the hardware", i.e., in one-to-one correspondence with the low level operations that the hardware directly knows how to execute. But as already noted, you can execute the instructions with your emulator. :)


In response to additional question in the comments.

But is there any way to make my own hardware? (easily if possible :)

Yes, there is of course a way to design and create the hardware needed to run a custom instruction set. Is it easy? It depends upon your skill level. You can find resources online on how to design a basic computer from scratch. Although the individual concepts are not difficult to understand for a basic CPU, it's not a trivial undertaking since there are lots of pieces to implement. You would be basically designing your own computer, from scratch.

If you're interested in this topic from a hardware perspective, I highly recommend looking up Ben Eater on YouTube. He has numerous excellent instructional videos discussing the creation of the various pieces of a CPU.

lurker
  • 56,987
  • 9
  • 69
  • 103
  • Hello, thank you very much for your help. You don't even know how much you helped me. But I still have a question: how do I run this hardware program on real hardware? I already realized that to be "custom", it means that there is no hardware that supports my instruction set. But is there any way to make my own hardware? (easily if possible :) – Miguel Carvalho Apr 22 '21 at 15:24
  • @MiguelCarvalho what do you mean by "hardware program"? It's just a program. :) I will update my answer to include your other question. – lurker Apr 22 '21 at 15:27
  • 1
    @MiguelCarvalho: You might want to read the RISC-V instruction-set manual; some of the comments on why it's designed that way mention ease of decoding in hardware (e.g. less muxing for certain bits of immediate operands, [Why are RISC-V S-B and U-J instruction types encoded in this way?](https://stackoverflow.com/a/59471596) quotes the text + diagrams I'm talking about). Of course RISC-V is aiming for high performance, but for a toy project you can just keep things simple for the hardware and accept tradeoffs like smaller jump displacements instead of "borrowing" bits with other purposes. – Peter Cordes Apr 23 '21 at 06:23