SICO

From Esolang
Jump to navigation Jump to search

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:


  1. If mem[A] = mem[B]
  2. If mem[A] = 0
  3. 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.