diff options
| author | Root THC | 2026-02-24 12:42:47 +0000 |
|---|---|---|
| committer | Root THC | 2026-02-24 12:42:47 +0000 |
| commit | c9cbeced5b3f2bdd7407e29c0811e65954132540 (patch) | |
| tree | aefc355416b561111819de159ccbd86c3004cf88 /other/burneye2/codegen.c | |
| parent | 073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff) | |
initial
Diffstat (limited to 'other/burneye2/codegen.c')
| -rw-r--r-- | other/burneye2/codegen.c | 512 |
1 files changed, 512 insertions, 0 deletions
diff --git a/other/burneye2/codegen.c b/other/burneye2/codegen.c new file mode 100644 index 0000000..be315c2 --- /dev/null +++ b/other/burneye2/codegen.c | |||
| @@ -0,0 +1,512 @@ | |||
| 1 | /* codegen.c - generic code generation functions | ||
| 2 | * | ||
| 3 | * by scut | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <assert.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <limits.h> | ||
| 10 | |||
| 11 | #include <common.h> | ||
| 12 | #include <utility.h> | ||
| 13 | |||
| 14 | #include <ia32/ia32_opcodes.h> | ||
| 15 | #include <ia32/ia32-decode.h> | ||
| 16 | #include <ia32/ia32-function.h> | ||
| 17 | #include <ia32/ia32-dataflow.h> | ||
| 18 | #include <codegen.h> | ||
| 19 | #include <objwriter.h> | ||
| 20 | |||
| 21 | #define CODEGEN_MAX_INST_TRIES 256 | ||
| 22 | |||
| 23 | /* from ia32-decode.c */ | ||
| 24 | extern ia32_opcode_e ia32_opcode_table[]; | ||
| 25 | extern char * ia32_regs_wide[]; | ||
| 26 | |||
| 27 | |||
| 28 | /*** GLOBALS */ | ||
| 29 | |||
| 30 | unsigned int codegen_operands[] = { | ||
| 31 | IA32_OP_aaa, IA32_OP_aad, IA32_OP_aam, IA32_OP_aas, | ||
| 32 | IA32_OP_adc, IA32_OP_add, IA32_OP_and, IA32_OP_bsf, IA32_OP_bsr, | ||
| 33 | IA32_OP_bswap, IA32_OP_bt, IA32_OP_btc, IA32_OP_bts, IA32_OP_cbw, | ||
| 34 | IA32_OP_daa, IA32_OP_das, IA32_OP_dec, IA32_OP_imul, IA32_OP_inc, | ||
| 35 | /* IA32_OP_lea, */ IA32_OP_mov, IA32_OP_neg, | ||
| 36 | /* IA32_OP_nop, */ IA32_OP_not, IA32_OP_or, IA32_OP_rcl1, IA32_OP_rcr1, | ||
| 37 | IA32_OP_sbb, IA32_OP_sub, IA32_OP_test, IA32_OP_xadd, IA32_OP_xchg, | ||
| 38 | IA32_OP_xor, 0 }; | ||
| 39 | |||
| 40 | unsigned int codegen_operands_length = | ||
| 41 | (sizeof (codegen_operands) / sizeof (unsigned int)) - 1; | ||
| 42 | |||
| 43 | double * codegen_operands_prob = NULL; | ||
| 44 | unsigned int codegen_operands_prob_count; | ||
| 45 | |||
| 46 | |||
| 47 | /*** IMPLEMENTATION */ | ||
| 48 | |||
| 49 | void | ||
| 50 | codegen_operands_prob_build (instuse_profile *iprof) | ||
| 51 | { | ||
| 52 | unsigned int cgn; | ||
| 53 | |||
| 54 | if (codegen_operands_prob != NULL) | ||
| 55 | return; | ||
| 56 | |||
| 57 | codegen_operands_prob = xcalloc (codegen_operands_length, | ||
| 58 | sizeof (double)); | ||
| 59 | codegen_operands_prob_count = codegen_operands_length; | ||
| 60 | |||
| 61 | for (cgn = 0 ; codegen_operands[cgn] != 0 ; ++cgn) { | ||
| 62 | codegen_operands_prob[cgn] = | ||
| 63 | iprof->inst_use[ia32_opnum_index (codegen_operands[cgn])]; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | |||
| 68 | ia32_instruction * | ||
| 69 | codegen_generate_instruction (unsigned int opcode, unsigned int used_mask, | ||
| 70 | ia32_instruction *place, int source_clobbered, reguse_profile *prof) | ||
| 71 | { | ||
| 72 | int imm_source; | ||
| 73 | |||
| 74 | memset (place, 0x00, sizeof (ia32_instruction)); | ||
| 75 | |||
| 76 | place->opc.used = OP_SOURCE | OP_TARGET; | ||
| 77 | place->opc.wide = 1; | ||
| 78 | |||
| 79 | place->opc.source_reg = place->opc.target_reg = 0; | ||
| 80 | |||
| 81 | place->opc.target_width = IA32_WIDTH_32; | ||
| 82 | place->opc.target_type = OP_TYPE_REG; | ||
| 83 | place->opc.target_reg = codegen_getreg (used_mask, 1, prof, -1); | ||
| 84 | |||
| 85 | imm_source = be_random_coin (0.5); | ||
| 86 | if (imm_source && ia32_opcode_has_immediate (opcode, | ||
| 87 | IA32_WIDTH_32, IA32_WIDTH_32)) | ||
| 88 | { | ||
| 89 | place->opc.imm_size = IA32_WIDTH_32; | ||
| 90 | place->opc.imm_value = be_random (UINT_MAX); | ||
| 91 | place->opc.source_type = OP_TYPE_IMM; | ||
| 92 | |||
| 93 | place->opc.source_reg = place->opc.target_reg; | ||
| 94 | } else { | ||
| 95 | place->opc.source_width = IA32_WIDTH_32; | ||
| 96 | place->opc.source_type = OP_TYPE_REG; | ||
| 97 | |||
| 98 | place->opc.source_reg = codegen_getreg (used_mask, | ||
| 99 | source_clobbered, prof, place->opc.target_reg); | ||
| 100 | } | ||
| 101 | |||
| 102 | /* hardwire to EAX in case its the only possible way (aaa, aam, aas, | ||
| 103 | * das, ..) instructions | ||
| 104 | */ | ||
| 105 | if (ia32_instruction_count (opcode) == 1) { | ||
| 106 | ia32_opcode_e * opc = ia32_opcode_find_bynum (opcode); | ||
| 107 | assert (opc != NULL); | ||
| 108 | |||
| 109 | if (OD_TEST (opc->flags, OD_REG_HARD_EAX)) | ||
| 110 | place->opc.target_reg = IA32_REG_EAX; | ||
| 111 | |||
| 112 | if ((1 << IA32_REG_EAX) & used_mask) | ||
| 113 | return (NULL); | ||
| 114 | } | ||
| 115 | |||
| 116 | if (place->opc.source_reg == -1 || place->opc.target_reg == -1) | ||
| 117 | return (NULL); | ||
| 118 | |||
| 119 | return (place); | ||
| 120 | } | ||
| 121 | |||
| 122 | |||
| 123 | /* this code is a bit messy | ||
| 124 | */ | ||
| 125 | |||
| 126 | int | ||
| 127 | codegen_getreg (unsigned int used_mask, int clobber, reguse_profile *prof, | ||
| 128 | int reg_avoid) | ||
| 129 | { | ||
| 130 | int reg_order[] = { | ||
| 131 | IA32_REG_EAX, IA32_REG_EDX, IA32_REG_EBX, IA32_REG_ECX, | ||
| 132 | IA32_REG_ESI, IA32_REG_EDI, IA32_REG_EBP, IA32_REG_ESP, -1 }; | ||
| 133 | unsigned int regmask = IA32_DF_GET_REG_MASK (used_mask), | ||
| 134 | reg_idx, | ||
| 135 | prob_tries; | ||
| 136 | double prof_sum; | ||
| 137 | double reg_use[IA32_REG_COUNT]; | ||
| 138 | int reg_tried[IA32_REG_COUNT], | ||
| 139 | reg_tried_count = 0; | ||
| 140 | |||
| 141 | |||
| 142 | /* do register picking based on probabilities | ||
| 143 | */ | ||
| 144 | if (prof != NULL) { | ||
| 145 | reg_tried_count = 0; | ||
| 146 | memset (reg_tried, 0x00, sizeof (reg_tried)); | ||
| 147 | |||
| 148 | /* for completely unused registers, at least put some basic | ||
| 149 | * chance in. | ||
| 150 | */ | ||
| 151 | prof_sum = prof->sum; | ||
| 152 | memcpy (reg_use, prof->reg_use, sizeof (reg_use)); | ||
| 153 | for (reg_idx = 0 ; reg_idx < IA32_REG_COUNT ; ++reg_idx) { | ||
| 154 | if (reg_use[reg_idx] == 0.0) { | ||
| 155 | reg_use[reg_idx] = 0.10; | ||
| 156 | prof_sum += 0.10; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | for (prob_tries = 0 ; | ||
| 162 | prof != NULL && reg_tried_count < IA32_REG_COUNT && | ||
| 163 | prob_tries < 64 ; ++prob_tries) | ||
| 164 | { | ||
| 165 | reg_idx = be_random_prob (IA32_REG_COUNT, reg_use); | ||
| 166 | |||
| 167 | if (reg_avoid >= 0 && prob_tries == (64 - 1)) | ||
| 168 | reg_idx = reg_avoid; | ||
| 169 | |||
| 170 | if (reg_tried[reg_idx]) | ||
| 171 | continue; | ||
| 172 | |||
| 173 | if (reg_avoid < 0 || reg_idx != reg_avoid) { | ||
| 174 | reg_tried[reg_idx] = 1; | ||
| 175 | reg_tried_count += 1; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* try to avoid a register if desired and at all possible | ||
| 179 | */ | ||
| 180 | if (prob_tries < (64 - 1) && reg_avoid >= 0 && | ||
| 181 | reg_idx == reg_avoid) | ||
| 182 | continue; | ||
| 183 | |||
| 184 | if (clobber && (((1 << reg_idx) & regmask) == 0)) | ||
| 185 | return (reg_idx); | ||
| 186 | |||
| 187 | if (clobber == 0 && ((1 << reg_idx) & regmask)) | ||
| 188 | return (reg_idx); | ||
| 189 | } | ||
| 190 | |||
| 191 | /* do the register picking based on fixed order | ||
| 192 | */ | ||
| 193 | for (reg_idx = 0 ; reg_order[reg_idx] != -1 ; ++reg_idx) { | ||
| 194 | if (reg_avoid >= 0 && reg_idx == reg_avoid) | ||
| 195 | continue; | ||
| 196 | |||
| 197 | if (clobber && (((1 << reg_order[reg_idx]) & regmask) == 0)) | ||
| 198 | return (reg_order[reg_idx]); | ||
| 199 | |||
| 200 | if (clobber == 0 && ((1 << reg_order[reg_idx]) & regmask)) | ||
| 201 | return (reg_order[reg_idx]); | ||
| 202 | } | ||
| 203 | |||
| 204 | /* fallback: if there is no used register, select eax | ||
| 205 | */ | ||
| 206 | if (clobber == 0) | ||
| 207 | return (IA32_REG_EAX); | ||
| 208 | |||
| 209 | return (-1); | ||
| 210 | } | ||
| 211 | |||
| 212 | |||
| 213 | unsigned int | ||
| 214 | codegen_generate_operation (unsigned int used_mask, int *source_clobbered, | ||
| 215 | instuse_profile *iprof) | ||
| 216 | { | ||
| 217 | unsigned int efl_used = IA32_DF_GET_FLAGS (used_mask), | ||
| 218 | efl_def, | ||
| 219 | reg_used = IA32_DF_GET_REG_MASK (used_mask), | ||
| 220 | reg_def; | ||
| 221 | unsigned int oper, | ||
| 222 | in, | ||
| 223 | inst_tries = 0; | ||
| 224 | ia32_opcode_e * oel; | ||
| 225 | |||
| 226 | |||
| 227 | if (iprof != NULL) | ||
| 228 | codegen_operands_prob_build (iprof); | ||
| 229 | |||
| 230 | do { | ||
| 231 | loop_cont: | ||
| 232 | if (inst_tries >= CODEGEN_MAX_INST_TRIES) | ||
| 233 | break; | ||
| 234 | |||
| 235 | oel = NULL; | ||
| 236 | if (iprof != NULL) { | ||
| 237 | oper = codegen_operands[be_random_prob | ||
| 238 | (codegen_operands_prob_count, | ||
| 239 | codegen_operands_prob)]; | ||
| 240 | } else { | ||
| 241 | oper = codegen_operands[be_random | ||
| 242 | (codegen_operands_length)]; | ||
| 243 | } | ||
| 244 | |||
| 245 | for (in = 0 ; ia32_opcode_table[in].opcode_num != 0 ; ++in) { | ||
| 246 | oel = NULL; | ||
| 247 | if (ia32_opcode_table[in].opcode_num != oper) | ||
| 248 | continue; | ||
| 249 | |||
| 250 | oel = &ia32_opcode_table[in]; | ||
| 251 | |||
| 252 | /* in case registers get clobbered, try next encoding | ||
| 253 | */ | ||
| 254 | reg_def = IA32_DF_DEF_REGMASK (oel->df_implicit_def); | ||
| 255 | if ((reg_def & reg_used) != 0) { | ||
| 256 | #ifdef CODEGEN_DEBUG | ||
| 257 | printf ("skipping \"%s\" due to: " | ||
| 258 | "d:0x%02x & u:0x%02x\n", | ||
| 259 | oel->name, reg_def, reg_used); | ||
| 260 | #endif | ||
| 261 | oel = NULL; | ||
| 262 | continue; | ||
| 263 | } | ||
| 264 | if (OD_TEST (oel->df_srctgt, IA32_DF_DEF_SOURCE)) | ||
| 265 | *source_clobbered = 1; | ||
| 266 | else | ||
| 267 | *source_clobbered = 0; | ||
| 268 | |||
| 269 | if (OD_TEST (oel->flags, OD_REG_HARD_EAX) && | ||
| 270 | (reg_used & IA32_REG_EAX)) | ||
| 271 | { | ||
| 272 | #ifdef CODEGEN_DEBUG | ||
| 273 | printf ("skipping \"%s\" due to eax " | ||
| 274 | "clobber\n", oel->name); | ||
| 275 | #endif | ||
| 276 | oel = NULL; | ||
| 277 | continue; | ||
| 278 | } | ||
| 279 | |||
| 280 | break; | ||
| 281 | } | ||
| 282 | |||
| 283 | /* no encoding found, continue search for proper opcode | ||
| 284 | */ | ||
| 285 | inst_tries += 1; | ||
| 286 | |||
| 287 | if (oel == NULL) | ||
| 288 | goto loop_cont; | ||
| 289 | |||
| 290 | efl_def = IA32_DF_DEF_GET_FLAGS (oel->df_implicit_def); | ||
| 291 | } while ((efl_def & efl_used) != 0); | ||
| 292 | |||
| 293 | if (inst_tries >= CODEGEN_MAX_INST_TRIES) | ||
| 294 | oper = IA32_OP_nop; | ||
| 295 | |||
| 296 | #ifdef CODEGEN_DEBUG | ||
| 297 | printf (" == choosing \"%s\"\n", oel->name); | ||
| 298 | #endif | ||
| 299 | |||
| 300 | return (oper); | ||
| 301 | } | ||
| 302 | |||
| 303 | |||
| 304 | void | ||
| 305 | codegen_reguse_profile_print (reguse_profile *prof) | ||
| 306 | { | ||
| 307 | unsigned int rn; /* register walker */ | ||
| 308 | |||
| 309 | printf ("register usage profile\n\n"); | ||
| 310 | printf (" reg | percentage\n" | ||
| 311 | "-----+-------------\n"); | ||
| 312 | for (rn = 0 ; rn < IA32_REG_COUNT ; ++rn) { | ||
| 313 | printf (" %s | %6.2lf\n", ia32_regs_wide[rn], | ||
| 314 | 100.0 * prof->reg_use[rn]); | ||
| 315 | } | ||
| 316 | |||
| 317 | printf ("-----+-------------\n" | ||
| 318 | " sum | %6.2lf, made up from %u instructions\n", | ||
| 319 | 100.0 * prof->sum, prof->lines); | ||
| 320 | printf (" '\n"); | ||
| 321 | } | ||
| 322 | |||
| 323 | |||
| 324 | reguse_profile * | ||
| 325 | codegen_reguse_profile_create (ia32_function **flist, unsigned int flist_count) | ||
| 326 | { | ||
| 327 | ia32_bblock ** all; | ||
| 328 | unsigned int all_count, | ||
| 329 | bn, /* basic block walker */ | ||
| 330 | in, /* instruction walker */ | ||
| 331 | bitn; /* use bit test walker */ | ||
| 332 | ia32_df_bblock * dfb; | ||
| 333 | reguse_profile * prof; | ||
| 334 | |||
| 335 | |||
| 336 | all = obj_bblist_build (flist, flist_count, &all_count); | ||
| 337 | assert (all != NULL); | ||
| 338 | |||
| 339 | prof = xcalloc (1, sizeof (reguse_profile)); | ||
| 340 | |||
| 341 | for (bn = 0 ; bn < all_count ; ++bn) { | ||
| 342 | assert (all[bn]->user != NULL && all[bn]->user->dfb != NULL); | ||
| 343 | dfb = (ia32_df_bblock *) all[bn]->user->dfb; | ||
| 344 | |||
| 345 | for (in = 0 ; in < dfb->df_count ; ++in) { | ||
| 346 | for (bitn = 0 ; bitn < IA32_REG_COUNT ; ++bitn) { | ||
| 347 | if (dfb->df[in].use & (1 << bitn)) | ||
| 348 | prof->reg_use[bitn] += 1; | ||
| 349 | } | ||
| 350 | prof->lines += 1; | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | assert (prof->lines > 0); | ||
| 355 | for (bitn = 0 ; bitn < IA32_REG_COUNT ; ++bitn) | ||
| 356 | prof->reg_use[bitn] /= (double) prof->lines; | ||
| 357 | |||
| 358 | prof->sum = 0.0; | ||
| 359 | for (bitn = 0 ; bitn < IA32_REG_COUNT ; ++bitn) | ||
| 360 | prof->sum += prof->reg_use[bitn]; | ||
| 361 | |||
| 362 | free (all); | ||
| 363 | return (prof); | ||
| 364 | } | ||
| 365 | |||
| 366 | |||
| 367 | void | ||
| 368 | codegen_instuse_profile_print (instuse_profile *iprof, int machine) | ||
| 369 | { | ||
| 370 | unsigned int on; | ||
| 371 | |||
| 372 | |||
| 373 | if (machine == 0) { | ||
| 374 | printf ("instruction usage profile\n\n"); | ||
| 375 | printf (" pct | abs | mnemonic\n" | ||
| 376 | "--------+--------+---------------------------------\n"); | ||
| 377 | } | ||
| 378 | |||
| 379 | for (on = 0 ; on < IA32_OPNUM_COUNT ; ++on) { | ||
| 380 | if (iprof->inst_use[on] == 0.0) | ||
| 381 | continue; | ||
| 382 | |||
| 383 | if (machine) { | ||
| 384 | printf ("%s,%lf # INSTUSE\n", ia32_opnum_name (on), | ||
| 385 | iprof->inst_use[on] * 100.0); | ||
| 386 | } else { | ||
| 387 | printf (" %6.2lf | %6.0lf | %s\n", | ||
| 388 | iprof->inst_use[on] * 100.0, | ||
| 389 | (double) (iprof->inst_use[on] * iprof->lines), | ||
| 390 | ia32_opnum_name (on)); | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | if (machine == 0) { | ||
| 395 | printf ("--------+--------+---------------------------------\n" | ||
| 396 | " | %6u instructions considered\n" | ||
| 397 | " '\n", iprof->lines); | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 401 | |||
| 402 | instuse_profile * | ||
| 403 | codegen_instuse_profile_create (ia32_function **flist, unsigned int flist_count) | ||
| 404 | { | ||
| 405 | ia32_bblock ** all; | ||
| 406 | unsigned int all_count, | ||
| 407 | bn, | ||
| 408 | on; /* opcode number walker */ | ||
| 409 | unsigned int mwlk; | ||
| 410 | int idx; | ||
| 411 | instuse_profile * iuse; | ||
| 412 | ia32_instruction * inst, | ||
| 413 | inst_s; | ||
| 414 | |||
| 415 | |||
| 416 | all = obj_bblist_build (flist, flist_count, &all_count); | ||
| 417 | assert (all != NULL); | ||
| 418 | iuse = xcalloc (1, sizeof (instuse_profile)); | ||
| 419 | |||
| 420 | for (bn = 0 ; bn < all_count ; ++bn) { | ||
| 421 | mwlk = 0; | ||
| 422 | |||
| 423 | while (mwlk < (all[bn]->end - all[bn]->start)) { | ||
| 424 | inst = ia32_decode_instruction (&all[bn]->mem[mwlk], | ||
| 425 | &inst_s); | ||
| 426 | assert (inst != NULL); | ||
| 427 | |||
| 428 | idx = ia32_opnum_index (inst->opc.opcode->opcode_num); | ||
| 429 | assert (idx != -1); | ||
| 430 | iuse->inst_use[idx] += 1.0; | ||
| 431 | iuse->lines += 1; | ||
| 432 | |||
| 433 | mwlk += inst->length; | ||
| 434 | } | ||
| 435 | } | ||
| 436 | free (all); | ||
| 437 | |||
| 438 | for (on = 0 ; on < IA32_OPNUM_COUNT ; ++on) | ||
| 439 | iuse->inst_use[on] /= (double) iuse->lines; | ||
| 440 | |||
| 441 | return (iuse); | ||
| 442 | } | ||
| 443 | |||
| 444 | |||
| 445 | instr_array * | ||
| 446 | codegen_instr_array_copy (instr_array *ia) | ||
| 447 | { | ||
| 448 | instr_array * new; | ||
| 449 | |||
| 450 | if (ia == NULL) | ||
| 451 | return (NULL); | ||
| 452 | |||
| 453 | new = xcalloc (1, sizeof (instr_array)); | ||
| 454 | new->in_count = ia->in_count; | ||
| 455 | |||
| 456 | new->in_points = xcalloc (new->in_count, sizeof (ia32_instruction *)); | ||
| 457 | memcpy (new->in_points, ia->in_points, | ||
| 458 | new->in_count * sizeof (ia32_instruction *)); | ||
| 459 | |||
| 460 | new->in_points_opcode = xcalloc (new->in_count, | ||
| 461 | sizeof (unsigned int *)); | ||
| 462 | memcpy (new->in_points_opcode, ia->in_points_opcode, | ||
| 463 | new->in_count * sizeof (unsigned int *)); | ||
| 464 | |||
| 465 | new->in_points_icount = xcalloc (new->in_count, sizeof (unsigned int)); | ||
| 466 | memcpy (new->in_points_icount, ia->in_points_icount, | ||
| 467 | new->in_count * sizeof (unsigned int)); | ||
| 468 | |||
| 469 | return (new); | ||
| 470 | } | ||
| 471 | |||
| 472 | |||
| 473 | instr_array * | ||
| 474 | codegen_instr_array_split (instr_array *ia, unsigned int split_point) | ||
| 475 | { | ||
| 476 | instr_array * new; | ||
| 477 | |||
| 478 | if (ia == NULL) | ||
| 479 | return (NULL); | ||
| 480 | |||
| 481 | assert (split_point <= ia->in_count); | ||
| 482 | |||
| 483 | new = xcalloc (1, sizeof (instr_array)); | ||
| 484 | new->in_count = ia->in_count - split_point; | ||
| 485 | |||
| 486 | /* duplicate data, using duplicate code ;-) | ||
| 487 | */ | ||
| 488 | new->in_points = xcalloc (new->in_count, sizeof (ia32_instruction *)); | ||
| 489 | memcpy (new->in_points, &ia->in_points[split_point], | ||
| 490 | new->in_count * sizeof (ia32_instruction *)); | ||
| 491 | |||
| 492 | new->in_points_opcode = xcalloc (new->in_count, | ||
| 493 | sizeof (unsigned int *)); | ||
| 494 | memcpy (new->in_points_opcode, &ia->in_points_opcode[split_point], | ||
| 495 | new->in_count * sizeof (unsigned int *)); | ||
| 496 | |||
| 497 | new->in_points_icount = xcalloc (new->in_count, sizeof (unsigned int)); | ||
| 498 | memcpy (new->in_points_icount, &ia->in_points_icount[split_point], | ||
| 499 | new->in_count * sizeof (unsigned int)); | ||
| 500 | |||
| 501 | ia->in_count -= new->in_count; | ||
| 502 | ia->in_points = xrealloc (ia->in_points, | ||
| 503 | ia->in_count * sizeof (ia32_instruction *)); | ||
| 504 | ia->in_points_opcode = xrealloc (ia->in_points_opcode, | ||
| 505 | ia->in_count * sizeof (unsigned int *)); | ||
| 506 | ia->in_points_icount = xrealloc (ia->in_points_icount, | ||
| 507 | ia->in_count * sizeof (unsigned int)); | ||
| 508 | |||
| 509 | return (new); | ||
| 510 | } | ||
| 511 | |||
| 512 | |||
