Commit fa4fbfb98ad09b1a5bde2c78db5cb1c13363bdf2
1 parent
5d794885
Emit trampolines manually in prologue
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4715 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
80 additions
and
38 deletions
tcg/ppc/tcg-target.c
| @@ -23,6 +23,8 @@ | @@ -23,6 +23,8 @@ | ||
| 23 | */ | 23 | */ |
| 24 | 24 | ||
| 25 | static uint8_t *tb_ret_addr; | 25 | static uint8_t *tb_ret_addr; |
| 26 | +static uint8_t *udiv_addr; | ||
| 27 | +static uint8_t *div_addr; | ||
| 26 | 28 | ||
| 27 | #define FAST_PATH | 29 | #define FAST_PATH |
| 28 | #if TARGET_PHYS_ADDR_BITS <= 32 | 30 | #if TARGET_PHYS_ADDR_BITS <= 32 |
| @@ -118,7 +120,7 @@ static const int tcg_target_call_oarg_regs[2] = { | @@ -118,7 +120,7 @@ static const int tcg_target_call_oarg_regs[2] = { | ||
| 118 | }; | 120 | }; |
| 119 | 121 | ||
| 120 | static const int tcg_target_callee_save_regs[] = { | 122 | static const int tcg_target_callee_save_regs[] = { |
| 121 | - TCG_REG_R13, /* sould r13 be saved? */ | 123 | + TCG_REG_R13, /* should r13 be saved? */ |
| 122 | TCG_REG_R14, | 124 | TCG_REG_R14, |
| 123 | TCG_REG_R15, | 125 | TCG_REG_R15, |
| 124 | TCG_REG_R16, | 126 | TCG_REG_R16, |
| @@ -135,6 +137,22 @@ static const int tcg_target_callee_save_regs[] = { | @@ -135,6 +137,22 @@ static const int tcg_target_callee_save_regs[] = { | ||
| 135 | TCG_REG_R31 | 137 | TCG_REG_R31 |
| 136 | }; | 138 | }; |
| 137 | 139 | ||
| 140 | +static const int div_save_regs[] = { | ||
| 141 | + TCG_REG_R4, | ||
| 142 | + TCG_REG_R5, | ||
| 143 | + TCG_REG_R7, | ||
| 144 | + TCG_REG_R8, | ||
| 145 | + TCG_REG_R9, | ||
| 146 | + TCG_REG_R10, | ||
| 147 | + TCG_REG_R11, | ||
| 148 | + TCG_REG_R12, | ||
| 149 | + TCG_REG_R13, /* should r13 be saved? */ | ||
| 150 | + TCG_REG_R24, | ||
| 151 | + TCG_REG_R25, | ||
| 152 | + TCG_REG_R26, | ||
| 153 | + TCG_REG_R27, | ||
| 154 | +}; | ||
| 155 | + | ||
| 138 | static uint32_t reloc_pc24_val (void *pc, tcg_target_long target) | 156 | static uint32_t reloc_pc24_val (void *pc, tcg_target_long target) |
| 139 | { | 157 | { |
| 140 | tcg_target_long disp; | 158 | tcg_target_long disp; |
| @@ -799,9 +817,25 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) | @@ -799,9 +817,25 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) | ||
| 799 | #endif | 817 | #endif |
| 800 | } | 818 | } |
| 801 | 819 | ||
| 820 | +static uint64_t ppc_udiv_helper (uint64_t a, uint32_t b) | ||
| 821 | +{ | ||
| 822 | + uint64_t rem, quo; | ||
| 823 | + quo = a / b; | ||
| 824 | + rem = a % b; | ||
| 825 | + return (rem << 32) | (uint32_t) quo; | ||
| 826 | +} | ||
| 827 | + | ||
| 828 | +static uint64_t ppc_div_helper (int64_t a, int32_t b) | ||
| 829 | +{ | ||
| 830 | + int64_t rem, quo; | ||
| 831 | + quo = a / b; | ||
| 832 | + rem = a % b; | ||
| 833 | + return (rem << 32) | (uint32_t) quo; | ||
| 834 | +} | ||
| 835 | + | ||
| 802 | void tcg_target_qemu_prologue (TCGContext *s) | 836 | void tcg_target_qemu_prologue (TCGContext *s) |
| 803 | { | 837 | { |
| 804 | - int i, frame_size; | 838 | + int i, j, frame_size; |
| 805 | 839 | ||
| 806 | frame_size = 0 | 840 | frame_size = 0 |
| 807 | + 4 /* back chain */ | 841 | + 4 /* back chain */ |
| @@ -837,6 +871,49 @@ void tcg_target_qemu_prologue (TCGContext *s) | @@ -837,6 +871,49 @@ void tcg_target_qemu_prologue (TCGContext *s) | ||
| 837 | tcg_out32 (s, MTSPR | RS (0) | LR); | 871 | tcg_out32 (s, MTSPR | RS (0) | LR); |
| 838 | tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size); | 872 | tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size); |
| 839 | tcg_out32 (s, BCLR | BO_ALWAYS); | 873 | tcg_out32 (s, BCLR | BO_ALWAYS); |
| 874 | + | ||
| 875 | + /* div trampolines */ | ||
| 876 | + for (j = 0; j < 2; ++j) { | ||
| 877 | + tcg_target_long target; | ||
| 878 | + | ||
| 879 | + frame_size = 8 + ARRAY_SIZE (div_save_regs) * 4; | ||
| 880 | + frame_size = (frame_size + 15) & ~15; | ||
| 881 | + | ||
| 882 | + if (j == 0) { | ||
| 883 | + target = (tcg_target_long) ppc_udiv_helper; | ||
| 884 | + udiv_addr = s->code_ptr; | ||
| 885 | + } | ||
| 886 | + else { | ||
| 887 | + target = (tcg_target_long) ppc_div_helper; | ||
| 888 | + div_addr = s->code_ptr; | ||
| 889 | + } | ||
| 890 | + | ||
| 891 | + tcg_out32 (s, MFSPR | RT (0) | LR); | ||
| 892 | + tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff)); | ||
| 893 | + for (i = 0; i < ARRAY_SIZE (div_save_regs); ++i) | ||
| 894 | + tcg_out32 (s, (STW | ||
| 895 | + | RS (div_save_regs[i]) | ||
| 896 | + | RA (1) | ||
| 897 | + | (i * 4 + 8) | ||
| 898 | + ) | ||
| 899 | + ); | ||
| 900 | + tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size - 4)); | ||
| 901 | + tcg_out_mov (s, 4, 6); | ||
| 902 | + tcg_out_b (s, LK, target); | ||
| 903 | + tcg_out_mov (s, 6, 4); | ||
| 904 | + | ||
| 905 | + for (i = 0; i < ARRAY_SIZE (div_save_regs); ++i) | ||
| 906 | + tcg_out32 (s, (LWZ | ||
| 907 | + | RT (div_save_regs[i]) | ||
| 908 | + | RA (1) | ||
| 909 | + | (i * 4 + 8) | ||
| 910 | + ) | ||
| 911 | + ); | ||
| 912 | + tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size - 4)); | ||
| 913 | + tcg_out32 (s, MTSPR | RS (0) | LR); | ||
| 914 | + tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size); | ||
| 915 | + tcg_out32 (s, BCLR | BO_ALWAYS); | ||
| 916 | + } | ||
| 840 | } | 917 | } |
| 841 | 918 | ||
| 842 | static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1, | 919 | static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1, |
| @@ -1018,41 +1095,6 @@ static void tcg_out_brcond2(TCGContext *s, | @@ -1018,41 +1095,6 @@ static void tcg_out_brcond2(TCGContext *s, | ||
| 1018 | tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr); | 1095 | tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr); |
| 1019 | } | 1096 | } |
| 1020 | 1097 | ||
| 1021 | -static uint64_t __attribute ((used)) ppc_udiv_helper (uint64_t a, uint32_t b) | ||
| 1022 | -{ | ||
| 1023 | - uint64_t rem, quo; | ||
| 1024 | - quo = a / b; | ||
| 1025 | - rem = a % b; | ||
| 1026 | - return (rem << 32) | (uint32_t) quo; | ||
| 1027 | -} | ||
| 1028 | - | ||
| 1029 | -static uint64_t __attribute ((used)) ppc_div_helper (int64_t a, int32_t b) | ||
| 1030 | -{ | ||
| 1031 | - int64_t rem, quo; | ||
| 1032 | - quo = a / b; | ||
| 1033 | - rem = a % b; | ||
| 1034 | - return (rem << 32) | (uint32_t) quo; | ||
| 1035 | -} | ||
| 1036 | - | ||
| 1037 | -#define MAKE_TRAMPOLINE(name) \ | ||
| 1038 | -extern void name##_trampoline (void); \ | ||
| 1039 | -asm (#name "_trampoline:\n" \ | ||
| 1040 | - " mflr 0\n" \ | ||
| 1041 | - " addi 1,1,-112\n" \ | ||
| 1042 | - " mr 4,6\n" \ | ||
| 1043 | - " stmw 7,0(1)\n" \ | ||
| 1044 | - " stw 0,108(0)\n" \ | ||
| 1045 | - " bl ppc_" #name "_helper\n" \ | ||
| 1046 | - " lmw 7,0(1)\n" \ | ||
| 1047 | - " lwz 0,108(0)\n" \ | ||
| 1048 | - " addi 1,1,112\n" \ | ||
| 1049 | - " mtlr 0\n" \ | ||
| 1050 | - " blr\n" \ | ||
| 1051 | - ) | ||
| 1052 | - | ||
| 1053 | -MAKE_TRAMPOLINE (div); | ||
| 1054 | -MAKE_TRAMPOLINE (udiv); | ||
| 1055 | - | ||
| 1056 | static void tcg_out_div2 (TCGContext *s, int uns) | 1098 | static void tcg_out_div2 (TCGContext *s, int uns) |
| 1057 | { | 1099 | { |
| 1058 | void *label1_ptr, *label2_ptr; | 1100 | void *label1_ptr, *label2_ptr; |
| @@ -1067,7 +1109,7 @@ static void tcg_out_div2 (TCGContext *s, int uns) | @@ -1067,7 +1109,7 @@ static void tcg_out_div2 (TCGContext *s, int uns) | ||
| 1067 | label1_ptr = s->code_ptr; | 1109 | label1_ptr = s->code_ptr; |
| 1068 | tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); | 1110 | tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); |
| 1069 | 1111 | ||
| 1070 | - tcg_out_b (s, LK, (tcg_target_long) (uns ? udiv_trampoline : div_trampoline)); | 1112 | + tcg_out_b (s, LK, (tcg_target_long) (uns ? udiv_addr : div_addr)); |
| 1071 | 1113 | ||
| 1072 | label2_ptr = s->code_ptr; | 1114 | label2_ptr = s->code_ptr; |
| 1073 | tcg_out32 (s, B); | 1115 | tcg_out32 (s, B); |