Smaller C (was: What does your OS look like?)
Posted: Tue Mar 04, 2014 5:32 am
Wow, first users of Smaller C!Bender wrote: And gcc is also boring, so?
SmallerC
The Place to Start for Operating System Developers
http://f.osdev.org/
Wow, first users of Smaller C!Bender wrote: And gcc is also boring, so?
SmallerC
Welcome to ★☆OSDev.org ☆★alexfru wrote:Wow, first users of Smaller C!
Code: Select all
#define FUNC(VARS) DO_STUFF()
Until a proper preprocessor has been developed for Smaller C, your only options are:Bender wrote: I find SmallerC simple, although it may have certain limitations, but I wanted to choose the "other" way, cause I wanted something special.
The only problems I see is the "#define" preprocessor command which doesn't support parametrized macros.
Like:Hope to see this fixed.Code: Select all
#define FUNC(VARS) DO_STUFF()
I suggest you to take a look at TinyCC: http://bellard.org/tcc/ -> http://repo.or.cz/w/tinycc.gitjal wrote:I don't want to derail this thread, but allow me to ask a short question re SmallerC: would it be easy to retarget it to a different platform? I'm developing a CPU on an FPGA, and would love a C-compiler for it (the assembler is more or less finished).
JAL
A basic port (like the MIPS code generator of Smaller C) shouldn't be problematic. But ultimately it all depends on how primitive, complex or convoluted the target is and how far you're willing to go.jal wrote:I don't want to derail this thread, but allow me to ask a short question re SmallerC: would it be easy to retarget it to a different platform? I'm developing a CPU on an FPGA, and would love a C-compiler for it (the assembler is more or less finished).
Currently it's a simple 16-bit CPU without multiplication and division, with separate address spaces for code and data.alexfru wrote:A basic port (like the MIPS code generator of Smaller C) shouldn't be problematic. But ultimately it all depends on how primitive, complex or convoluted the target is and how far you're willing to go.
That is insufficiently descriptive.jal wrote:Currently it's a simple 16-bit CPU without multiplication and division, with separate address spaces for code and data.
Well, I can elaborate a bit. It's a fairly standard RISC with minimal instructions. The CPU has 16 16-bit registers, of which one is hardwired to 0, and one is used as program counter. Instructions may have three registers as operand (rrr: destination, term1, term2), two registers and a 4-bit immediate value (rri), or a single register and a 16-bit immediate value. Instructions are add, sub, bit shift, all with both rrr and rri variants, and, or, xor (only rrr), load immediate (reg = 16-bit value), load from address register indirect with auto increment/decrement (reg1 = [reg2], reg2 += immediate value), load from address immediate indirect (reg = [addr]), store register indirect with auto inc/dec, and store immediate indirect. Also, there's a 1-byte opcode that causes the next instruction to be executed conditionally based on status flags.alexfru wrote:There are other variations on the theme, but this is the very first thing one needs to consider when writing a code generator.
Looks like either you'll need a decent assembler for this CPU or you'll need to do some of its work in the code generator. For example, immediate operands that are shorter than 16 bits will need to be handled specially (or full-width operands w.r.t. to these short ones). The same applies to jumps/branches that use displacements of different widths. Short jumps are always painful to deal with. Not sure about "address" registers, if they are in any way special. On top of that, if the smallest memory operand is 16-bit, you'll have a bit of trouble implementing 8-bit chars and pointers to 8-bit chars, unless, of course, you abandon non-16-bit types altogether and make char=short=int=void*=void(*)()=16 bits=1 "C byte". Either way, if 8-bit chars aren't directly accessible, some serious work will be needed since the compiler is not designed to support such a platform (not that it can't be tweaked, of course, but it'll be many places, not one). Other than that it looks like you should be able to make a code generator similar to my MIPS CG relatively easily, but it'll likely be hard to make it generate more optimal code since only the load and store instructions can access data memory.jal wrote:Well, I can elaborate a bit. It's a fairly standard RISC with minimal instructions. ...
I've written an assembler, so if the C compiler outputs asm that's fine (and even desirable).alexfru wrote:Looks like either you'll need a decent assembler for this CPU
No, there are just general purpose registers.Not sure about "address" registers, if they are in any way special.
That's indeed something I'd have to solve. I could have 16-bit chars, like having wchars and have the Unicode thing solved at the same time :). But I appreciate that's a bit of a problem for the compiler to deal with.On top of that, if the smallest memory operand is 16-bit, you'll have a bit of trouble implementing 8-bit chars and pointers to 8-bit chars, unless, of course, you abandon non-16-bit types altogether and make char=short=int=void*=void(*)()=16 bits=1 "C byte".
True, though given that there are 14 general purpose registers, it's probably possible to reserve a few for dedicated constructions (e.g. for loading memory operands in add or sub).Other than that it looks like you should be able to make a code generator similar to my MIPS CG relatively easily, but it'll likely be hard to make it generate more optimal code since only the load and store instructions can access data memory.
Code: Select all
/*
How to compile for DOS (all mode(l)s: tiny/.COM, small/.EXE, huge/.EXE):
smlrcc -dost hw.c -o hwdt.com
smlrcc -doss hw.c -o hwds.exe
smlrcc -dosh hw.c -o hwdh.exe
*/
#include <stdio.h>
int main(void)
{
puts("Hello, World!");
return 0;
}