IOTA-C0

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 pointerDefault value: 0x8100
 
 
 0x8001
 NO
 Value becomes value|0x8000Default 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.
 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
 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.
 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
 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.
 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.
* The C0's GET and SET commands require a memory look-up, which cannot be reasonably done from the C-RAM of a physical processor. Therefore, those commands would have to be replaced or removed entirely. I don't know what to replace them with though.
* The C0 has no interactive IO. The C1 would add a few bytes of C-RAM for the purpose of communicating with external devices.
* The HLT command was put in before the LBL command was added. It doesn't provide any reasonable purpose now, and should be removed for the C1.
* The C0 is very limited on memory. The C1 could (though this is more questionable) provide a way to bank-swap sections of RAM. It is possible that the literals section could be used for this purpose, but I'm not so sure of the idea of losing access to literals in order to save more data.
Category:Languages
Category:2018
Category:Cell-based
Category:Turing complete
Category:Implemented