VM: Refactor instruction_operands.cpp/hpp to Factor style

db4
Erik Charlebois 2013-05-11 22:06:39 -04:00
parent f6047832cb
commit d3d1d3bb7a
2 changed files with 251 additions and 272 deletions

View File

@ -1,171 +1,165 @@
#include "master.hpp" #include "master.hpp"
namespace factor namespace factor {
{
instruction_operand::instruction_operand(relocation_entry rel_, code_block *compiled_, cell index_) : instruction_operand::instruction_operand(relocation_entry rel_,
rel(rel_), compiled(compiled_), index(index_), pointer((cell)compiled_->entry_point() + rel_.rel_offset()) {} code_block* compiled_, cell index_)
: rel(rel_),
compiled(compiled_),
index(index_),
pointer((cell) compiled_->entry_point() + rel_.rel_offset()) {}
/* Load a 32-bit value from a PowerPC LIS/ORI sequence */ /* Load a 32-bit value from a PowerPC LIS/ORI sequence */
fixnum instruction_operand::load_value_2_2() fixnum instruction_operand::load_value_2_2() {
{ u32* ptr = (u32*)pointer;
u32 *ptr = (u32 *)pointer; cell hi = (ptr[-2] & 0xffff);
cell hi = (ptr[-2] & 0xffff); cell lo = (ptr[-1] & 0xffff);
cell lo = (ptr[-1] & 0xffff); return hi << 16 | lo;
return hi << 16 | lo;
} }
/* Load a 64-bit value from a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */ /* Load a 64-bit value from a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */
fixnum instruction_operand::load_value_2_2_2_2() fixnum instruction_operand::load_value_2_2_2_2() {
{ u32* ptr = (u32*)pointer;
u32 *ptr = (u32 *)pointer; u64 hhi = (ptr[-5] & 0xffff);
u64 hhi = (ptr[-5] & 0xffff); u64 hlo = (ptr[-4] & 0xffff);
u64 hlo = (ptr[-4] & 0xffff); u64 lhi = (ptr[-2] & 0xffff);
u64 lhi = (ptr[-2] & 0xffff); u64 llo = (ptr[-1] & 0xffff);
u64 llo = (ptr[-1] & 0xffff); u64 val = hhi << 48 | hlo << 32 | lhi << 16 | llo;
u64 val = hhi << 48 | hlo << 32 | lhi << 16 | llo; return (cell) val;
return (cell)val;
} }
/* Load a value from a bitfield of a PowerPC instruction */ /* Load a value from a bitfield of a PowerPC instruction */
fixnum instruction_operand::load_value_masked(cell mask, cell bits, cell shift) fixnum instruction_operand::load_value_masked(cell mask, cell bits,
{ cell shift) {
s32 *ptr = (s32 *)(pointer - sizeof(u32)); s32* ptr = (s32*)(pointer - sizeof(u32));
return (((*ptr & (s32)mask) << bits) >> bits) << shift; return (((*ptr & (s32) mask) << bits) >> bits) << shift;
} }
fixnum instruction_operand::load_value(cell relative_to) fixnum instruction_operand::load_value(cell relative_to) {
{ switch (rel.rel_class()) {
switch(rel.rel_class()) case RC_ABSOLUTE_CELL:
{ return *(cell*)(pointer - sizeof(cell));
case RC_ABSOLUTE_CELL: case RC_ABSOLUTE:
return *(cell *)(pointer - sizeof(cell)); return *(u32*)(pointer - sizeof(u32));
case RC_ABSOLUTE: case RC_RELATIVE:
return *(u32 *)(pointer - sizeof(u32)); return *(s32*)(pointer - sizeof(u32)) + relative_to;
case RC_RELATIVE: case RC_ABSOLUTE_PPC_2_2:
return *(s32 *)(pointer - sizeof(u32)) + relative_to; return load_value_2_2();
case RC_ABSOLUTE_PPC_2_2: case RC_ABSOLUTE_PPC_2:
return load_value_2_2(); return load_value_masked(rel_absolute_ppc_2_mask, 16, 0);
case RC_ABSOLUTE_PPC_2: case RC_RELATIVE_PPC_2_PC:
return load_value_masked(rel_absolute_ppc_2_mask,16,0); return load_value_masked(rel_relative_ppc_2_mask, 16, 0) + relative_to -
case RC_RELATIVE_PPC_2_PC: 4;
return load_value_masked(rel_relative_ppc_2_mask,16,0) + relative_to - 4; case RC_RELATIVE_PPC_3_PC:
case RC_RELATIVE_PPC_3_PC: return load_value_masked(rel_relative_ppc_3_mask, 6, 0) + relative_to - 4;
return load_value_masked(rel_relative_ppc_3_mask,6,0) + relative_to - 4; case RC_RELATIVE_ARM_3:
case RC_RELATIVE_ARM_3: return load_value_masked(rel_relative_arm_3_mask, 6, 2) + relative_to +
return load_value_masked(rel_relative_arm_3_mask,6,2) + relative_to + sizeof(cell); sizeof(cell);
case RC_INDIRECT_ARM: case RC_INDIRECT_ARM:
return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to; return load_value_masked(rel_indirect_arm_mask, 20, 0) + relative_to;
case RC_INDIRECT_ARM_PC: case RC_INDIRECT_ARM_PC:
return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to + sizeof(cell); return load_value_masked(rel_indirect_arm_mask, 20, 0) + relative_to +
case RC_ABSOLUTE_2: sizeof(cell);
return *(u16 *)(pointer - sizeof(u16)); case RC_ABSOLUTE_2:
case RC_ABSOLUTE_1: return *(u16*)(pointer - sizeof(u16));
return *(u8 *)(pointer - sizeof(u8)); case RC_ABSOLUTE_1:
case RC_ABSOLUTE_PPC_2_2_2_2: return *(u8*)(pointer - sizeof(u8));
return load_value_2_2_2_2(); case RC_ABSOLUTE_PPC_2_2_2_2:
default: return load_value_2_2_2_2();
critical_error("Bad rel class",rel.rel_class()); default:
return 0; critical_error("Bad rel class", rel.rel_class());
} return 0;
}
} }
fixnum instruction_operand::load_value() fixnum instruction_operand::load_value() { return load_value(pointer); }
{
return load_value(pointer); code_block* instruction_operand::load_code_block(cell relative_to) {
return ((code_block*)load_value(relative_to) - 1);
} }
code_block *instruction_operand::load_code_block(cell relative_to) code_block* instruction_operand::load_code_block() {
{ return load_code_block(pointer);
return ((code_block *)load_value(relative_to) - 1);
}
code_block *instruction_operand::load_code_block()
{
return load_code_block(pointer);
} }
/* Store a 32-bit value into a PowerPC LIS/ORI sequence */ /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
void instruction_operand::store_value_2_2(fixnum value) void instruction_operand::store_value_2_2(fixnum value) {
{ u32* ptr = (u32*)pointer;
u32 *ptr = (u32 *)pointer; ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff));
ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff)); ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff));
ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff));
} }
/* Store a 64-bit value into a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */ /* Store a 64-bit value into a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */
void instruction_operand::store_value_2_2_2_2(fixnum value) void instruction_operand::store_value_2_2_2_2(fixnum value) {
{ u64 val = value;
u64 val = value; u32* ptr = (u32*)pointer;
u32 *ptr = (u32 *)pointer; ptr[-5] = ((ptr[-5] & ~0xffff) | ((val >> 48) & 0xffff));
ptr[-5] = ((ptr[-5] & ~0xffff) | ((val >> 48) & 0xffff)); ptr[-4] = ((ptr[-4] & ~0xffff) | ((val >> 32) & 0xffff));
ptr[-4] = ((ptr[-4] & ~0xffff) | ((val >> 32) & 0xffff)); ptr[-2] = ((ptr[-2] & ~0xffff) | ((val >> 16) & 0xffff));
ptr[-2] = ((ptr[-2] & ~0xffff) | ((val >> 16) & 0xffff)); ptr[-1] = ((ptr[-1] & ~0xffff) | ((val >> 0) & 0xffff));
ptr[-1] = ((ptr[-1] & ~0xffff) | ((val >> 0) & 0xffff));
} }
/* Store a value into a bitfield of a PowerPC instruction */ /* Store a value into a bitfield of a PowerPC instruction */
void instruction_operand::store_value_masked(fixnum value, cell mask, cell shift) void instruction_operand::store_value_masked(fixnum value, cell mask,
{ cell shift) {
u32 *ptr = (u32 *)(pointer - sizeof(u32)); u32* ptr = (u32*)(pointer - sizeof(u32));
*ptr = (u32)((*ptr & ~mask) | ((value >> shift) & mask)); *ptr = (u32)((*ptr & ~mask) | ((value >> shift) & mask));
} }
void instruction_operand::store_value(fixnum absolute_value) void instruction_operand::store_value(fixnum absolute_value) {
{ fixnum relative_value = absolute_value - pointer;
fixnum relative_value = absolute_value - pointer;
switch(rel.rel_class()) switch (rel.rel_class()) {
{ case RC_ABSOLUTE_CELL:
case RC_ABSOLUTE_CELL: *(cell*)(pointer - sizeof(cell)) = absolute_value;
*(cell *)(pointer - sizeof(cell)) = absolute_value; break;
break; case RC_ABSOLUTE:
case RC_ABSOLUTE: *(u32*)(pointer - sizeof(u32)) = (u32) absolute_value;
*(u32 *)(pointer - sizeof(u32)) = (u32)absolute_value; break;
break; case RC_RELATIVE:
case RC_RELATIVE: *(s32*)(pointer - sizeof(s32)) = (s32) relative_value;
*(s32 *)(pointer - sizeof(s32)) = (s32)relative_value; break;
break; case RC_ABSOLUTE_PPC_2_2:
case RC_ABSOLUTE_PPC_2_2: store_value_2_2(absolute_value);
store_value_2_2(absolute_value); break;
break; case RC_ABSOLUTE_PPC_2:
case RC_ABSOLUTE_PPC_2: store_value_masked(absolute_value, rel_absolute_ppc_2_mask, 0);
store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0); break;
break; case RC_RELATIVE_PPC_2_PC:
case RC_RELATIVE_PPC_2_PC: store_value_masked(relative_value + 4, rel_relative_ppc_2_mask, 0);
store_value_masked(relative_value + 4,rel_relative_ppc_2_mask,0); break;
break; case RC_RELATIVE_PPC_3_PC:
case RC_RELATIVE_PPC_3_PC: store_value_masked(relative_value + 4, rel_relative_ppc_3_mask, 0);
store_value_masked(relative_value + 4,rel_relative_ppc_3_mask,0); break;
break; case RC_RELATIVE_ARM_3:
case RC_RELATIVE_ARM_3: store_value_masked(relative_value - sizeof(cell), rel_relative_arm_3_mask,
store_value_masked(relative_value - sizeof(cell),rel_relative_arm_3_mask,2); 2);
break; break;
case RC_INDIRECT_ARM: case RC_INDIRECT_ARM:
store_value_masked(relative_value,rel_indirect_arm_mask,0); store_value_masked(relative_value, rel_indirect_arm_mask, 0);
break; break;
case RC_INDIRECT_ARM_PC: case RC_INDIRECT_ARM_PC:
store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0); store_value_masked(relative_value - sizeof(cell), rel_indirect_arm_mask,
break; 0);
case RC_ABSOLUTE_2: break;
*(u16 *)(pointer - sizeof(u16)) = (u16)absolute_value; case RC_ABSOLUTE_2:
break; *(u16*)(pointer - sizeof(u16)) = (u16) absolute_value;
case RC_ABSOLUTE_1: break;
*(u8 *)(pointer - sizeof(u8)) = (u8)absolute_value; case RC_ABSOLUTE_1:
break; *(u8*)(pointer - sizeof(u8)) = (u8) absolute_value;
case RC_ABSOLUTE_PPC_2_2_2_2: break;
store_value_2_2_2_2(absolute_value); case RC_ABSOLUTE_PPC_2_2_2_2:
break; store_value_2_2_2_2(absolute_value);
default: break;
critical_error("Bad rel class",rel.rel_class()); default:
break; critical_error("Bad rel class", rel.rel_class());
} break;
}
} }
void instruction_operand::store_code_block(code_block *compiled) void instruction_operand::store_code_block(code_block* compiled) {
{ store_value((cell) compiled->entry_point());
store_value((cell)compiled->entry_point());
} }
} }

View File

@ -1,168 +1,153 @@
namespace factor namespace factor {
{
enum relocation_type { enum relocation_type {
/* arg is a literal table index, holding a pair (symbol/dll) */ /* arg is a literal table index, holding a pair (symbol/dll) */
RT_DLSYM, RT_DLSYM,
/* a word or quotation's general entry point */ /* a word or quotation's general entry point */
RT_ENTRY_POINT, RT_ENTRY_POINT,
/* a word's PIC entry point */ /* a word's PIC entry point */
RT_ENTRY_POINT_PIC, RT_ENTRY_POINT_PIC,
/* a word's tail-call PIC entry point */ /* a word's tail-call PIC entry point */
RT_ENTRY_POINT_PIC_TAIL, RT_ENTRY_POINT_PIC_TAIL,
/* current offset */ /* current offset */
RT_HERE, RT_HERE,
/* current code block */ /* current code block */
RT_THIS, RT_THIS,
/* data heap literal */ /* data heap literal */
RT_LITERAL, RT_LITERAL,
/* untagged fixnum literal */ /* untagged fixnum literal */
RT_UNTAGGED, RT_UNTAGGED,
/* address of megamorphic_cache_hits var */ /* address of megamorphic_cache_hits var */
RT_MEGAMORPHIC_CACHE_HITS, RT_MEGAMORPHIC_CACHE_HITS,
/* address of vm object */ /* address of vm object */
RT_VM, RT_VM,
/* value of vm->cards_offset */ /* value of vm->cards_offset */
RT_CARDS_OFFSET, RT_CARDS_OFFSET,
/* value of vm->decks_offset */ /* value of vm->decks_offset */
RT_DECKS_OFFSET, RT_DECKS_OFFSET,
/* address of exception_handler -- this exists as a separate relocation /* address of exception_handler -- this exists as a separate relocation
type since its used in a situation where relocation arguments cannot type since its used in a situation where relocation arguments cannot
be passed in, and so RT_DLSYM is inappropriate (Windows only) */ be passed in, and so RT_DLSYM is inappropriate (Windows only) */
RT_EXCEPTION_HANDLER, RT_EXCEPTION_HANDLER,
/* arg is a literal table index, holding a pair (symbol/dll) */ /* arg is a literal table index, holding a pair (symbol/dll) */
RT_DLSYM_TOC, RT_DLSYM_TOC,
/* address of inline_cache_miss function. This is a separate /* address of inline_cache_miss function. This is a separate
relocation to reduce compile time and size for PICs. */ relocation to reduce compile time and size for PICs. */
RT_INLINE_CACHE_MISS, RT_INLINE_CACHE_MISS,
/* address of safepoint page in code heap */ /* address of safepoint page in code heap */
RT_SAFEPOINT RT_SAFEPOINT
}; };
enum relocation_class { enum relocation_class {
/* absolute address in a pointer-width location */ /* absolute address in a pointer-width location */
RC_ABSOLUTE_CELL, RC_ABSOLUTE_CELL,
/* absolute address in a 4 byte location */ /* absolute address in a 4 byte location */
RC_ABSOLUTE, RC_ABSOLUTE,
/* relative address in a 4 byte location */ /* relative address in a 4 byte location */
RC_RELATIVE, RC_RELATIVE,
/* absolute address in a PowerPC LIS/ORI sequence */ /* absolute address in a PowerPC LIS/ORI sequence */
RC_ABSOLUTE_PPC_2_2, RC_ABSOLUTE_PPC_2_2,
/* absolute address in a PowerPC LWZ instruction */ /* absolute address in a PowerPC LWZ instruction */
RC_ABSOLUTE_PPC_2, RC_ABSOLUTE_PPC_2,
/* relative address in a PowerPC LWZ/STW/BC instruction */ /* relative address in a PowerPC LWZ/STW/BC instruction */
RC_RELATIVE_PPC_2_PC, RC_RELATIVE_PPC_2_PC,
/* relative address in a PowerPC B/BL instruction */ /* relative address in a PowerPC B/BL instruction */
RC_RELATIVE_PPC_3_PC, RC_RELATIVE_PPC_3_PC,
/* relative address in an ARM B/BL instruction */ /* relative address in an ARM B/BL instruction */
RC_RELATIVE_ARM_3, RC_RELATIVE_ARM_3,
/* pointer to address in an ARM LDR/STR instruction */ /* pointer to address in an ARM LDR/STR instruction */
RC_INDIRECT_ARM, RC_INDIRECT_ARM,
/* pointer to address in an ARM LDR/STR instruction offset by 8 bytes */ /* pointer to address in an ARM LDR/STR instruction offset by 8 bytes */
RC_INDIRECT_ARM_PC, RC_INDIRECT_ARM_PC,
/* absolute address in a 2 byte location */ /* absolute address in a 2 byte location */
RC_ABSOLUTE_2, RC_ABSOLUTE_2,
/* absolute address in a 1 byte location */ /* absolute address in a 1 byte location */
RC_ABSOLUTE_1, RC_ABSOLUTE_1,
/* absolute address in a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */ /* absolute address in a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */
RC_ABSOLUTE_PPC_2_2_2_2, RC_ABSOLUTE_PPC_2_2_2_2,
}; };
static const cell rel_absolute_ppc_2_mask = 0x0000ffff; static const cell rel_absolute_ppc_2_mask = 0x0000ffff;
static const cell rel_relative_ppc_2_mask = 0x0000fffc; static const cell rel_relative_ppc_2_mask = 0x0000fffc;
static const cell rel_relative_ppc_3_mask = 0x03fffffc; static const cell rel_relative_ppc_3_mask = 0x03fffffc;
static const cell rel_indirect_arm_mask = 0x00000fff; static const cell rel_indirect_arm_mask = 0x00000fff;
static const cell rel_relative_arm_3_mask = 0x00ffffff; static const cell rel_relative_arm_3_mask = 0x00ffffff;
/* code relocation table consists of a table of entries for each fixup */ /* code relocation table consists of a table of entries for each fixup */
struct relocation_entry { struct relocation_entry {
u32 value; u32 value;
explicit relocation_entry(u32 value_) : value(value_) {} explicit relocation_entry(u32 value_) : value(value_) {}
relocation_entry(relocation_type rel_type, relocation_entry(relocation_type rel_type, relocation_class rel_class,
relocation_class rel_class, cell offset) {
cell offset) value = (u32)((rel_type << 28) | (rel_class << 24) | offset);
{ }
value = (u32)((rel_type << 28) | (rel_class << 24) | offset);
}
relocation_type rel_type() relocation_type rel_type() {
{ return (relocation_type)((value & 0xf0000000) >> 28);
return (relocation_type)((value & 0xf0000000) >> 28); }
}
relocation_class rel_class() relocation_class rel_class() {
{ return (relocation_class)((value & 0x0f000000) >> 24);
return (relocation_class)((value & 0x0f000000) >> 24); }
}
cell rel_offset() cell rel_offset() { return (value & 0x00ffffff); }
{
return (value & 0x00ffffff);
}
int number_of_parameters() int number_of_parameters() {
{ switch (rel_type()) {
switch(rel_type()) case RT_VM:
{ return 1;
case RT_VM: case RT_DLSYM:
return 1; case RT_DLSYM_TOC:
case RT_DLSYM: return 2;
case RT_DLSYM_TOC: case RT_ENTRY_POINT:
return 2; case RT_ENTRY_POINT_PIC:
case RT_ENTRY_POINT: case RT_ENTRY_POINT_PIC_TAIL:
case RT_ENTRY_POINT_PIC: case RT_LITERAL:
case RT_ENTRY_POINT_PIC_TAIL: case RT_HERE:
case RT_LITERAL: case RT_UNTAGGED:
case RT_HERE: case RT_THIS:
case RT_UNTAGGED: case RT_MEGAMORPHIC_CACHE_HITS:
case RT_THIS: case RT_CARDS_OFFSET:
case RT_MEGAMORPHIC_CACHE_HITS: case RT_DECKS_OFFSET:
case RT_CARDS_OFFSET: case RT_EXCEPTION_HANDLER:
case RT_DECKS_OFFSET: case RT_INLINE_CACHE_MISS:
case RT_EXCEPTION_HANDLER: case RT_SAFEPOINT:
case RT_INLINE_CACHE_MISS: return 0;
case RT_SAFEPOINT: default:
return 0; critical_error("Bad rel type in number_of_parameters()", rel_type());
default: return -1; /* Can't happen */
critical_error("Bad rel type in number_of_parameters()",rel_type()); }
return -1; /* Can't happen */ }
}
}
}; };
struct instruction_operand { struct instruction_operand {
relocation_entry rel; relocation_entry rel;
code_block *compiled; code_block* compiled;
cell index; cell index;
cell pointer; cell pointer;
instruction_operand(relocation_entry rel_, code_block *compiled_, cell index_); instruction_operand(relocation_entry rel_, code_block* compiled_,
cell index_);
relocation_type rel_type() relocation_type rel_type() { return rel.rel_type(); }
{
return rel.rel_type();
}
cell rel_offset() cell rel_offset() { return rel.rel_offset(); }
{
return rel.rel_offset();
}
fixnum load_value_2_2(); fixnum load_value_2_2();
fixnum load_value_2_2_2_2(); fixnum load_value_2_2_2_2();
fixnum load_value_masked(cell mask, cell bits, cell shift); fixnum load_value_masked(cell mask, cell bits, cell shift);
fixnum load_value(cell relative_to); fixnum load_value(cell relative_to);
fixnum load_value(); fixnum load_value();
code_block *load_code_block(cell relative_to); code_block* load_code_block(cell relative_to);
code_block *load_code_block(); code_block* load_code_block();
void store_value_2_2(fixnum value); void store_value_2_2(fixnum value);
void store_value_2_2_2_2(fixnum value); void store_value_2_2_2_2(fixnum value);
void store_value_masked(fixnum value, cell mask, cell shift); void store_value_masked(fixnum value, cell mask, cell shift);
void store_value(fixnum value); void store_value(fixnum value);
void store_code_block(code_block *compiled); void store_code_block(code_block* compiled);
}; };
} }