5

Recently ive been consumed by creating my own simple CPU architecture that at some point could be easily implemented in hardware (No FPGA, but actual Logic Gate circuits). Naturally to fulfill this requirement i went with a simple 4 Bit CPU, with a 4kB program space and 256 Byte RAM.

It supports all the fundamental operations such as ADD, Subtract, AND, LOAD, STORE etc. Before i start committing this to hardware i want to develop a moderately powerful software stack that could compile the a C/ C like language for the architecture, so the cpu could be programmed using a high level language. Currently i have written a working assembler in VB.NET, but now im stuck on how to approach the final goal of a working compiler.

Specifically i have the following questions:

What should be my next step, and how should i approach writing a compiler?

Even though a 4 Bit CPU is simple, it is not very useful as it cannot handle large calculations at once, thus my final goal would be abstract this inability by developing a software stack that to the user would be like programming a 16 bit (or larger) CPU. Currently i manually write assembly that can span larger numbers over multiple registers and perform calculations between them, but ultimately what part of the software stack deals with handling numbers and calculations which are greater than the size of the physical registers?

What part of the software stack deals with Subroutine calling etc?

Please let me know if i need to clarify anything.

8
  • 3
    I would guess, as you'd approach writing any other compiler. Why is the common path not sufficient?
    – Telastyn
    Commented Dec 27, 2014 at 13:58
  • 1
    recommended reading: Where to start?
    – gnat
    Commented Dec 27, 2014 at 14:22
  • 2
    @Adil: C cannot be compiled to architectures that do not support pointers, at least 8-bit bytes, call stacks, and such, as those are fundamental language features.
    – DeadMG
    Commented Dec 27, 2014 at 14:33
  • 1
    At your place, I would create a C-like (or Pascal-like) language with a custom compiler coded in Ocaml. However, I am not sure that a 4 bit computer is very fun. Can't you make it a 12 bit or a 16 bit one? Even with 74181 circuitry it does not mean a lot of hardware. Commented Dec 27, 2014 at 19:25
  • 1
    the vbcc compiler is easier to port to than llvm, llvm is non-trivial. there are many other compilers out there too that are open source and retargetable...just use google to find them...being 4 bit you are going to struggle though, even with sdcc...certainly with llvm...
    – old_timer
    Commented Dec 28, 2014 at 18:37

1 Answer 1

9

LLVM backend is the primary sane way of doing this. If you lower LLVM IR to assembly or microcode, you can roll from there and just use the numerous LLVM frontends to convert higher languages like C++ into LLVM IR.

In other words, LLVM was explicitly designed to support this scenario.

The full stack goes like this:

  • Frontend (e.g. Clang for C and C++) - source code -> LLVM IR
  • Optimizer (LLVM) - LLVM IR -> LLVM IR
  • Backend (you) - LLVM IR -> assembly/microcode/whatever

The first part is provided for you on a per-language basis. So for C and C++, you can use Clang, for D you can use LDC, etc. The second part is provided by LLVM- they provide a large number of target-independent optimization routines and some target-aware ones. Finally, you provide a translation service from LLVM IR to your architecture-specific code.

Note that LLVM IR makes a few guarantees, because they are targetted at real platforms. For example, they assume IEEE754 floating-point support and 8-bit bytes as well as various types of pointer support. You will need to support all of these anyway if you want to compile languages like C to target your architecture in general. If you are willing to restrict the source language a bit beyond normal you can get away without implementing all of these features- for example, if the C code doesn't use floats, in principle there's no reason why the frontend should emit float-using LLVM IR code.

LLVM IR is a common middle-ground that you can compile any language to target, and then from there, can be lowered for any CPU. Basically, all you need to do is support the primitives, and then provide an LLVM backend to convert from LLVM IR to your assembly. LLVM and language frontends will do all the rest.

3
  • Exactly what I was going to suggest. I'm not aware of any existing 4-bit back ends for llvm, but there are several 8-bit examples which should give you some idea how to approach porting llvm to more restricted architectures.
    – Jules
    Commented Dec 27, 2014 at 15:39
  • Ive never heard of that, having a look at it now. Just a sanity check: Is LLVM the middle ground which i should try to assemble for my own language? Can you please give me a brief overview how the software stack would flow here? Thankyou :)
    – MAM
    Commented Dec 27, 2014 at 15:48
  • 1
    Yes, llvm consists of a set of compilers that all emit a standardized, low level intermediate code form, optimizers that read that code and output in the same format, and code generators that read the same format and output assembly language. The format is very simple, and there's a c++ library for manipulating it, and lots of good documentation on how to write your own back end.
    – Jules
    Commented Dec 27, 2014 at 15:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.