blob: 51080bfc795d08136ca1a27f7551919685553ef9 [file] [log] [blame] [raw]
/*
* This file contains functions to decode the modrm and sib bytes
*
* These functions return a virtual address
*
* Gets #included by cpu.macro.js
*/
"use strict";
(function() {
v86.prototype.modrm_table16 = Array(0xC0);
v86.prototype.modrm_table32 = Array(0xC0);
v86.prototype.sib_table = Array(0x100);
#define ds cpu.get_seg_prefix(reg_ds)
#define ss cpu.get_seg_prefix(reg_ss)
#define eax cpu.reg32s[reg_eax]
#define ecx cpu.reg32s[reg_ecx]
#define edx cpu.reg32s[reg_edx]
#define ebx cpu.reg32s[reg_ebx]
#define esp cpu.reg32s[reg_esp]
#define ebp cpu.reg32s[reg_ebp]
#define esi cpu.reg32s[reg_esi]
#define edi cpu.reg32s[reg_edi]
#define entry16_level1(row, seg, value)\
entry16_level2(0x00 | row, seg + ((value) & 0xFFFF))\
entry16_level2(0x40 | row, seg + ((value) + cpu.read_imm8s() & 0xFFFF))\
entry16_level2(0x80 | row, seg + ((value) + cpu.read_imm16() & 0xFFFF))\
#define entry16_level2(n, offset)\
v86.prototype.modrm_table16[n] = function(cpu) { return offset | 0; };\
entry16_level1(0, ds, cpu.reg16[reg_bx] + cpu.reg16[reg_si])
entry16_level1(1, ds, cpu.reg16[reg_bx] + cpu.reg16[reg_di])
entry16_level1(2, ss, cpu.reg16[reg_bp] + cpu.reg16[reg_si])
entry16_level1(3, ss, cpu.reg16[reg_bp] + cpu.reg16[reg_di])
entry16_level1(4, ds, cpu.reg16[reg_si])
entry16_level1(5, ds, cpu.reg16[reg_di])
entry16_level1(6, ss, cpu.reg16[reg_bp])
entry16_level1(7, ds, cpu.reg16[reg_bx])
#define getsib(mod)\
cpu.sib_table[cpu.read_imm8()](cpu, mod)
#define entry32_level1(row, value)\
entry32_level2(0x00 | row, (value))\
entry32_level2(0x40 | row, (value) + cpu.read_imm8s())\
entry32_level2(0x80 | row, (value) + cpu.read_imm32s())\
#define entry32_level2(n, offset)\
v86.prototype.modrm_table32[n] = function(cpu) { return offset | 0; };
entry32_level1(0, ds + eax);
entry32_level1(1, ds + ecx);
entry32_level1(2, ds + edx);
entry32_level1(3, ds + ebx);
entry32_level1(4, getsib(false));
entry32_level1(5, ss + ebp);
entry32_level1(6, ds + esi);
entry32_level1(7, ds + edi);
// special cases
v86.prototype.modrm_table16[0x00 | 6] = function(cpu) { return ds + cpu.read_imm16() | 0; }
v86.prototype.modrm_table32[0x00 | 5] = function(cpu) { return ds + cpu.read_imm32s() | 0; };
v86.prototype.modrm_table32[0x00 | 4] = function(cpu) { return getsib(false) | 0; };
v86.prototype.modrm_table32[0x40 | 4] = function(cpu) { return getsib(true) + cpu.read_imm8s() | 0; };
v86.prototype.modrm_table32[0x80 | 4] = function(cpu) { return getsib(true) + cpu.read_imm32s() | 0; };
for(var low = 0; low < 8; low++)
{
for(var high = 0; high < 3; high++)
{
var x = low | high << 6;
for(var i = 1; i < 8; i++)
{
v86.prototype.modrm_table32[x | i << 3] = v86.prototype.modrm_table32[x];
v86.prototype.modrm_table16[x | i << 3] = v86.prototype.modrm_table16[x];
}
}
}
#define entry_sib_level1(n, reg1)\
entry_sib_level2(0x00 | n << 3, reg1)\
entry_sib_level2(0x40 | n << 3, reg1 << 1)\
entry_sib_level2(0x80 | n << 3, reg1 << 2)\
entry_sib_level2(0xC0 | n << 3, reg1 << 3)
#define entry_sib_level2(n, offset)\
entry_sib_level3(n | 0, (offset) + ds + eax)\
entry_sib_level3(n | 1, (offset) + ds + ecx)\
entry_sib_level3(n | 2, (offset) + ds + edx)\
entry_sib_level3(n | 3, (offset) + ds + ebx)\
entry_sib_level3(n | 4, (offset) + ss + esp)\
entry_sib_level3(n | 5, (offset) + (mod ? ss + ebp : ds + cpu.read_imm32s()))\
entry_sib_level3(n | 6, (offset) + ds + esi)\
entry_sib_level3(n | 7, (offset) + ds + edi)
#define entry_sib_level3(n, offset)\
v86.prototype.sib_table[n] = function(cpu, mod) { return offset | 0; };
entry_sib_level1(0, eax);
entry_sib_level1(1, ecx);
entry_sib_level1(2, edx);
entry_sib_level1(3, ebx);
entry_sib_level1(4, 0);
entry_sib_level1(5, ebp);
entry_sib_level1(6, esi);
entry_sib_level1(7, edi);
///**
// * @param {number} modrm_byte
// * @return {number}
// */
//v86.prototype.modrm_resolve16 = function(modrm_byte)
//{
// return this.modrm_table16[modrm_byte](this);
//}
///**
// * @param {number} modrm_byte
// * @return {number}
// */
//v86.prototype.modrm_resolve32 = function(modrm_byte)
//{
// return this.modrm_table32[modrm_byte](this);
//}
v86.prototype.modrm_resolve = function(modrm_byte)
{
return (this.address_size_32 ? this.modrm_table32 : this.modrm_table16)[modrm_byte](this);
};
//v86.prototype.modrm_skip = function(modrm_byte)
//{
// // advance the instruction pointer depending on modrm byte
// // but don't actually do address arithmatic
//
// if(modrm_byte < 0xC0)
// {
// // TODO
// this.modrm_resolve(modrm_byte);
// }
//}
#undef ds
#undef ss
#undef eax
#undef ecx
#undef edx
#undef ebx
#undef esp
#undef ebp
#undef esi
#undef edi
#undef entry16_level1
#undef entry16_level2
#undef entry32_level1
#undef entry32_level2
#undef getsib
#undef entry_sib_level1
#undef entry_sib_level2
#undef entry_sib_level3
})();