Add more Instructions
Currently, 8086.js can only execute the instructions in the switch-case below. However, support needs to be added for the remaining instructions to make it more usable.
Also, some instructions are not implemented properly, which maybe be because of one of the following reasons.
- They do not set the right flags
- They do not check the operand sizes before executing the operation.
These need to be fixed to make it behave more like an Intel 8086.
Currently implemented instructions
The following is a list of instructions that have been implemented. They have been written in src/emulator/cpu/core.js, and they use the Addressing class from addressing.js in the same folder.
Note: Relative addressing has not been implemented yet.
|
switch (mnemonic.value) { |
|
case 'MOV': |
|
if (op1.size < op2.size) { |
|
throw SyntaxError(`Can't move larger ${op2.size} bit value to ${op1.size} bit location`); |
|
} |
|
setAddr(op1, getAddr(op2)); |
|
break; |
|
|
|
case 'JS': |
|
if (regs.flags.getFlag(flags.sign) === 1) { |
|
ip = getAddr(op1) - 1; |
|
} |
|
break; |
|
|
|
case 'JNS': { |
|
if (regs.flags.getFlag(flags.sign) === 0) { |
|
ip = getAddr(op1) - 1; |
|
} |
|
break; |
|
} |
|
case 'JO': { |
|
if (regs.flags.getFlag(flags.overflow) === 1) { |
|
ip = getAddr(op1) - 1; |
|
} |
|
break; |
|
} |
|
case 'JNO': { |
|
if (regs.flags.getFlag(flags.overflow) === 0) { |
|
ip = getAddr(op1) - 1; |
|
} |
|
break; |
|
} |
|
case 'JP': |
|
case 'JPE': |
|
{ |
|
if (regs.flags.getFlag(flags.parity) === 1) { |
|
ip = getAddr(op1) - 1; |
|
} |
|
break; |
|
} |
|
case 'JNP': |
|
{ |
|
if (regs.flags.getFlag(flags.parity) === 0) { |
|
ip = getAddr(op1) - 1; |
|
} |
|
break; |
|
} |
|
case 'ADD': |
|
if (!op2) { |
|
let s = op1.size === 8 ? regs.AX.get('l') : regs.AX.get(); |
|
s += getAddr(op1); |
|
regs.AX.set(s); |
|
} else { |
|
let s = getAddr(op1); |
|
s += getAddr(op2); |
|
setAddr(op1, s); |
|
} |
|
break; |
|
|
|
case 'DIV': |
|
if (op1.size === 8) { |
|
const al = regs.AX.get('l') / getAddr(op1); |
|
const ah = regs.AX.get('l') % getAddr(op1); |
|
regs.AX.set(al, 'l'); |
|
regs.AX.set(ah, 'h'); |
|
} else { |
|
const ax = regs.AX.get() / getAddr(op1); |
|
const dx = regs.AX.get() % getAddr(op1); |
|
regs.AX.set(ax); |
|
regs.DX.set(dx); |
|
} |
|
break; |
|
|
|
case 'MUL': |
|
if (op1.size === 8) { |
|
const prod = regs.AX.get('l') * getAddr(op1); |
|
regs.AX.set(prod); |
|
} else { |
|
const prod = regs.AX.get() * getAddr(op1); |
|
regs.AX.set(prod); |
|
// Store higher bits in DX |
|
} |
|
break; |
|
|
|
case 'AND': |
|
setAddr(op1, getAddr(op1) & getAddr(op2)); |
|
break; |
|
|
|
case 'OR': |
|
setAddr(op1, getAddr(op1) | getAddr(op2)); |
|
break; |
|
case 'SUB': { |
|
const s1 = getAddr(op1); |
|
const s2 = getAddr(op2); |
|
const ans = s1 - s2; |
|
setAddr(op1, ans); |
|
break; |
|
} |
|
case 'CMP': { |
|
const s1 = getAddr(op1); |
|
const s2 = getAddr(op2); |
|
if (s1 === s2) { |
|
regs.flags.setFlag(flags.zero); |
|
regs.flags.unsetFlag(flags.carry); |
|
} else if (s1 > s2) { |
|
regs.flags.unsetFlag(flags.zero); |
|
regs.flags.unsetFlag(flags.carry); |
|
} else { |
|
regs.flags.setFlag(flags.carry); |
|
regs.flags.unsetFlag(flags.zero); |
|
} |
|
break; |
|
} |
|
case 'NOT': { |
|
setAddr(op1, ~getAddr(op1)); |
|
break; |
|
} |
|
case 'JMP': { |
|
ip = getAddr(op1) - 1; |
|
break; |
|
} |
|
case 'JE': |
|
case 'JZ': |
|
{ |
|
if (regs.flags.getFlag(flags.zero) === 1) { |
|
ip = getAddr(op1) - 1; |
|
} |
|
break; |
|
} |
|
case 'JNE': |
|
case 'JNZ': |
|
{ |
|
if (regs.flags.getFlag(flags.zero) === 0) { |
|
ip = getAddr(op1) - 1; |
|
} |
|
break; |
|
} |
|
default: |
|
break; |
|
} |
Add more Instructions
Currently,
8086.jscan only execute the instructions in theswitch-casebelow. However, support needs to be added for the remaining instructions to make it more usable.Also, some instructions are not implemented properly, which maybe be because of one of the following reasons.
These need to be fixed to make it behave more like an Intel 8086.
Currently implemented instructions
The following is a list of instructions that have been implemented. They have been written in src/emulator/cpu/core.js, and they use the
Addressingclass fromaddressing.jsin the same folder.8086.js/src/emulator/cpu/core.js
Lines 33 to 172 in 017505b