Skip to content

Repository files navigation

emex64

Chip MarkingCase Sticker
Chip MarkingCase Sticker

Introduction

emex64 is a 64bit lightweight little endian architecture. It's a mix out of RISC and CISC it is based on no previous architecture, except the ones @mach-port-t(me) created in the past, emex64 evolved from this path LA8 -> LA816 -> LA16 -> LA32/LA64 -> emex64. emex64 is a much better version of LA64. LA stands for LightweightArchitecture, it is the original ISA, the idea of the ISA is to not hold baggage from decades ago and not bend for the industry giving the best result currently possible to the consumer.

Outside the SoC, the emulated board additionally integrates support for UART, (Re-Implementation pending (a vibecoder contributed audio before and was cought vibecoding which resulted in his code being removed)) Audio, and (implementation pending) Graphics.

Besides that there is a proper polymorphic toolchain called EmexToolchain which can be used to assemble, link and execute emex64 code all in the same process with proper memory management lavering EmexFoundation. The assembler spits out ELF relocatable objects, which the linker can either link all of them together to a firmware image which is something like emex64's BIOS or to a merged ELF relocatable object. ELF is the only thing that I didn't do from scratch, I originally wanted to use the LO(LightweightObject) format made by me, but thought then that this will be nightmares to implement.

Setup and Installation of the emex64 toolchain

Bulding the toolchain and installing it is as simple as the following:

make full

This will install emex64's toolchain and VM to /usr/local, and will prompt for a superuser password to do so.

emex64vm will additionally require GLFW/GLEW if using the virtual display.

If you wanna test it quickly you can run this.

make full CMAKE_FLAGS="-DEMEX64_BUILD_EXAMPLES=1"&& emex64hello

emex64hello is a example of a utility entirely in memory assembling and linking a hello world test firmware and executing it with the virtual machine.

Using the Virtual Machine (VM)

The VM can be invoked to run firmware with emex64vm -f <image path>. Test programs and the current testing firmware can be found in ./tests/.

These examples will be compiled and directly run with make.

Instruction Set Architecture (ISA)

The instruction coding is variable, it is not a fixed lenght instruction set, which is a CISC concept. Instructions are coded by the first 8 bit serving as the opcode, followed by operands that are not aligned to a byte boundary. Operands are coded by the first 4 bit serving as the type of operand followed by the operand it self, except it is a offset coding, that means that 2 more operands will follow where the first one is the main operand and the 2nd one is the operand responsible for the offset. A table of the operand types here:

TypeBinaryDescription
End0b0000Terminates the instruction, parser stops parsing
Register0b00014 bit register identifier
Immediate (4bit)0b00104 bit immediate
Immediate (8bit)0b00118 bit immediate
Immediate (16bit)0b010016 bit immediate
Immediate (32bit)0b010132 bit immediate
Immediate (64bit)0b011064 bit immediate
Address (64bit)0b011164 bit immediate, with the difference that the decoder aligns to the next byte boundary, this was done with the intention for easy address relocation in the linker, it payed off >:3.
Register Extended0b10004 bit register identifier to the 2nd register file
Register Increment0b10014 bit register identifier, but decoder increments register after parse
Register Decrement0b10104 bit register identifier, but decoder decrements register after parse
Offset Add0b1011Offset Addition
Offset Subtract0b1100Offset Subtraction

In case it is a immediate it stores the immediate into a immediate cache of the core which then gets used as a operand inside of the operation logic. Offsetted operands are always in the immediate cache.

Register Set (RS)

Main Register File

Each of these registers are accessible in userspace aswell as in kernelspace. These registers also support the operand codings like "Register Increment" and "Register Decrement."

RegisterNameBinaryDescription
pcProgram Counter0b0000Points to the current address at which the CPU currently is, it increments by the lenght of the instruction when the CPU is done executing the instruction at which PC points to at that time.
spStack Pointer0b0001Points to the current address at which the stack lives, the stack grows downwards on allocation and upwards on deallocation.
fpFrame Pointer0b0010Points to the address at which the stack frame of the last function call lives, basically empowering you to branch and link and return back without destroying values stored in registers previously.
cfControl Flag0b0011Used by control flow operations like cmp, be and bne. Basically used for if else kind of statements.
fpcFloating PointControl0b0100Controls the behaviour of the implementation pending floating point registers.
r0 - r9General Purpose Registers0b0101 - 0b1110Use it for what ever.
rrReturn Register0b1111Unaffected by operations like blw and wret. Intended to be used as a return value register.

Extended Register File

As only 10 general purpose registers is not much we created a extended register file, but the cavet is that it doesn't support direct decode level manipulation like increment and decrementing in place.

RegisterNameBinaryDescription
er0 - er15Extended General Purpose Registers0b0000 - 0b1111Use it for what ever.

Control Register File

RegisterNameBinaryDescription
crelControl Register Eleveation Level0b0000Controls the elevation of the core, the higher the value the more priveleged the core is.
crkspControl Register Kernel Stack Pointer0b0001Stores the address of the stack base used when the interrupt controller interrupts the core.
crexcControl Register Exception0b0010Stores exception information.
crvecControl Register Vector0b0011No-Op
crptbControl Pegister Page Table Base0b0100Is treated by the MMU as the 5th level page table entry.
crfpcControl Register Floating Point Control0b0101No-Op
crisaControl Register ISA0b0110Used to get the ISA version and select older ISA version on-demand if firmware or kernel was intended for running on older ISA.

Opcode Set

(1) Applies mathematical operation either on two or one operand together and stores the result into the source, the source must always be a register and can also be a operand.

(2) Variadic instruction, meaning it can be used to apply the same operation onto many registers at the same time.

Core

OpcodeBinaryDescription
hlt0b00000000Halts the CPU core until the next interrupt occurs from a timer or other device.
nop0b00000001Does nothing, does a cycle.

Data

OpcodeBinaryDescription
mov0b00000010Moves a immediate or a value of a register into a register.
swp0b00000011Swaps the values of two registers.
movz0b00000100Moves the values of two registers, while zeroing out the source.
push0b00000101Pushes a immediate or a value of a register onto the stack. *(2)
pop0b00000110Pops a immediate from the stack into a register. *(2)
ldb0b00000111Loads a byte from a memory address into a register.
ldw0b00001000Loads a word from a memory address into a register.
ldd0b00001001Loads a double word from a memory address into a register.
ldq0b00001010Loads a quad word form a memory address into a register.
stb0b00001011Stores a byte from a register into a memory address.
stw0b00001100Stores a word from a register into a memory address.
std0b00001101Stores a double word from a register into a memory address.
stq0b00001110Stores a quad word from a register into a memory address.

ALU

OpcodeBinaryDescription
add0b00001111Addition. *(1)
sub0b00010000Subtraction. *(1)
mul0b00010001Multiplication. *(1)
div0b00010010Division. *(1)
idiv0b00010011Signed Division. *(1)
mod0b00010100Mudolu. *(1)
not0b00010101Applies a bitwise NOT gate onto the operands. *(2)
neg0b00010110Applies arithmetic negation onto the operands. *(2)
and0b00010111AND gate *(1)
or0b00011000OR gate *(1)
xor0b00011001XOR gate *(1)
shr0b00011010Shifts bits to the right. *(1)
shl0b00011011Shifts bits to the left. *(1)
sar0b00011100Shifts bits to the right arithmetically. *(1)
ror0b00011101Rolls bits to the right. *(1)
rol0b00011110Rolls bits to the left. *(1)
pdep0b00011111Extracts non-contiguous bits from a source operand based on a mask pattern.
pext0b00100000Does the reverse of pext. Spreads contiguous bits into non-contiguous positions.
bswapw0b00100001Reverses the byte order of a word.
bswapd0b00100010Reverses the byte order of a double word.
bswapq0b00100011Reverses the byte order of a quad word.
inc0b00100100Increments operands. *(2)
dec0b00100101Decrements operands. *(2)

Control flow

OpcodeBinaryDescription
b0b00100110Branches to a address by setting the PC register.
cmp0b00100111Compares two operands and sets the cf register.
be0b00101000Branches when the cf register says that the compared operands compared using cmp were equal.
bne0b00101001Branches when the cf register says that the compared operands compared using cmp were not equal.
blt0b00101010Branches when the cf register says that the first compared operand of the operands compared using cmp was less than the second operand.
bgt0b00101011Branches when the cf register says that the first compared operand of the operands compared using cmp was greater than the second operand.
ble0b00101100Branches when the cf register says that the first compared operand of the operands compared using cmp was less or equal to the second operand.
bge0b00101101Branches when the cf register says that the first compared operand of the operands compared using cmp was greater or equal to the second operand.
bz0b00101110Branches when the first operand is zero.
bnz0b00101111Branches when the first operand is not zero.
blw0b00110000Branches and links wastefully to a address by pushing all registers usable in the userspace to the stack. Linkage is done by storing the last stack pointer address to the stack frame in the fp register.
wret0b00110001Wastefully returns to the address it branched from when blw was used to branch by restoring all previously pushed registers.
iret0b00110010Returns from a interrupt handler by restoring all registers backedup by the interrupt controller onto the stack located at the kernel stack pointer.
bl0b00110011branches and links by only storing the last sp address into the fp register.
ret0b00110100Returns from a bl branch.

Data (v2)

OpcodeBinaryDescription
clr0b00110101Clears operands. *(2)
cmov0b00110110Moves a value of a register or immediate into a control register of the core.
cmovb0b00110111Moves a value from a control register into a register.
clar0b00111000Clears all registers in the normal and the extended register file.
bbz0b00111001Tests for a bit and if set it branches.
bbnz0b00111010Tests for a bit and if not set it branches.
rdrnd0b00111011Sets operand to a random number by entropy.

About

lightweight 64bit architecture

Resources

Stars

41 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages