



Introduction

IOTA-C0 is a processor specification created by User:Enoua5 in 2018. It was meant to work entirely off of computational RAM, its only native instruction being to copy the value in one memory address into another memory address. There were a few decisions in the creation of this specification that would make the IOTA-C0 very impractical to build, though it does make the programming a little easier.

Processor Documentation

Memory

Basics

RAM: 65536 16-bit addresses, from 0x0000 to 0xFFFF

Registers: 2 16-bit registers for holding data read from RAM

Layout of RAM

Section name Start address End address Read only? Description Default value Literals 0x0000 0x7FFF YES Because the IOTA-C0 can only work with pointers, these memory addresses hold literals, so that programs can actually use literals. Their address in memory Computation RAM 0x8000 0x807F See Computational RAM Stack A 0x8080 0x80BF YES Values are filled from low end to high end. If all 64 are filled and a value is pushed, nothing happens If there are no values in the stack when a value is popped, returns 0x0000 and makes no change 0 Stack B 0x80C0 0x80FF YES Values are filled from low end to high end. If all 64 are filled and a value is pushed, nothing happens If there are no values in the stack when a value is popped, returns 0x0000 and makes no change 0 Standard RAM 0x8100 0xFFFF NO Low end reserved for program; all rest is for the program's variables 0

Clock Cycle

The following procedure is run every clock cycle

Copy the value in memory address 0x8000 into register 0 Copy the value in the memory address pointed to by the value in register 0 into register 0 Increment the value in memory address 0x8000 Copy the value in memory address 0x8000 into register 1 Copy the value in the memory address pointed to by the value in register 1 into register 1 Increment the value in memory address 0x8000 Copy the value in the memory address pointed to by the value in register 1 into the memory address pointed to by the value in register 0

Or, in less verbose terms:

R[0]=M[0x8000] R[0]=M[R[0]] M[0x8000]++ R[1]=M[0x8000] R[1]=M[R[1]] M[0x8000]++ M[R[0]]=M[R[1]]

Computational RAM

Computation RAM is how the IOTA-C0 performs all its computation. The values in this area (0x8000-0x807F) change between clock cycles based on nearby values, following the rules detailed in the table below.

A hex number is a literal.

A hex number in brackets is a value pointed to by the number. (a pointer)

A hex number in double brackets is a value pointed to by the number at the address pointed to by the number. (a pointer pointer)

Address Read only? Operation 0x8000 NO Instruction pointer

Default value: 0x8100 0x8001 NO Value becomes value|0x8000

Default value: 0x807F 0x8002 NO The value here gets written to [[0x8001]] 0x8003 NO Normal slot 0x8004 NO Value becomes value|0x8000 0x8005 NO Value becomes value|0x8000 0x8006 YES Value becomes [0x8004] if [0x8003] is not 0x0000;

Value becomes [0x8005] id [0x8003] is 0x0000 0x8007 NO Normal slot 0x8008 NO Normal slot 0x8009 NO Normal slot 0x800A YES Value becomes [0x8008] if [0x8007] is not 0x0000;

Value becomes [0x8009] id [0x8007] is 0x0000 0x800B NO Normal slot 0x800C NO Normal slot 0x800D YES Value becomes [0x800B]&[0x800C] 0x800E NO Normal slot 0x800F NO Normal slot 0x8010 YES Value becomes [0x800E]|[0x800F] 0x8011 NO Normal slot 0x8012 NO Normal slot 0x8013 YES Value becomes [0x8011]XOR[0x8012] 0x8014 NO Normal slot 0x8015 YES Value becomes ~[0x8014] 0x8016 NO Normal slot 0x8017 NO Normal slot 0x8018 YES Value becomes 0xFFFF if [0x8016]<[0x8017];

Value becomes 0x0000 otherwise 0x8019 NO Normal slot 0x801A NO Normal slot 0x801B YES Value becomes 0xFFFF if [0x8019]<=[0x801A];

Value becomes 0x0000 otherwise 0x801C NO Normal slot 0x801D NO Normal slot 0x801E YES Value becomes 0xFFFF if [0x801C]>[0x801D];

Value becomes 0x0000 otherwise 0x801F NO Normal slot 0x8020 NO Normal slot 0x8021 YES Value becomes 0xFFFF if [0x801F]>=[0x8020];

Value becomes 0x0000 otherwise 0x8022 NO Normal slot 0x8023 NO Normal slot 0x8024 YES Value becomes 0xFFFF if [0x8022]==[0x8023];

Value becomes 0x0000 otherwise 0x8025 NO Normal slot 0x8026 NO Normal slot 0x8027 YES Value becomes 0xFFFF if [0x8025]!=[0x8026];

Value becomes 0x0000 otherwise 0x8028 NO Normal slot 0x8029 NO Normal slot 0x802A YES Value becomes [0x8028]>>>[0x8029] 0x802B NO Normal slot 0x802C NO Normal slot 0x802D YES Value becomes [0x802B]>>[0x802C] 0x802E NO Normal slot 0x802F NO Normal slot 0x8030 YES Value becomes [0x802E]<<[0x802F] 0x8031 NO Normal slot 0x8032 NO Normal slot 0x8033 YES Value becomes [0x8031]+[0x8032] 0x8034 NO Normal slot 0x8035 NO Normal slot 0x8036 YES Value becomes [0x8034]-[0x8035] 0x8037 NO Normal slot 0x8038 NO Normal slot 0x8039 YES Value becomes [0x8037]*[0x8038] 0x803A NO Normal slot 0x803B NO Normal slot 0x803C YES Value becomes [0x803A]/[0x803B]

Division by 0 results in 0 0x803D NO Normal slot 0x803E NO Normal slot 0x803F YES Value becomes [0x803D]%[0x803E]

Division by 0 results in 0 0x8040 NO Normal slot 0x8041 YES Value becomes [0x8040]+1 0x8042 NO Normal slot 0x8043 YES Value becomes [0x8042]-1 0x8044 NO Normal slot 0x8045 YES Value becomes [0x8044]*-1 0x8046 NO Value becomes value|0x8000 0x8047 NO Normal slot 0x8048 YES If a non-zero value is attempted to be moved here,

[0x8047] is pushed to stack A 0x8049 NO Normal slot 0x804A YES If a non-zero value is attempted to be moved here,

[0x8049] becomes the value popped off stack A 0x804B NO Normal slot 0x804C YES If a non-zero value is attempted to be moved here,

[0x804B]|0x8000 is pushed to stack B 0x804D NO Normal slot 0x804E YES If a non-zero value is attempted to be moved here,

[0x804D] becomes the value popped off stack B 0x804F YES Returns a random value when read 0x8050 YES Normal slot 0x8051 YES Value becomes the value in [[0x8050]] 0x8052-0x807E YES Unassigned 0x807F YES If a non-zero value is attempted to be moved here, all writable memory is set to 0

Assembly Documentation

Preprocessor

A preprocessot instruction begins with a . character on its own line. The dot is followed by the command, then arguments seperated by spaces.

Commands

Command Arguments Description Technical .const name value Creates a constant that can be called by prepending : to the front of the name. name follows C variable naming rules.

follows C variable naming rules. Will replace all instances of :name with value . .var name Declares a varible that can be called by prepending : to the front of the name. Compiles into a .const declaration

The first .var will be given a value of 0xFFFF when compiled into a .const

of 0xFFFF when compiled into a .const Each successive .var will be given a value one less than the last. .var name[number] Declares an array that can be called by prepending : to the front of the name and appending an index in brackets. Compiles into .var declarations and a .const declaration

number is a positive integer in base 10.

is a positive integer in base 10. Compiles into number .var declarations, with names from name[0] to name[number-1] , and a .const declaration with a value 0x8000 less than name[0]

Preprocessor Example

If we start with the following code;

.var variable

.var array[3]

.const constant1 10

.const constant2 42

ADD :constant1 :constant2 :array[1]

ADD :array[1] :array :variable

First, vars will be compiled into consts to get this;

.const variable 0xFFFF

.const array[2] 0xFFFE

.const array[1] 0xFFFD

.const array[0] 0xFFFC

.const array 0x7FFC

.const constant1 10

.const constant2 42

ADD :constant1 :constant2 :array[1]

ADD :array[1] :array :variable

Then, the consts will be pasted into the code to get this;

ADD 10 42 0xFFFF

ADD 0xFFFE 0x7FFC 0xFFFF

Assembly

One command per line

# denotes a comment

denotes a comment Any amount of whitespace can go before or after a command

One of more white space characters (excluding new line) can go between arguments

Arguments can be any dec, hex, octal, or binary number from 0x000-0xFFFF

dec is written as just a number (eg 42)

hex is written as 0x and a number (eg 0x2A)

octal is written as 0 and a number (eg 052)

binary is written as a 0b and a number (eg 0b101010)

* can be put before a number to to work as an address (eg *0x10 becomes 0x8010 when compiled)

In this table:

An argument prepended with : will default to being prepended with * , even if this is not put there in the program. This cannot be turned off.

will default to being prepended with , even if this is not put there in the program. This cannot be turned off. An argument in brackets means that it is optional. A section of compilation in brackets means that it will only be present if the optional argument is present

Command Arguments Mnemonic Description Compiles into NOP None No Operation Does nothing 0000 0000 MOV :N M Move Copy M into address N NNNN MMMM JMP N Jump Jump execution to address N 8046 NNNN 8000 8046 QJP :N Quick Jump (Can't take literals) Jump execution to the address in address N 8000 NNNN SET N M Set Set the value in memory address N to M 8001 NNNN 8002 MMMM STA N Set Address Like SET, but without changing the value currently being used 8001 NNNN STV N Set Value Like SET, but without changing the address currently being used 8002 NNNN TNA N M L [:K] Ternary Address If N is nonzero, set the value in memory address K to :M; else set it to :L 8003 NNNN 8004 MMMM 8005 LLLL [KKKK 8006] TRN N M L [:K] Ternary If N is nonzero, set the value in memory address K to M; else set it to L 8007 NNNN 8008 MMMM 8009 LLLL [KKKK 800A] AND N M [:L] And Write the result of the bitwise-and operation between N and M to memory address L 800B NNNN 800C MMMM [LLLL 800D] ORR N M [:L] Or Write the result of the bitwise-or operation between N and M to memory address L 800E NNNN 800F MMMM [LLLL 8010] XOR N M [:L] Exclusive Or Write the result of the bitwise-xor operation between N and M to memory address L 8011 NNNN 8012 MMMM [LLLL 8013] NOT N [:M] Not Write the result of the bitwise-not operation of N to memory address M 8014 NNNN [MMMM 8015] LST N M [:L] Less Than If M is less than M, set the value in memory address L to 0xFFFF; else set it to 0 8016 NNNN 8017 MMMM [LLLL 8018] LOE N M [:L] Less Than or Equal If M is less than or equal to M, set the value in memory address L to 0xFFFF; else set it to 0 8019 NNNN 801A MMMM [LLLL 801B] GRT N M [:L] Greater Than If M is greater than M, set the value in memory address L to 0xFFFF; else set it to 0 801C NNNN 801D MMMM [LLLL 801E] GOE N M [:L] Greater Than or Equal If M is greater than or equal to M, set the value in memory address L to 0xFFFF; else set it to 0 801F NNNN 8020 MMMM [LLLL 8021] EQU N M [:L] Equal If M is equal to M, set the value in memory address L to 0xFFFF; else set it to 0 8022 NNNN 8023 MMMM [LLLL 8024] NEQ N M [:L] Not Equal If M is not equal to M, set the value in memory address L to 0xFFFF; else set it to 0 8025 NNNN 8026 MMMM [LLLL 8027] SHR N M [:L] Shift Right Shifts N right by M bits and saves the value in memory address L 8028 NNNN 8029 MMMM [LLLL 802A] ASR N M [:L] Arithmatic Shift Right Shifts N right by M bits arithmatically and saves the value in memory address L 802B NNNN 802C MMMM [LLLL 802D] SHL N M [:L] Shift Left Shifts N left by M bits and saves the value in memory address L 802E NNNN 802F MMMM [LLLL 8030] ADD N M [:L] Add Add N and M, saving the result in memory address L 8031 NNNN 8032 MMMM [LLLL 8033] SUB N M [:L] Subtract Subtract M form N, saving the result in memory address L 8034 NNNN 8035 MMMM [LLLL 8036] MUL N M [:L] Multiply Multiply N by M, saving the result in memory address L 8037 NNNN 8038 MMMM [LLLL 8039] DIV N M [:L] Divide Divide N by M, saving the result in memory address L. Division by zero results in a 0. 803A NNNN 803B MMMM [LLLL 803C] MOD N M [:L] Modulo Divide N by M, saving the remainder of result in memory address L. Modulo by zero results in a 0. 803D NNNN 803E MMMM [LLLL 803F] INC N [:M] Increment Add 1 to N, saving the result in memory address M 8040 NNNN [MMMM 8041] DEC N [:M] Decrement Subtract 1 from N, saving the result in memory address M 8042 NNNN [MMMM 8043] NEG N [:M] Negative Multiply N by -1 (i.e. 0xFFFF), saving the result in memory address M 8044 NNNN [MMMM 8045] ADR N [:M] Address Use bitwise-or with N and 0x8000 (i.e. make a litteral into an pointer), saving the result in memory address M 8046 NNNN [MMMM 8046] PSH N Push Push the value N onto stack A 8047 NNNN 8048 0001 POP [:N] Pop Pop a value off of stack A and save it in memory address N 804A 0001 [NNNN 8049] PSA N Push Address Use bitwise-or with N and 0x8000 (i.e. make a litteral into an pointer), and push the result onto stack B (the call-stack) 804B NNNN 804C 0001 POA [:N] Pop Address Pop a value off of stack B (the call-stack), and the it in memory address N 804E 0001 [NNNN 804D] RND :N Random Get a random number and save it in memory address N NNNN 804F GET :N [:M] Get Copy the value pointed to by the value in memory address N and copy it into memory address M 8050 NNNN [MMMM 8051] LBL :N Label Save the address of the next command in memory address N NNNN 8000 CAL N Call Jump execution to memory address N, pushing the memory address of the next command onto stack B (the call-stack) 8031 0008 8032 8000 804B 8033 804C 0001 8046 NNNN 8000 8046 RET None Return Pop a pointer off stack B (the call-stack) and jump exectuation to it. 804E 0001 8000 804D HLT None Halt Set all writable RAM to 0, stopping execution. 807F 0001

Postprocessor

A postprocessor instruction begins with a . character on its own line.

All postprocessor instructions and targets are ignored by the assembler.

Command Arguments Description Technical .lbl name Will create a label which can be jumped to by the JMP command. Will replace all instances of &name with the address of the next instruction in memory

Example Programs

Fill

Fills the memory with 0x0F0F

#uses only draft 1 SET 0x0200 0x0F0F ADR 0x0108 MOV 0x01FF *0x0046 INC *0x0001 0x0001 QJP 0x01FF

Fibonacci

Calculates the Fibonacci sequence

#uses only draft 2, which added more instructions #initial state MOV 0x200 1 MOV 0x201 1 #locations of the most recent numbers ADR 0x200 0x1FE ADR 0x201 0x1FF #location of the next number STA 0x202 #start the loop LBL 0x1FB #add the two numbers together GET 0x1FE 0x1FC GET 0x1FF 0x1FD ADD *0x1FC *0x1FD #write the sum to the referenced address STV *0x33 #increment the pointers INC *0x1FE 0x1FE INC *0x1FF 0x1FF #the address of DFA INC *0x1 0x1 #jump to the start of the loop QJP 0x1FB

Factorial

Calculates the factorials for the numbers 1 through 8

#uses draft 3, which added pre and post processor JMP &start_program .var results[8] .var n .var tot .lbl fact #init factorial MOV :tot 1 #start the body of the function .lbl fact_body #check if n is at or below 1 .var fact_reached_1 LOE :n 1 :fact_reached_1 #if it is, exit the function .var fact_jump_loc TNA :fact_reached_1 &fact_ret &fact_mult :fact_jump_loc QJP :fact_jump_loc #otherwise, tot=tot*(n--) .lbl fact_mult MUL :n :tot :tot DEC :n :n #recursion! CAL &fact_body #the exit .lbl fact_ret RET .lbl start_program #for i=1 .var i MOV :i 1 .var for_loop LBL :for_loop #i<=8 .var end_of_array LOE :i 8 :end_of_array .var for_jump TNA :end_of_array &continue_for &exit_for :for_jump QJP :for_jump .lbl continue_for #get i factorial into tot MOV :n :i CAL &fact #put it into results .var addr ADD :results :i :addr DEC :addr :addr ADR :addr :addr SET :addr :tot #i++ INC :i :i QJP :for_loop .lbl exit_for .lbl exit_program JMP &exit_program

The Future

I am considering creating another similar processor specification, the IOTA-C1. If I decide to go with it, the C1 would improve upon many of the C0's shortcomings.