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); |