Skip to content

Commit

Permalink
Adds a general conditional jump instruction (#44)
Browse files Browse the repository at this point in the history
* Adds pseudo instructions for all comparisons
* Updates example programs
* Updates bf compiler
* Updates README
  • Loading branch information
Frank Stokes committed Aug 3, 2017
1 parent 8598714 commit e9aa25b
Show file tree
Hide file tree
Showing 19 changed files with 150 additions and 109 deletions.
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ A couple of examples illustrating the language can be found in the `asm/` folder
### Instruction set

#### Real instructions

``
|Instruction|Arguments|16 bit representation |Description|
|-----------|---------|-------------------------|-------------|
|`MVR`| `D, S, V` | `VVVVVVVVSSDD0000` | Add a sign-extended byte to value at source register and move it to destination register|
Expand All @@ -48,7 +48,7 @@ A couple of examples illustrating the language can be found in the `asm/` folder
|`ATH`| `D, S, O, M, B` | `BBBMOOOOSSDD0100` | Perform an arithmetic operation on the source and destination registers. O specifies the operation (listed below) and M is the mode, where 0 = place result in destination register and 1 = place result in source register. If the instruction is right or left shift then B specifies the shifting value|
|`CAL`| `D` | `XXXXXXXXXXDD0101` | Call a function in memory pointed at by the destination register|
|`RET`| | `XXXXXXXXXXXX0110` | Return from function|
|`JLT`| `D, S` | `XXXXXXXXSSDD0111` | Jump to memory address pointed at by the source register, if value in the A register is less than value in destination register|
|`JCP`| `D, S, A, O` | `XXXOOOAASSDD0111` | Jump to memory address pointed at by the address register, depending on the comparison specified by the O operation of the destination register and the source register. Operation table specified below.|
|`PSH`| `S` | `XXXXXXXXSSXX1000` | Push the value in source register onto the stack|
|`POP`| `D` | `XXXXXXXXXXDD1001` | Pop the stack into the destination register|
|`SYS`| | `XXXXXXXXXXXX1010` | Perform a system call. This is described below in more detail.|
Expand Down Expand Up @@ -89,9 +89,14 @@ Pseudo instructions are prepocessed by the assembler and expanded into combinati
|`NOT` | `D` |1 | Binary not (invert) the destination|
|`LDV16` | `D, V` |2 | Load a 16 bit value into destination|
|`SWP` | `D, S` |3 | Swap the values in the source and destination registers|
|`JGE` | `D, A` |4 | Jump to address A if value in destination register is greater than or equal to the A register. Can potentially mutate all registers except A and destination|
|`JEQ` | `D, A` |11 | Jump to address A if value in destination register is equal to the A register. Can potentially mutate all registers except A and destination|
|`JNE` | `D, A` |14 | Jump to address A if value in destination register is not equal to the A register. Can potentially mutate all registers except A and destination|
|`JEQ` | `D, S, A` |1 | Jump to address A if value in destination register is equal to the source register.|
|`JNE` | `D, S, A` |1 | Jump to address A if value in destination register is not equal to the source register.|
|`JLT` | `D, S, A` |1 | Jump to address A if value in destination register is less than the source register.|
|`JGT` | `D, S, A` |1 | Jump to address A if value in destination register is greater than the source register.|
|`JLE` | `D, S, A` |1 | Jump to address A if value in destination register is less than or equal to the source register.|
|`JGE` | `D, S, A` |1 | Jump to address A if value in destination register is greater than or equal to the source register.|
|`JZE` | `D, S, A` |1 | Jump to address A if value in destination register is zero.|
|`JNZ` | `D, S, A` |1 | Jump to address A if value in destination register is not zero.|


#### Arithmetic Operation table
Expand Down
2 changes: 1 addition & 1 deletion asm/factorial.asm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ factorial:
pop A
ldv B, 3
ldv D, done:
jlt B, D
JLT A, B, D

psh a
psh b
Expand Down
4 changes: 2 additions & 2 deletions asm/get-name.asm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ get_name:
ldv d, get_name:
mov a, b
ldv b, 1
jlt b, d ; if a < 1, loop
jlt a, b, d ; if a < 1, loop

;;;;; Place character into memory ;;;;
ldv b, .name ; get the start address of name
Expand All @@ -39,7 +39,7 @@ get_name:

;;;;; Got all the characters? ;;;;;;;;
ldv c, final_zero:
jlt b, c ; if (a < b) = (name_max < name_pointer), we are done
jlt a, b, c ; if (a < b) = (name_max < name_pointer), we are done
ldv c, get_name: ; otherwise jump back to the beginning to get the next character
jmr c

Expand Down
2 changes: 1 addition & 1 deletion asm/loop-until-a-is-pressed.asm
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ main:

loop:
cal D
jne B, C
jne A, B, C

hlt
5 changes: 3 additions & 2 deletions src/assembler/assembler/instruction-encoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const {
SOURCE_SHIFT,
LONG_ADDRESS_SHIFT,
OFFSET_SHIFT,
ADDRESS_SHIFT,

JUMP,

ARITHMETIC_MODE_SHIFT,
OPERATION_SHIFT,
Expand Down Expand Up @@ -34,7 +35,7 @@ module.exports = {
STR: (args) => opcodes.STR | (reg[args[0]] << DESTINATION_SHIFT) | (reg[args[1]] << SOURCE_SHIFT) | (args.length > 2 ? (args[2] << OFFSET_SHIFT) : 0),
ATH: (args) => opcodes.ATH | (reg[args[0]] << DESTINATION_SHIFT) | (reg[args[1]] << SOURCE_SHIFT) | (args[2] << OPERATION_SHIFT) | (args[3] << ARITHMETIC_MODE_SHIFT) | (args[4] << BITWISE_SHIFT_SHIFT),
CAL: (args) => opcodes.CAL | (reg[args[0]] << DESTINATION_SHIFT),
JLT: (args) => opcodes.JLT | (reg[args[0]] << DESTINATION_SHIFT) | (reg[args[1]] << SOURCE_SHIFT),
JCP: (args) => opcodes.JCP | (reg[args[0]] << JUMP.R1) | (reg[args[1]] << JUMP.R2) | (reg[args[2]] << JUMP.AR) | (args[3] << JUMP.OP),
PSH: (args) => opcodes.PSH | (reg[args[0]] << SOURCE_SHIFT),
POP: (args) => opcodes.POP | (reg[args[0]] << DESTINATION_SHIFT),
JMP: (args) => opcodes.JMP | (reg[args[0]] << DESTINATION_SHIFT) | (args[1] << LONG_ADDRESS_SHIFT),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,7 @@
const {
getInstructionArguments,
uniqueLabel,
getUsableRegister
} = require('../../../../utils');
const { getInstructionArguments } = require('../../../../utils');
const { JUMP } = require('../../../../../../constants');

module.exports = (instruction) => {
const [source, addressRegister] = getInstructionArguments(instruction);
const mutableRegister = getUsableRegister(source, addressRegister);

const firstCheck = uniqueLabel();
const equal = uniqueLabel();
const notEqual = uniqueLabel();

return [
`PSH ${mutableRegister}`, // Push mr [mr]

`PSH ${addressRegister}`, // Push ar [ar, mr]
`LDV16 ${addressRegister}, ${firstCheck}`,
`LDV16 ${mutableRegister}, ${notEqual}`,

`JGE ${source}, ${addressRegister}`,
`JMR ${mutableRegister}`,

`${firstCheck}`,
`LDV16 ${addressRegister}, ${equal}`,
`SWP A, ${source}`,
`JGE ${source}, ${addressRegister}`,

`SWP A, ${source}`,
`JMR ${mutableRegister}`,

`${equal}`,
`SWP A, ${source}`,
`POP ${addressRegister}`, // Pop ar [mr]
`POP ${mutableRegister}`, // Pop mr []
`JMR ${addressRegister}`,

`${notEqual}`,
`POP ${addressRegister}`, // Pop ar [mr]
`POP ${mutableRegister}` // Pop mr []
];
}
const [r1, r2, addressRegister] = getInstructionArguments(instruction);
return [`JCP ${r1}, ${r2}, ${addressRegister}, ${JUMP.EQ}`];
};
Original file line number Diff line number Diff line change
@@ -1,24 +1,7 @@
const {
getInstructionArguments,
uniqueLabel,
getUsableRegister
} = require('../../../../utils');

const { getInstructionArguments } = require('../../../../utils');
const { JUMP } = require('../../../../../../constants');

module.exports = (instruction) => {
const [source, addressRegister] = getInstructionArguments(instruction);
const lessThan = uniqueLabel();
const mutableRegister = getUsableRegister(source, addressRegister);

return [
`PSH ${mutableRegister}`,
`LDV16 ${mutableRegister}, ${lessThan}`,

`JLT ${source}, ${mutableRegister}`,
`POP ${mutableRegister}`,
`JMR ${addressRegister}`,

`${lessThan}`,
`POP ${mutableRegister}`
];
}
const [r1, r2, addressRegister] = getInstructionArguments(instruction);
return [`JCP ${r1}, ${r2}, ${addressRegister}, ${JUMP.GTE}`];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const { getInstructionArguments } = require('../../../../utils');
const { JUMP } = require('../../../../../../constants');

module.exports = (instruction) => {
const [r1, r2, addressRegister] = getInstructionArguments(instruction);
return [`JCP ${r1}, ${r2}, ${addressRegister}, ${JUMP.GT}`];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const { getInstructionArguments } = require('../../../../utils');
const { JUMP } = require('../../../../../../constants');

module.exports = (instruction) => {
const [r1, r2, addressRegister] = getInstructionArguments(instruction);
return [`JCP ${r1}, ${r2}, ${addressRegister}, ${JUMP.JLE}`];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const { getInstructionArguments } = require('../../../../utils');
const { JUMP } = require('../../../../../../constants');

module.exports = (instruction) => {
const [r1, r2, addressRegister] = getInstructionArguments(instruction);
return [`JCP ${r1}, ${r2}, ${addressRegister}, ${JUMP.LT}`];
};
Original file line number Diff line number Diff line change
@@ -1,23 +1,7 @@
const {
getInstructionArguments,
uniqueLabel,
getUsableRegister
} = require('../../../../utils');
const { getInstructionArguments } = require('../../../../utils');
const { JUMP } = require('../../../../../../constants');

module.exports = (instruction) => {
const [source, addressRegister] = getInstructionArguments(instruction);
const equal = uniqueLabel();
const mutableRegister = getUsableRegister(source, addressRegister);

return [
`PSH ${mutableRegister}`,
`LDV16 ${mutableRegister}, ${equal}`,

`JEQ ${source}, ${mutableRegister}`,
`POP ${mutableRegister}`,
`JMR ${addressRegister}`,

`${equal}`,
`POP ${mutableRegister}`
];
}
const [r1, r2, addressRegister] = getInstructionArguments(instruction);
return [`JCP ${r1}, ${r2}, ${addressRegister}, ${JUMP.NEQ}`];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const { getInstructionArguments } = require('../../../../utils');
const { JUMP } = require('../../../../../../constants');

module.exports = (instruction) => {
const [r1, r2, addressRegister] = getInstructionArguments(instruction);
return [`JCP ${r1}, ${r2}, ${addressRegister}, ${JUMP.NZE}`];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const { getInstructionArguments } = require('../../../../utils');
const { JUMP } = require('../../../../../../constants');

module.exports = (instruction) => {
const [r1, r2, addressRegister] = getInstructionArguments(instruction);
return [`JCP ${r1}, ${r2}, ${addressRegister}, ${JUMP.ZER}`];
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
const JEQ = require('./JEQ');
const JGE = require('./JGE');
const JNE = require('./JNE');
const JLT = require('./JLT');
const JGT = require('./JGT');
const JLE = require('./JLE');
const JGE = require('./JGE');
const JZE = require('./JZE');
const JNZ = require('./JNZ');

module.exports = {
JEQ,
JNE,
JLT,
JGT,
JLE,
JGE,
JNE
JZE,
JNZ
};
2 changes: 1 addition & 1 deletion src/compilers/bf/asm/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ input:
mov A, B ; swap A and B
ldv B, 1 ; load 1 into B for comparison
ldv C, input: ; load the input address into C
jlt B, C ; if A < 1(B), loop back to input
jlt A, B, C ; if A < 1(B), loop back to input
psh A ; push the character into stack
ldv16 A, .offset ; Same procedure as inc_mem_ptr, except just set the value directly
ldr B, A
Expand Down
2 changes: 1 addition & 1 deletion src/compilers/bf/asm/loop-end.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ ldr B, A ; B = value at [memory + offset]
mov A, B ; A = value at [memory + offset]
ldv B, 1 ; Set B to comparison value of 1
ldv C, ${label}
jge B, C ; A(Memory value) >= B(1), then jump
jge A, B, C ; A(Memory value) >= B(1), then jump
`;
18 changes: 17 additions & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = {
'STA',
'ATH',
'CAL',
'JLT',
'JCP',
'RET',
'PSH',
'POP',
Expand All @@ -30,6 +30,22 @@ module.exports = {
ARITHMETIC_MODE_SHIFT: 12,
BITWISE_SHIFT_SHIFT: 13,

JUMP: {
EQ: 0,
NEQ: 1,
LT: 2,
GT: 3,
LTE: 4,
GTE: 5,
ZER: 6,
NZE: 7,

R1: 4,
R2: 6,
AR: 8,
OP: 10
},

ARITHMETIC: {
ADD: 0,
SUB: 1,
Expand Down
Loading

0 comments on commit e9aa25b

Please sign in to comment.