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 | 23 | */ |
24 | 24 | |
25 | 25 | static uint8_t *tb_ret_addr; |
26 | +static uint8_t *udiv_addr; | |
27 | +static uint8_t *div_addr; | |
26 | 28 | |
27 | 29 | #define FAST_PATH |
28 | 30 | #if TARGET_PHYS_ADDR_BITS <= 32 |
... | ... | @@ -118,7 +120,7 @@ static const int tcg_target_call_oarg_regs[2] = { |
118 | 120 | }; |
119 | 121 | |
120 | 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 | 124 | TCG_REG_R14, |
123 | 125 | TCG_REG_R15, |
124 | 126 | TCG_REG_R16, |
... | ... | @@ -135,6 +137,22 @@ static const int tcg_target_callee_save_regs[] = { |
135 | 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 | 156 | static uint32_t reloc_pc24_val (void *pc, tcg_target_long target) |
139 | 157 | { |
140 | 158 | tcg_target_long disp; |
... | ... | @@ -799,9 +817,25 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) |
799 | 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 | 836 | void tcg_target_qemu_prologue (TCGContext *s) |
803 | 837 | { |
804 | - int i, frame_size; | |
838 | + int i, j, frame_size; | |
805 | 839 | |
806 | 840 | frame_size = 0 |
807 | 841 | + 4 /* back chain */ |
... | ... | @@ -837,6 +871,49 @@ void tcg_target_qemu_prologue (TCGContext *s) |
837 | 871 | tcg_out32 (s, MTSPR | RS (0) | LR); |
838 | 872 | tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size); |
839 | 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 | 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 | 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 | 1098 | static void tcg_out_div2 (TCGContext *s, int uns) |
1057 | 1099 | { |
1058 | 1100 | void *label1_ptr, *label2_ptr; |
... | ... | @@ -1067,7 +1109,7 @@ static void tcg_out_div2 (TCGContext *s, int uns) |
1067 | 1109 | label1_ptr = s->code_ptr; |
1068 | 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 | 1114 | label2_ptr = s->code_ptr; |
1073 | 1115 | tcg_out32 (s, B); | ... | ... |