Magic-16 ISA
Home ] Up ] New Stuff ] Minix Port ] Overview ] Photo Gallery ] Construction ] Technical Info ] My Other Projects ] Links ]

 

Magic-16

Here's the current definition and encoding of Magic-16's instruction set architecture.  Some notes:

bulletThere are 8 16-bit general registers and at least one control register
bulletGeneral register 0 is hardwired to always return a 0
bulletGeneral register 7 is hardwired as the program counter.
bulletGeneral register 2 is by convention the link register
bulletGeneral register 6 is by convention the stack pointer
bulletControl register 0 will contain the carry bit, mode bit, interrupt enable, etc.
bulletOther than the carry bit, Magic-16 arithmetic operations are stateless (i.e. no Z bit, V bit, etc)
bulletThe skip instruction will nullify execution of the following instruction if (op1 <cond> op2) is true.
bulletSkip conditions are encoded as follows.  Note that unsigned greater than and unsigned greater than or equal are missing.  The compiler will be responsible for swapping operands in these cases and using the corresponding unsigned less/less equal conditions.
bullet000 -> equal
bullet001 -> not equal
bullet010 -> signed less than
bullet011-> signed less than or equal
bullet100 -> signed greater than
bullet101 -> signed greater than or equal
bullet110 -> unsigned less than
bullet111 -> unsigned less than or equal
bulletThe addskip instruction will add op1 to op2 and store the result in res.  Additionally, if the result condition is met, the following instruction will be nullified.  The allowed result conditions are result zero (0) and result non-zero (1).
bulletFields marked "I/R" denote that operand 1 is either a register or an encoded 3-bit immediate.  The immediate encoding is:
bullet000 -> 1
bullet001 -> 2
bullet010 -> 4
bullet011 -> 8
bullet100 -> -8
bullet101 -> -4
bullet110 -> -2
bullet111 -> -1
bulletInstructions marked with "*" may only be executed at the highest privilge level
bulletLoading a 16-bit immediate involves a two-instruction sequence: ldi to load the low 9 bits, and addih to add in the high 7 bits.  Note the 1-bit overlap, which assembler macros will handle properly.
bulletConditional branching will be accomplished by placing the unconditional branch instruction in the shadow of either a skip or addskip instruction.
bulletDoing a procedure call requires explicit setting of the link register prior to branching.  This was done to avoid requiring two write ports on the register file (though I may figure out how to set the link without penalty during implementation).  For example, to call "foo
bulletadd    4,pc,link    ; materialize return address
bulletbr        foo           ; branch to foo
bulletMost arithmetic operations are three address, but for some of the more uncommon ones (addc, subc, xor, etc.) I'm limiting support to two address.  This is a little unclean, but I decided that they weren't worth the opcode space. 
bulletI haven't yet defined the memory management instructions, paging & segmentation support, return from interrupt and supported traps.  I'll likely do something similar to Magic-1 there.
bulletI've left plenty of room in the encoding for adding new instructions.  Should be lots of room to play.

Overall, I'm quite pleased with the encoding.  As you can see, I've dedicated the opcode space to correspond to the expected frequency of instruction execution.  Ideally, I'd have a bit more displacement space for the loads and stores, but I'm pretty happy with the balance here.

Opcode group 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
ldw sw7(base),tgt 0 0 0 signed 7-bit word offset base tgt
ldb sb7(base),tgt 0 0 1 signed 7-bit byte offset base tgt
stw src,sw7(base) 0 1 0 signed 7-bit word offset base src
stb src,sw7(base) 0 1 1 signed 7-bit byte offset base src
br <label> 1 0 0 signed 13-bit pc relative offset
ldi s10,tgt 1 0 1 signed 10-bit immediate tgt
add op1,op2,res 1 1 0 0 0 0 I/R op1 op2 res
sub op1,op2,res 1 1 0 0 0 1 I/R op1 op2 res
and op1,op2,res 1 1 0 0 1 0 I/R op1 op2 res
or op2,op2,res 1 1 0 0 1 1 I/R op1 op2 res
skip.c op1,op2 1 1 0 1 0 0 I/R op1 op2 condition
addskp.z op1,op2,res 1 1 0 1 0 1 I/R op1 op2 res
ldw (base,idx),tgt 1 1 0 1 1 0 0 idx base tgt
ldb (base,idx),tgt 1 1 0 1 1 0 1 idx base tgt
stw src,(base,idx) 1 1 0 1 1 1 0 idx base src
stb src,(base,idx) 1 1 0 1 1 1 1 idx base src
shl cnt,src,res 1 1 1 0 0 0 shift count src res
shr cnt,src,res 1 1 1 0 0 1 shift count src res
addih u7,res 1 1 1 0 1 0 7-bit imm (<< 9 & add) res
addc src,tgt 1 1 1 0 1 1 0 0 0 0 src res
subb src,tgt 1 1 1 0 1 1 0 0 0 1 src res
xor src,tgt 1 1 1 0 1 1 0 0 1 0 src res
addto src,tgt 1 1 1 0 1 1 0 0 1 1 src res
subto src,tgt 1 1 1 0 1 1 0 1 0 0 src res
[reserved 2-operand] 1 1 1 0 1 1 0 1 0 1 src res
[reserved 2-operand] 1 1 1 0 1 1 0 1 1 0 src res
bv (tgt) 1 1 1 0 1 1 0 1 1 1 0 0 0 tgt
sext res 1 1 1 0 1 1 0 1 1 1 0 0 1 tgt
[reserved 1-operand] 1 1 1 0 1 1 0 1 1 1 0 1 0 tgt
[reserved 1-operand] 1 1 1 0 1 1 0 1 1 1 0 1 1 tgt
[reserved 0-operand] 1 1 1 0 1 1 0 1 1 1 1 X
copy cr,tgt (*) 1 1 1 0 1 1 1 0 0 0 cr tgt
copy src,cr (*) 1 1 1 0 1 1 1 0 0 1 cr src
[reserved (*)] 1 1 1 0 1 1 1 0 1 X
[reserved (*)] 1 1 1 0 1 1 1 1 X
addskp.nz op1,op2,res 1 1 1 1 0 0 I/R op1 op2 res
sh1add op1,op2,res 1 1 1 1 0 1 I/R op1 op2 res
sh2add op1,op2,res 1 1 1 1 1 0 I/R op1 op2 res
sh3add op1,op2,res 1 1 1 1 1 1 I/R op1 op2 res