274 |
{ |
{ |
275 |
int copy_size = 0; |
int copy_size = 0; |
276 |
uint8_t *p_start, *p_end; |
uint8_t *p_start, *p_end; |
277 |
|
host_ulong start_offset; |
278 |
int nb_args, i, n; |
int nb_args, i, n; |
279 |
uint8_t args_present[MAX_ARGS]; |
uint8_t args_present[MAX_ARGS]; |
280 |
const char *sym_name, *p; |
const char *sym_name, *p; |
281 |
ELF_RELOC *rel; |
ELF_RELOC *rel; |
282 |
|
|
283 |
/* compute exact size excluding return instruction */ |
/* Compute exact size excluding prologue and epilogue instructions. |
284 |
|
* Increment start_offset to skip epilogue instructions, then compute |
285 |
|
* copy_size the indicate the size of the remaining instructions (in |
286 |
|
* bytes). |
287 |
|
*/ |
288 |
p_start = text + offset; |
p_start = text + offset; |
289 |
p_end = p_start + size; |
p_end = p_start + size; |
290 |
|
start_offset = offset; |
291 |
switch(ELF_ARCH) { |
switch(ELF_ARCH) { |
292 |
case EM_386: |
case EM_386: |
293 |
{ |
{ |
349 |
case EM_SPARC: |
case EM_SPARC: |
350 |
case EM_SPARC32PLUS: |
case EM_SPARC32PLUS: |
351 |
{ |
{ |
352 |
|
uint32_t start_insn, end_insn1, end_insn2, skip_insn; |
353 |
uint8_t *p; |
uint8_t *p; |
354 |
p = (void *)(p_end - 8); |
p = (void *)(p_end - 8); |
355 |
if (p <= p_start) |
if (p <= p_start) |
356 |
error("empty code for %s", name); |
error("empty code for %s", name); |
357 |
if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf98) |
start_insn = get32((uint32_t *)(p_start + 0x0)); |
358 |
error("save %%sp,-104,%%sp expected at the start of %s " |
end_insn1 = get32((uint32_t *)(p + 0x0)); |
359 |
"found [%08x]", |
end_insn2 = get32((uint32_t *)(p + 0x4)); |
360 |
name, get32((uint32_t *)(p_start + 0x0))); |
if ((start_insn & ~0x1fff) == 0x9de3a000) { |
361 |
if (get32((uint32_t *)(p + 0x0)) != 0x81c7e008 || |
p_start += 0x4; |
362 |
get32((uint32_t *)(p + 0x4)) != 0x81e80000) |
start_offset += 0x4; |
363 |
error("ret; restore; expected at the end of %s found [%08x:%08x]", |
if ((int)(start_insn | ~0x1fff) < -128) |
364 |
name, |
error("Found bogus save at the start of %s", name); |
365 |
get32((uint32_t *)(p + 0x0)), |
if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000) |
366 |
get32((uint32_t *)(p + 0x4))); |
error("ret; restore; not found at end of %s", name); |
367 |
|
} else { |
368 |
|
error("No save at the beginning of %s", name); |
369 |
|
} |
370 |
|
|
371 |
|
/* Skip a preceeding nop, if present. */ |
372 |
|
if (p > p_start) { |
373 |
|
skip_insn = get32((uint32_t *)(p - 0x4)); |
374 |
|
if (skip_insn == 0x01000000) |
375 |
|
p -= 4; |
376 |
|
} |
377 |
|
|
378 |
copy_size = p - p_start; |
copy_size = p - p_start; |
379 |
} |
} |
380 |
break; |
break; |
381 |
case EM_SPARCV9: |
case EM_SPARCV9: |
382 |
{ |
{ |
383 |
|
uint32_t start_insn, end_insn1, end_insn2, skip_insn; |
384 |
uint8_t *p; |
uint8_t *p; |
385 |
p = (void *)(p_end - 8); |
p = (void *)(p_end - 8); |
386 |
if (p <= p_start) |
if (p <= p_start) |
387 |
error("empty code for %s", name); |
error("empty code for %s", name); |
388 |
if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf40) |
start_insn = get32((uint32_t *)(p_start + 0x0)); |
389 |
error("save %%sp,-192,%%sp expected at the start of %s " |
end_insn1 = get32((uint32_t *)(p + 0x0)); |
390 |
"found [%08x]", |
end_insn2 = get32((uint32_t *)(p + 0x4)); |
391 |
name, get32((uint32_t *)(p_start + 0x0))); |
if ((start_insn & ~0x1fff) == 0x9de3a000) { |
392 |
if (get32((uint32_t *)(p + 0x0)) != 0x81cfe008 || |
p_start += 0x4; |
393 |
get32((uint32_t *)(p + 0x4)) != 0x01000000) |
start_offset += 0x4; |
394 |
error("rett %%i7+8; nop; expected at the end of %s " |
if ((int)(start_insn | ~0x1fff) < -256) |
395 |
"found [%08x:%08x]", |
error("Found bogus save at the start of %s", name); |
396 |
name, |
if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000) |
397 |
get32((uint32_t *)(p + 0x0)), |
error("ret; restore; not found at end of %s", name); |
398 |
get32((uint32_t *)(p + 0x4))); |
} else { |
399 |
|
error("No save at the beginning of %s", name); |
400 |
|
} |
401 |
|
|
402 |
|
/* Skip a preceeding nop, if present. */ |
403 |
|
if (p > p_start) { |
404 |
|
skip_insn = get32((uint32_t *)(p - 0x4)); |
405 |
|
if (skip_insn == 0x01000000) |
406 |
|
p -= 4; |
407 |
|
} |
408 |
|
|
409 |
copy_size = p - p_start; |
copy_size = p - p_start; |
410 |
} |
} |
411 |
break; |
break; |
418 |
args_present[i] = 0; |
args_present[i] = 0; |
419 |
|
|
420 |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
421 |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
if (rel->r_offset >= start_offset && |
422 |
|
rel->r_offset < start_offset + copy_size) { |
423 |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
424 |
if (strstart(sym_name, "__op_param", &p)) { |
if (strstart(sym_name, "__op_param", &p)) { |
425 |
n = strtoul(p, NULL, 10); |
n = strtoul(p, NULL, 10); |
456 |
fprintf(outfile, " extern void %s();\n", name); |
fprintf(outfile, " extern void %s();\n", name); |
457 |
|
|
458 |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
459 |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
if (rel->r_offset >= start_offset && |
460 |
|
rel->r_offset < start_offset + copy_size) { |
461 |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
462 |
if (*sym_name && !strstart(sym_name, "__op_param", &p)) { |
if (*sym_name && !strstart(sym_name, "__op_param", &p)) { |
463 |
#if defined(HOST_SPARC) |
#if defined(HOST_SPARC) |
473 |
} |
} |
474 |
} |
} |
475 |
|
|
476 |
fprintf(outfile, " memcpy(gen_code_ptr, &%s, %d);\n", name, copy_size); |
fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n", name, start_offset - offset, copy_size); |
477 |
for(i = 0; i < nb_args; i++) { |
for(i = 0; i < nb_args; i++) { |
478 |
fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); |
fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); |
479 |
} |
} |
485 |
int type; |
int type; |
486 |
int addend; |
int addend; |
487 |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
488 |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
if (rel->r_offset >= start_offset && |
489 |
|
rel->r_offset < start_offset + copy_size) { |
490 |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
491 |
if (strstart(sym_name, "__op_param", &p)) { |
if (strstart(sym_name, "__op_param", &p)) { |
492 |
snprintf(name, sizeof(name), "param%s", p); |
snprintf(name, sizeof(name), "param%s", p); |
498 |
switch(type) { |
switch(type) { |
499 |
case R_386_32: |
case R_386_32: |
500 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
501 |
rel->r_offset - offset, name, addend); |
rel->r_offset - start_offset, name, addend); |
502 |
break; |
break; |
503 |
case R_386_PC32: |
case R_386_PC32: |
504 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", |
505 |
rel->r_offset - offset, name, rel->r_offset - offset, addend); |
rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend); |
506 |
break; |
break; |
507 |
default: |
default: |
508 |
error("unsupported i386 relocation (%d)", type); |
error("unsupported i386 relocation (%d)", type); |
516 |
int type; |
int type; |
517 |
int addend; |
int addend; |
518 |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
519 |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
if (rel->r_offset >= start_offset && |
520 |
|
rel->r_offset < start_offset + copy_size) { |
521 |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
522 |
if (strstart(sym_name, "__op_param", &p)) { |
if (strstart(sym_name, "__op_param", &p)) { |
523 |
snprintf(name, sizeof(name), "param%s", p); |
snprintf(name, sizeof(name), "param%s", p); |
529 |
switch(type) { |
switch(type) { |
530 |
case R_PPC_ADDR32: |
case R_PPC_ADDR32: |
531 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
532 |
rel->r_offset - offset, name, addend); |
rel->r_offset - start_offset, name, addend); |
533 |
break; |
break; |
534 |
case R_PPC_ADDR16_LO: |
case R_PPC_ADDR16_LO: |
535 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", |
536 |
rel->r_offset - offset, name, addend); |
rel->r_offset - start_offset, name, addend); |
537 |
break; |
break; |
538 |
case R_PPC_ADDR16_HI: |
case R_PPC_ADDR16_HI: |
539 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", |
540 |
rel->r_offset - offset, name, addend); |
rel->r_offset - start_offset, name, addend); |
541 |
break; |
break; |
542 |
case R_PPC_ADDR16_HA: |
case R_PPC_ADDR16_HA: |
543 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", |
544 |
rel->r_offset - offset, name, addend); |
rel->r_offset - start_offset, name, addend); |
545 |
break; |
break; |
546 |
case R_PPC_REL24: |
case R_PPC_REL24: |
547 |
/* warning: must be at 32 MB distancy */ |
/* warning: must be at 32 MB distancy */ |
548 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", |
549 |
rel->r_offset - offset, rel->r_offset - offset, name, rel->r_offset - offset, addend); |
rel->r_offset - start_offset, rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend); |
550 |
break; |
break; |
551 |
default: |
default: |
552 |
error("unsupported powerpc relocation (%d)", type); |
error("unsupported powerpc relocation (%d)", type); |
560 |
int type; |
int type; |
561 |
int addend; |
int addend; |
562 |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
563 |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
if (rel->r_offset >= start_offset && |
564 |
|
rel->r_offset < start_offset + copy_size) { |
565 |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
566 |
if (strstart(sym_name, "__op_param", &p)) { |
if (strstart(sym_name, "__op_param", &p)) { |
567 |
snprintf(name, sizeof(name), "param%s", p); |
snprintf(name, sizeof(name), "param%s", p); |
573 |
switch(type) { |
switch(type) { |
574 |
case R_390_32: |
case R_390_32: |
575 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
576 |
rel->r_offset - offset, name, addend); |
rel->r_offset - start_offset, name, addend); |
577 |
break; |
break; |
578 |
case R_390_16: |
case R_390_16: |
579 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", |
580 |
rel->r_offset - offset, name, addend); |
rel->r_offset - start_offset, name, addend); |
581 |
break; |
break; |
582 |
case R_390_8: |
case R_390_8: |
583 |
fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", |
fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", |
584 |
rel->r_offset - offset, name, addend); |
rel->r_offset - start_offset, name, addend); |
585 |
break; |
break; |
586 |
default: |
default: |
587 |
error("unsupported s390 relocation (%d)", type); |
error("unsupported s390 relocation (%d)", type); |
592 |
#elif defined(HOST_ALPHA) |
#elif defined(HOST_ALPHA) |
593 |
{ |
{ |
594 |
for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { |
for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { |
595 |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { |
596 |
int type; |
int type; |
597 |
|
|
598 |
type = ELF64_R_TYPE(rel->r_info); |
type = ELF64_R_TYPE(rel->r_info); |
602 |
/* The gp is just 32 bit, and never changes, so it's easiest to emit it |
/* The gp is just 32 bit, and never changes, so it's easiest to emit it |
603 |
as an immediate instead of constructing it from the pv or ra. */ |
as an immediate instead of constructing it from the pv or ra. */ |
604 |
fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n", |
fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n", |
605 |
rel->r_offset - offset); |
rel->r_offset - start_offset); |
606 |
fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n", |
fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n", |
607 |
rel->r_offset - offset + rel->r_addend); |
rel->r_offset - start_offset + rel->r_addend); |
608 |
break; |
break; |
609 |
case R_ALPHA_LITUSE: |
case R_ALPHA_LITUSE: |
610 |
/* jsr to literal hint. Could be used to optimize to bsr. Ignore for |
/* jsr to literal hint. Could be used to optimize to bsr. Ignore for |
624 |
special treatment. */ |
special treatment. */ |
625 |
if (strstart(sym_name, "__op_param", &p)) |
if (strstart(sym_name, "__op_param", &p)) |
626 |
fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n", |
fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n", |
627 |
rel->r_offset - offset, p); |
rel->r_offset - start_offset, p); |
628 |
break; |
break; |
629 |
case R_ALPHA_GPRELLOW: |
case R_ALPHA_GPRELLOW: |
630 |
if (strstart(sym_name, "__op_param", &p)) |
if (strstart(sym_name, "__op_param", &p)) |
631 |
fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n", |
fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n", |
632 |
rel->r_offset - offset, p); |
rel->r_offset - start_offset, p); |
633 |
break; |
break; |
634 |
case R_ALPHA_BRSGP: |
case R_ALPHA_BRSGP: |
635 |
/* PC-relative jump. Tweak offset to skip the two instructions that try to |
/* PC-relative jump. Tweak offset to skip the two instructions that try to |
636 |
set up the gp from the pv. */ |
set up the gp from the pv. */ |
637 |
fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld) + 4);\n", |
fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld) + 4);\n", |
638 |
rel->r_offset - offset, sym_name, rel->r_offset - offset); |
rel->r_offset - start_offset, sym_name, rel->r_offset - start_offset); |
639 |
break; |
break; |
640 |
default: |
default: |
641 |
error("unsupported Alpha relocation (%d)", type); |
error("unsupported Alpha relocation (%d)", type); |
649 |
int type; |
int type; |
650 |
int addend; |
int addend; |
651 |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
652 |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { |
653 |
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; |
654 |
if (strstart(sym_name, "__op_param", &p)) { |
if (strstart(sym_name, "__op_param", &p)) { |
655 |
snprintf(name, sizeof(name), "param%s", p); |
snprintf(name, sizeof(name), "param%s", p); |
675 |
int type; |
int type; |
676 |
int addend; |
int addend; |
677 |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
678 |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
if (rel->r_offset >= start_offset && |
679 |
|
rel->r_offset < start_offset + copy_size) { |
680 |
sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; |
681 |
if (strstart(sym_name, "__op_param", &p)) { |
if (strstart(sym_name, "__op_param", &p)) { |
682 |
snprintf(name, sizeof(name), "param%s", p); |
snprintf(name, sizeof(name), "param%s", p); |
694 |
switch(type) { |
switch(type) { |
695 |
case R_SPARC_32: |
case R_SPARC_32: |
696 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
697 |
rel->r_offset - offset, name, addend); |
rel->r_offset - start_offset, name, addend); |
698 |
break; |
break; |
699 |
case R_SPARC_HI22: |
case R_SPARC_HI22: |
700 |
fprintf(outfile, |
fprintf(outfile, |
701 |
" *(uint32_t *)(gen_code_ptr + %d) = " |
" *(uint32_t *)(gen_code_ptr + %d) = " |
702 |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
703 |
" & ~0x3fffff) " |
" & ~0x3fffff) " |
704 |
" | ((%s + %d) & 0x3fffff);\n", |
" | (((%s + %d) >> 10) & 0x3fffff);\n", |
705 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
706 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
707 |
name, addend); |
name, addend); |
708 |
break; |
break; |
709 |
case R_SPARC_LO10: |
case R_SPARC_LO10: |
712 |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
713 |
" & ~0x3ff) " |
" & ~0x3ff) " |
714 |
" | ((%s + %d) & 0x3ff);\n", |
" | ((%s + %d) & 0x3ff);\n", |
715 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
716 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
717 |
name, addend); |
name, addend); |
718 |
break; |
break; |
719 |
case R_SPARC_WDISP30: |
case R_SPARC_WDISP30: |
721 |
" *(uint32_t *)(gen_code_ptr + %d) = " |
" *(uint32_t *)(gen_code_ptr + %d) = " |
722 |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
723 |
" & ~0x3fffffff) " |
" & ~0x3fffffff) " |
724 |
" | ((((%s + %d) - (long)gen_code_ptr)>>2) " |
" | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " |
725 |
" & 0x3fffffff);\n", |
" & 0x3fffffff);\n", |
726 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
727 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
728 |
name, addend); |
name, addend, |
729 |
|
rel->r_offset - start_offset); |
730 |
break; |
break; |
731 |
default: |
default: |
732 |
error("unsupported sparc relocation (%d)", type); |
error("unsupported sparc relocation (%d)", type); |
740 |
int type; |
int type; |
741 |
int addend; |
int addend; |
742 |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
743 |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
if (rel->r_offset >= start_offset && |
744 |
|
rel->r_offset < start_offset + copy_size) { |
745 |
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; |
746 |
if (strstart(sym_name, "__op_param", &p)) { |
if (strstart(sym_name, "__op_param", &p)) { |
747 |
snprintf(name, sizeof(name), "param%s", p); |
snprintf(name, sizeof(name), "param%s", p); |
753 |
switch(type) { |
switch(type) { |
754 |
case R_SPARC_32: |
case R_SPARC_32: |
755 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
756 |
rel->r_offset - offset, name, addend); |
rel->r_offset - start_offset, name, addend); |
757 |
break; |
break; |
758 |
case R_SPARC_HI22: |
case R_SPARC_HI22: |
759 |
fprintf(outfile, |
fprintf(outfile, |
760 |
" *(uint32_t *)(gen_code_ptr + %d) = " |
" *(uint32_t *)(gen_code_ptr + %d) = " |
761 |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
762 |
" & ~0x3fffff) " |
" & ~0x3fffff) " |
763 |
" | ((%s + %d) & 0x3fffff);\n", |
" | (((%s + %d) >> 10) & 0x3fffff);\n", |
764 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
765 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
766 |
name, addend); |
name, addend); |
767 |
break; |
break; |
768 |
case R_SPARC_LO10: |
case R_SPARC_LO10: |
771 |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
772 |
" & ~0x3ff) " |
" & ~0x3ff) " |
773 |
" | ((%s + %d) & 0x3ff);\n", |
" | ((%s + %d) & 0x3ff);\n", |
774 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
775 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
776 |
name, addend); |
name, addend); |
777 |
break; |
break; |
778 |
case R_SPARC_WDISP30: |
case R_SPARC_WDISP30: |
780 |
" *(uint32_t *)(gen_code_ptr + %d) = " |
" *(uint32_t *)(gen_code_ptr + %d) = " |
781 |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
"((*(uint32_t *)(gen_code_ptr + %d)) " |
782 |
" & ~0x3fffffff) " |
" & ~0x3fffffff) " |
783 |
" | ((((%s + %d) - (long)gen_code_ptr)>>2) " |
" | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " |
784 |
" & 0x3fffffff);\n", |
" & 0x3fffffff);\n", |
785 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
786 |
rel->r_offset - offset, |
rel->r_offset - start_offset, |
787 |
name, addend); |
name, addend, |
788 |
|
rel->r_offset - start_offset); |
789 |
break; |
break; |
790 |
default: |
default: |
791 |
error("unsupported sparc64 relocation (%d)", type); |
error("unsupported sparc64 relocation (%d)", type); |
970 |
" const uint32_t *opparam_ptr;\n" |
" const uint32_t *opparam_ptr;\n" |
971 |
" gen_code_ptr = gen_code_buf;\n" |
" gen_code_ptr = gen_code_buf;\n" |
972 |
" opc_ptr = opc_buf;\n" |
" opc_ptr = opc_buf;\n" |
973 |
" opparam_ptr = opparam_buf;\n" |
" opparam_ptr = opparam_buf;\n"); |
974 |
|
|
975 |
|
/* Generate prologue, if needed. */ |
976 |
|
switch(ELF_ARCH) { |
977 |
|
case EM_SPARC: |
978 |
|
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c23a080; /* sub %%sp, 128, %%sp */\n"); |
979 |
|
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc27a080; /* sub %%fp, 128, %%fp */\n"); |
980 |
|
break; |
981 |
|
|
982 |
|
case EM_SPARCV9: |
983 |
|
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c23a100; /* sub %%sp, 256, %%sp */\n"); |
984 |
|
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc27a100; /* sub %%fp, 256, %%fp */\n"); |
985 |
|
break; |
986 |
|
}; |
987 |
|
|
988 |
|
fprintf(outfile, |
989 |
" for(;;) {\n" |
" for(;;) {\n" |
990 |
" switch(*opc_ptr++) {\n" |
" switch(*opc_ptr++) {\n" |
991 |
); |
); |
1013 |
" the_end:\n" |
" the_end:\n" |
1014 |
); |
); |
1015 |
|
|
1016 |
/* generate a return */ |
/* generate epilogue */ |
1017 |
switch(ELF_ARCH) { |
switch(ELF_ARCH) { |
1018 |
case EM_386: |
case EM_386: |
1019 |
fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n"); |
fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n"); |
1032 |
break; |
break; |
1033 |
case EM_SPARC: |
case EM_SPARC: |
1034 |
case EM_SPARC32PLUS: |
case EM_SPARC32PLUS: |
1035 |
|
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc07a080; /* add %%fp, 256, %%fp */\n"); |
1036 |
|
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c62008; /* jmpl %%i0 + 8, %%g0 */\n"); |
1037 |
|
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c03a080; /* add %%sp, 256, %%sp */\n"); |
1038 |
|
break; |
1039 |
case EM_SPARCV9: |
case EM_SPARCV9: |
1040 |
/* Fill the delay slot. */ |
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c7e008; /* ret */\n"); |
1041 |
fprintf(outfile, "*((uint32_t *)gen_code_ptr) = *((uint32_t *)gen_code_ptr - 1); /* delay slot */\n"); |
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81e80000; /* restore */\n"); |
|
fprintf(outfile, "*((uint32_t *)gen_code_ptr - 1) = 0x81c3e008; /* retl */\n"); |
|
|
fprintf(outfile, "gen_code_ptr++;\n"); |
|
1042 |
break; |
break; |
1043 |
default: |
default: |
1044 |
error("unknown ELF architecture"); |
error("unknown ELF architecture"); |