SICO

SICO is a Single Instruction COmputer. Originally named Unileq, it is an unsigned version of Subleq. Instead of jumping if A-B<=0, SICO jumps if A-B generates a borrow or zero.
==Overview==
A basic SICO instruction looks like this when implemented in Python:
 A = mem[IP+0]
 B = mem[IP+1]
 C = mem[IP+2]
 IP += 3
 if mem[A] <= mem[B]: IP = C
 mem[A] -= mem[B]
Interaction with the host environment is done by writing to special addresses. For instance: if A=-1, the program will terminate. If A=-2, then mem[B] will be printed to the console.
==Assembly==
The assembly language is fairly simple:
Name 	Function
label: 	Defines a label
.sublabel: 	Defines a sublabel
? 	The current address
# 	Single line comment
#| ... |#	Block comment
==Functions==
Functions can easily be implemented with no need for assembler macros like in other OISC's. We can call a function by executing a SICO instruction that places the current IP in address 0, and then jumps to the function. For instance:
 0 ? uint.add A B C
This can be broken down into two components:
 0 ? uint.add # calling instruction
 A B C # parameters for the function
The function uint.add will use the value in address 0 to determine where it was called from. It will then load A, B, and C, perform [A]=[B]+[C], and then jump back to the address after C to resume program flow.
For completeness, this is what the uint.add function is in SICO assembly:
 uint.add:
 	# Call : 0 ? uint.add ret a b
 	#
 	# Effect: [ret] = [a] + [b]
 	#
 	# Time : 30
 	#
 	# Use [0] to get the calling address.
 	.tmp .tmp ?+1
 	.tmp .arg2 ?+1
 	0 .tmp ?+1
 	0 .off ?+1
 	.arg2 0 ?+1
 	.arg3 0 ?+1
 	.arg4 0 ?+1
 	.arg5 0 ?+1
 	# Get [ret]
 	.ret0 .arg2:2 ?+1
 	.ret1 .ret0 ?+1
 	.ret2 .ret0 ?+1
 	.tmp .tmp ?+1
 	.tmp .ret1 ?+1
 	.ret0 .ret0 ?+1
 	.ret0 .tmp ?+1
 	# Get [a]
 	.tmp .tmp ?+1
 	.tmp .arg3:3 ?+1
 	.a0 .a0 ?+1
 	.a0 .tmp ?+1
 	# Get [b]
 	.tmp .tmp ?+1
 	.tmp .arg4:4 ?+1
 	.b0 .b0 ?+1
 	.b0 .tmp ?+1
 	# Set [ret]
 	.tmp .tmp ?+1
 	.tmp .a0:0 ?+1
 	.tmp .b0:0 ?+1
 	.ret0:0 .ret1:0 ?+1
 	.ret2:0 .tmp ?+1
 	# Return
 	0 0 .arg5:5
 	# Variables
 	.off:2
 	.tmp:0
==Performance==
Using the function calling notation above, several libraries have been created for SICO (here) which implement most common programming functions.
Time complexities for some of the functions are given below. Time is measured in number of instructions needed when using 64-bit underlying integers.
Function 	Time
uint.write	2303
uint.read 	1456
uint.cmp 	29
uint.min 	34
uint.max 	34
uint.set 	24
uint.neg 	25
uint.add 	30
uint.sub 	31
uint.mul 	885
uint.div 	613
uint.gcd 	1330
uint.shl 	168
uint.shr 	543
uint.not 	26
uint.and 	485
uint.or 	486
uint.xor 	487
==Comparisons vs Subleq==
The two major differences between SICO and Subleq are the signedness of the values and the order of the operands.
For the values A B C, Subleq would perform mem[B] -= mem[A], while SICO will perform mem[A] -= mem[B].
SICO also guarantees 3 conditions in which an instruction will jump:
# If mem[A] = mem[B]
# If mem[A] = 0
# If mem[B] = -1
While Subleq only guarantees a jump if mem[A] = mem[B]. These extra conditions have helped SICO when optimizing mathematical functions.
==See also==
Subleq
==External resources==
SICO - An online interpreter for SICO.
Category:Languages
Category:Cell-based
Category:Turing complete
Category:Implemented
Category:Low-level
Category:Self-modifying
Category:OISC