Skip to content

Add more 8086 Instructions #13

@roerohan

Description

@roerohan

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;
}

Metadata

Metadata

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions