v86/src/modrm.macro.js
2013-11-06 01:12:55 +01:00

177 lines
3.9 KiB
JavaScript

/*
* 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";
var modrm_resolve16,
modrm_resolve32;
(function() {
var modrm_table16 = Array(0xC0),
modrm_table32 = Array(0xC0),
sib_table = Array(0x100);
#define ds get_seg_prefix(reg_ds)
#define ss get_seg_prefix(reg_ss)
#define eax reg32s[reg_eax]
#define ecx reg32s[reg_ecx]
#define edx reg32s[reg_edx]
#define ebx reg32s[reg_ebx]
#define esp reg32s[reg_esp]
#define ebp reg32s[reg_ebp]
#define esi reg32s[reg_esi]
#define edi reg32s[reg_edi]
#define imm32 read_imm32s()
#define imm16 read_imm16()
#define imm8 read_imm8()
#define entry16(row, seg, value)\
entry16_(0x00 | row, seg + ((value) & 0xFFFF))\
entry16_(0x40 | row, seg + ((value) + read_imm8s() & 0xFFFF))\
entry16_(0x80 | row, seg + ((value) + read_imm16() & 0xFFFF))\
#define entry16_(n, offset)\
modrm_table16[n] = function() { return offset | 0; };
entry16(0, ds, reg16[reg_bx] + reg16[reg_si])
entry16(1, ds, reg16[reg_bx] + reg16[reg_di])
entry16(2, ss, reg16[reg_bp] + reg16[reg_si])
entry16(3, ss, reg16[reg_bp] + reg16[reg_di])
entry16(4, ds, reg16[reg_si])
entry16(5, ds, reg16[reg_di])
entry16(6, ss, reg16[reg_bp])
entry16(7, ds, reg16[reg_bx])
#define entry32(row, value)\
entry32_(0x00 | row, (value))\
entry32_(0x40 | row, (value) + read_imm8s())\
entry32_(0x80 | row, (value) + read_imm32s())\
#define entry32_(n, offset)\
modrm_table32[n] = function() { return offset | 0; };
entry32(0, ds + eax);
entry32(1, ds + ecx);
entry32(2, ds + edx);
entry32(3, ds + ebx);
entry32(4, getsib(false));
entry32(5, ss + ebp);
entry32(6, ds + esi);
entry32(7, ds + edi);
// special cases
modrm_table16[0x00 | 6] = function() { return ds + read_imm16() | 0; }
modrm_table32[0x00 | 5] = function() { return ds + read_imm32s() | 0; };
modrm_table32[0x00 | 4] = function() { return getsib(false) | 0; };
modrm_table32[0x40 | 4] = function() { return getsib(true) + read_imm8s() | 0; };
modrm_table32[0x80 | 4] = function() { return getsib(true) + read_imm32s() | 0; };
for(var low = 0; low < 8; low++)
{
for(var high = 0; high < 3; high++)
{
for(var i = 1; i < 8; i++)
{
var x = low | high << 6;
modrm_table32[x | i << 3] = modrm_table32[x];
modrm_table16[x | i << 3] = modrm_table16[x];
}
}
}
#define entry_sib(n, reg1)\
entry_sib2(0x00 | n << 3, reg1)\
entry_sib2(0x40 | n << 3, reg1 << 1)\
entry_sib2(0x80 | n << 3, reg1 << 2)\
entry_sib2(0xC0 | n << 3, reg1 << 3)
#define entry_sib2(n, offset)\
entry_sib3(n | 0, (offset) + ds + eax)\
entry_sib3(n | 1, (offset) + ds + ecx)\
entry_sib3(n | 2, (offset) + ds + edx)\
entry_sib3(n | 3, (offset) + ds + ebx)\
entry_sib3(n | 4, (offset) + ss + esp)\
entry_sib3(n | 5, (offset) + (mod ? ss + ebp : ds + imm32))\
entry_sib3(n | 6, (offset) + ds + esi)\
entry_sib3(n | 7, (offset) + ds + edi)
#define entry_sib3(n, offset)\
sib_table[n] = function(mod) { return offset | 0; };
entry_sib(0, eax);
entry_sib(1, ecx);
entry_sib(2, edx);
entry_sib(3, ebx);
entry_sib(4, 0);
entry_sib(5, ebp);
entry_sib(6, esi);
entry_sib(7, edi);
/**
* @param {number} modrm_byte
* @return {number}
*/
modrm_resolve16 = function(modrm_byte)
{
return modrm_table16[modrm_byte]();
}
/**
* @param {number} modrm_byte
* @return {number}
*/
modrm_resolve32 = function(modrm_byte)
{
return modrm_table32[modrm_byte]();
}
/**
* @param {boolean} mod
* @return {number}
*/
function getsib(mod)
{
return sib_table[read_imm8()](mod);
}
#undef ds
#undef ss
#undef eax
#undef ecx
#undef edx
#undef ebx
#undef esp
#undef ebp
#undef esi
#undef edi
#undef imm32
#undef imm16
#undef imm8
#undef entry16
#undef entry16_
#undef entry32_
#undef entry_sib
#undef entry_sib2
#undef entry_sib3
})();