Skip to content

Instantly share code, notes, and snippets.

@mithro
Last active April 11, 2017 03:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mithro/6a95b5506367463af1685f3c13c725af to your computer and use it in GitHub Desktop.
Save mithro/6a95b5506367463af1685f3c13c725af to your computer and use it in GitHub Desktop.
Code for dynamically patching or1k l.j functions....
/*
* l.j instruction is opcode 0 and does a
* PC ← exts(Immediate << 2) + JumpInsnAddr
*/
// Top 6 bits is the op code
#define OPENRISC_OPCODE_MASK 0xfc000000 // Top 6 bits
#define OPENRISC_OPCODE_J 0x0 << 26
#define OPENRISC_OPCODE_BNF 0x3 << 26
#define OPENRISC_OPCODE_BF 0x4 << 26
static void __patch_reljump_instruction(unsigned int opcode, void* instruction_ptr, void* memory_location)
{
// Make sure the existing instruction is a jump
unsigned int existing_instruction = (unsigned int)*instruction_ptr;
assert((existing_instruction & OPENRISC_OPCODE_MASK) == opcode);
// Work out the distance to jump
unsigned int jump_from_addr = (unsigned int)instruction_ptr;
unsigned int jump_to_addr = (unsigned int)memory_location;
unsigned int jump_delta = jump_to - jump_from;
// Check the jump_delta fits into the instruction "N" bits.
assert((jump_delta >> 2) < (2**26));
*instruction_ptr = opcode | (jump_delta >> 2);
}
#define patch_lj_instruction(instruction_ptr, memory_location) \
__patch_reljump_instruction(OPENRISC_OPCODE_J, instruction_ptr, memory_location)
#define patch_lbf_instruction(instruction_ptr, memory_location) \
__patch_reljump_instruction(OPENRISC_OPCODE_BF, instruction_ptr, memory_location)
#define patch_lbnf_instruction(instruction_ptr, memory_location) \
__patch_reljump_instruction(OPENRISC_OPCODE_BNF, instruction_ptr, memory_location)
static void* extract_jump_location(void* jump_instruction)
{
unsigned int jump_instruction = *((unsigned int*)(jump_instruction));
assert((jump_instruction | OPENRISC_OPCODE) == OPENRISC_OPCODE_J);
unsigned int jump_delta = (~OPENRISC_OPCODE & jump_instruction) << 2;
return jump_instruction + jump_delta;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment