I have been taking a course called nand2tetris. In it, we build a 16-bit computer, and in each instruction, the first bit chooses address mode or command mode, i.e., if it's 0, then we load the address register, if it's 1, we execute an instruction. The last 3 bits specify the jump condition (based on ALU output) like so:
000 - no jump
001 - jump if greater than 0
010 - jump if equal to 0
011 - jump if greater than or equal to 0
100 - jump if less than 0
101 - jump if not equal to 0
110 - jump if less than or equal to 0
111 - jump
Suppose I'm making an 8-bit computer, and I only have 1 bit to specify the jump instruction. If it's 0, don't jump, if it's 1, then jump if ALU output is 0. How will I do the other comparisons? My guess was to store conditions in registers, i.e., ALU stores "greater than" (0 if true else 1) in register 0, "greater than or equal to" in register 1, "less than" in register 2, and so on. When I want to check for inequality, I load the value in the address register and jump if it's 0.
// greater than or equal to loaded in address register
// below is equivalent to ld 0x03
ld geq
// set D register to value in geq
mv D M
// "loop" line address loaded in address register
ld loop
// goto "loop" if D is 0 else continue
D: jp
Is this right approach? This is 4 lines of instruction compared to single line to specify jump specification in the 16-bit computer! There has to be a simple better way to specify.
CodePudding user response:
Do you have any free opcodes in aaaa?
If so, you might add an "is-greater-than-0" and an "is-greater-than-or-equal-to-0" opcodes. These would check, say, the D register's value and replace it with a boolean 1 or 0.
So, your compare sequence is to subtract two items, then use one of these opcodes, and your conditional jump on zero.
You can swap the operands to subtraction to get the other relations (less than, less than zero).
You can also subtract 1 from a boolean to reverse it (make true 0 and make false non-zero).
Alternatively, you can shift away all but the sign bit, i.e. logical shift right by 15 bits will move the sign bit to the low bit position — that will give you 0 for >= 0 and 1 for < 0. (An arithmetic shift by 15 bits right would give 0 for >= 0 and -1 for < 0.)
As @Peter points out, compare instructions can operate without risk of overflow. MIPS provides for a single compare, slt
, which stand for set less than. MIPS also provides for branch on condition true as well as branch on condition false. That, combined with the ability to swap the operands, allows for all 4 relational operations (<, <=, >, >=).