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