code-patching.c (053a858efa46c9ab86363b271374ec02ad2af753) | code-patching.c (411781a290b0d0a31fd73826b3ee110f1e3cc3b6) |
---|---|
1/* 2 * Copyright 2008 Michael Ellerman, IBM Corporation. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 */ --- 27 unchanged lines hidden (view full) --- 36 if (offset < -0x2000000 || offset > 0x1fffffc || offset & 0x3) 37 return 0; 38 39 /* Mask out the flags and target, so they don't step on each other. */ 40 instruction = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC); 41 42 return instruction; 43} | 1/* 2 * Copyright 2008 Michael Ellerman, IBM Corporation. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 */ --- 27 unchanged lines hidden (view full) --- 36 if (offset < -0x2000000 || offset > 0x1fffffc || offset & 0x3) 37 return 0; 38 39 /* Mask out the flags and target, so they don't step on each other. */ 40 instruction = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC); 41 42 return instruction; 43} |
44 45unsigned int create_cond_branch(const unsigned int *addr, 46 unsigned long target, int flags) 47{ 48 unsigned int instruction; 49 long offset; 50 51 offset = target; 52 if (! (flags & BRANCH_ABSOLUTE)) 53 offset = offset - (unsigned long)addr; 54 55 /* Check we can represent the target in the instruction format */ 56 if (offset < -0x8000 || offset > 0x7FFF || offset & 0x3) 57 return 0; 58 59 /* Mask out the flags and target, so they don't step on each other. */ 60 instruction = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC); 61 62 return instruction; 63} 64 65static unsigned int branch_opcode(unsigned int instr) 66{ 67 return (instr >> 26) & 0x3F; 68} 69 70static int instr_is_branch_iform(unsigned int instr) 71{ 72 return branch_opcode(instr) == 18; 73} 74 75static int instr_is_branch_bform(unsigned int instr) 76{ 77 return branch_opcode(instr) == 16; 78} 79 80int instr_is_relative_branch(unsigned int instr) 81{ 82 if (instr & BRANCH_ABSOLUTE) 83 return 0; 84 85 return instr_is_branch_iform(instr) || instr_is_branch_bform(instr); 86} 87 88static unsigned long branch_iform_target(const unsigned int *instr) 89{ 90 signed long imm; 91 92 imm = *instr & 0x3FFFFFC; 93 94 /* If the top bit of the immediate value is set this is negative */ 95 if (imm & 0x2000000) 96 imm -= 0x4000000; 97 98 if ((*instr & BRANCH_ABSOLUTE) == 0) 99 imm += (unsigned long)instr; 100 101 return (unsigned long)imm; 102} 103 104static unsigned long branch_bform_target(const unsigned int *instr) 105{ 106 signed long imm; 107 108 imm = *instr & 0xFFFC; 109 110 /* If the top bit of the immediate value is set this is negative */ 111 if (imm & 0x8000) 112 imm -= 0x10000; 113 114 if ((*instr & BRANCH_ABSOLUTE) == 0) 115 imm += (unsigned long)instr; 116 117 return (unsigned long)imm; 118} 119 120unsigned long branch_target(const unsigned int *instr) 121{ 122 if (instr_is_branch_iform(*instr)) 123 return branch_iform_target(instr); 124 else if (instr_is_branch_bform(*instr)) 125 return branch_bform_target(instr); 126 127 return 0; 128} 129 130int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr) 131{ 132 if (instr_is_branch_iform(*instr) || instr_is_branch_bform(*instr)) 133 return branch_target(instr) == addr; 134 135 return 0; 136} 137 138unsigned int translate_branch(const unsigned int *dest, const unsigned int *src) 139{ 140 unsigned long target; 141 142 target = branch_target(src); 143 144 if (instr_is_branch_iform(*src)) 145 return create_branch(dest, target, *src); 146 else if (instr_is_branch_bform(*src)) 147 return create_cond_branch(dest, target, *src); 148 149 return 0; 150} |
|