

Instruction encoding for misc operations:
	instruction group: bits 0 to 1 (2 bits) {NOTE: for misc operations, should be set to 0b00}
	opcode:            bits 2 to 7 (6 bits)
	imm:               bits 8 to 31 {NOTE: depending on the opcode, could be an address, or a register indirection}


Instruction encoding for register operations:
	instruction group: bits 0 to 1 (2 bits) {NOTE: for register operations, should be set to 0b01}
	opcode:            bits 2 to 8 (7 bits)
	dest:              bits 9 to 13 (5 bits)
	src1               bits 14 to 18 (5 bits)
	src2               bits 19 to 23 (5 bits)
	all other bits unused, however should be set to zero


Instruction encoding for load/store operations:
	instruction group: bits 0 to 1 (2 bits) {NOTE: for load/store operations, should be set to 0b10}
	opcode:            bits 2 to 5 (4 bits)
	register:          bits 6 to 10 (5 bits)
	imm:               bits 11 to 31 {NOTE: depending on the opcode, could be an address, or register indirect, or an immediate}
		is be one of:
			A) signed 21-bit offset from PC
			B) signed 21-bit offset from SP
			C) base register (5 bits) and a 16-bit signed offset from PC
			D) signed 21 bit immediate


The difference between 'arithmetic' and 'logical' shifts/rotates is that in arithmetic shifts/rotates
the sign bit is untouched, while logical shifts/rotates don't care about the sign bit.
Also, we only need arithmetic shift right because arithmetic shift left is typically the same as a logical shift left.
Another instruction we really don't 'need' is a rotate left instrction, because you can do the same thing with a rotate right
instruction, and rotate right instructions are more common than rotate left instructions.

opcodes for register operations (in order of opcode numbers):
	add; add src1 and src2 and store the result in dest.
	sub; subtract src1 and src2 and store the result in dest.
	mul; multiply src1 and src2 and store the result in dest.
	div; divide src1 and src2 and store the result in dest. If src1 or src2 is zero, dest is untouched and a exception is raised.
	mod; divide src1 and src2 and store the remainder in dest. If src1 or src2 is zero, dest is untouched and a exception is raised.
	
	shl; logically shift src1 left by src2 and store the result in dest.
	shr; logically shift src1 right by src2 and store the result in dest.
	ahr; arithmetic shift src1 right by src2 and store the result in dest.
	ror; logically rotate src1 right by src2 and store the result in dest.

	and; AND src1 by src2 and store the result in dest.
	or;  OR src1 by src2 and store the result in dest.
	xor; XOR src1 by src2 and store the result in dest.
	not; NOT src1 and store the result in dest, ignore src2.
	
	
	
	xchg; exchange src1 and src2, ingore dest.

opcodes for load/store operations: (in order of opcode numbers)
	ldr; load register from value at PC + imm
	lds; load register from value at SP + imm
	ldb; load register from value base_reg + imm
	ldi; load low 21 bits of register with value imm
	
	str; store register at address PC + imm
	sts; store register at address SP + imm
	stb; store register at address base_reg + imm
	ldh; load high 11 bits of register with value imm
	
	sti; store immediate at address PC + register
	stj; store immediate at address SP + register
