Commit 0a878c4760718e1604e2cfe423252729716110ad

Authored by malc
1 parent 1a14026e

PPC TCG Fixes

* Fix typo in aliased div2
* "Optimize" aliased div2/divu2
* Fix two remaining branch retranslation problems
  (Kudos to Andrzej Zaborowski)
* Rework goto_tb and set_jmp_target1
* Use correct size when flushing icache
* Use correct register selection for ORI
  (Was harmless since in both cases srcreg was equal to dstreg)



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4691 c046a42c-6fe2-441c-8c8c-71466251a162
exec-all.h
... ... @@ -184,32 +184,37 @@ extern int code_gen_max_blocks;
184 184 #if defined(USE_DIRECT_JUMP)
185 185  
186 186 #if defined(__powerpc__)
  187 +static inline void flush_icache_range(unsigned long start, unsigned long stop);
187 188 static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
188 189 {
189   - uint32_t val, *ptr;
  190 + /* This must be in concord with INDEX_op_goto_tb inside tcg_out_op */
  191 + uint32_t *ptr;
190 192 long disp = addr - jmp_addr;
  193 + unsigned long patch_size;
191 194  
192 195 ptr = (uint32_t *)jmp_addr;
193   - val = *ptr;
194 196  
195 197 if ((disp << 6) >> 6 != disp) {
196   - uint16_t *p1;
197   -
198   - p1 = (uint16_t *) ptr;
199   - *ptr = (val & ~0x03fffffc) | 4;
200   - p1[3] = addr >> 16;
201   - p1[5] = addr & 0xffff;
  198 + ptr[0] = 0x3c000000 | (addr >> 16); /* lis 0,addr@ha */
  199 + ptr[1] = 0x60000000 | (addr & 0xffff); /* la 0,addr@l(0) */
  200 + ptr[2] = 0x7c0903a6; /* mtctr 0 */
  201 + ptr[3] = 0x4e800420; /* brctr */
  202 + patch_size = 16;
202 203 } else {
203 204 /* patch the branch destination */
204   - val = (val & ~0x03fffffc) | (disp & 0x03fffffc);
205   - *ptr = val;
  205 + if (disp != 16) {
  206 + *ptr = 0x48000000 | (disp & 0x03fffffc); /* b disp */
  207 + patch_size = 4;
  208 + } else {
  209 + ptr[0] = 0x60000000; /* nop */
  210 + ptr[1] = 0x60000000;
  211 + ptr[2] = 0x60000000;
  212 + ptr[3] = 0x60000000;
  213 + patch_size = 16;
  214 + }
206 215 }
207 216 /* flush icache */
208   - asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory");
209   - asm volatile ("sync" : : : "memory");
210   - asm volatile ("icbi 0,%0" : : "r"(ptr) : "memory");
211   - asm volatile ("sync" : : : "memory");
212   - asm volatile ("isync" : : : "memory");
  217 + flush_icache_range(jmp_addr, jmp_addr + patch_size);
213 218 }
214 219 #elif defined(__i386__) || defined(__x86_64__)
215 220 static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
... ...
tcg/ppc/tcg-target.c
... ... @@ -388,7 +388,7 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
388 388 else {
389 389 tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff));
390 390 if (arg & 0xffff)
391   - tcg_out32 (s, ORI | RT (ret) | RA (ret) | (arg & 0xffff));
  391 + tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff));
392 392 }
393 393 }
394 394  
... ... @@ -939,18 +939,14 @@ static void tcg_out_brcond(TCGContext *s, int cond,
939 939 tcg_out32 (s, op | RA (arg1) | RB (arg2));
940 940 }
941 941  
942   - if (l->has_value) {
943   - tcg_target_long disp;
944   -
945   - disp = (tcg_target_long) s->code_ptr - l->u.value;
946   - if (disp != (int16_t) disp)
947   - tcg_abort ();
948   -
  942 + if (l->has_value)
949 943 tcg_out32 (s, tcg_to_bc[cond] | reloc_pc14_val (s->code_ptr,
950 944 l->u.value));
951   - }
952 945 else {
953   - tcg_out32 (s, tcg_to_bc[cond]);
  946 + uint16_t val = *(uint16_t *) &s->code_ptr[2];
  947 +
  948 + /* Thanks to Andrzej Zaborowski */
  949 + tcg_out32 (s, tcg_to_bc[cond] | (val & 0xfffc));
954 950 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
955 951 }
956 952 }
... ... @@ -1029,24 +1025,9 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
1029 1025 case INDEX_op_goto_tb:
1030 1026 if (s->tb_jmp_offset) {
1031 1027 /* direct jump method */
1032   - uint32_t val;
1033   - uint16_t *p;
1034 1028  
1035 1029 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1036   - /* Thanks to Andrzej Zaborowski for this */
1037   - val = *(uint32_t *) s->code_ptr & 0x3fffffc;
1038   -
1039   - tcg_out32 (s, B | val);
1040   -
1041   - /* For branches outside of LL range
1042   - This must be in concord with tb_set_jmp_target1 */
1043   - p = (uint16_t *) s->code_ptr;
1044   - p[0] = (ADDIS | RT (0) | RA (0)) >> 16;
1045   - p[2] = (ORI | RT (0) | RA (0)) >> 16;
1046   - s->code_ptr += 8;
1047   -
1048   - tcg_out32 (s, MTSPR | RS (0) | CTR);
1049   - tcg_out32 (s, BCCTR | BO_ALWAYS);
  1030 + s->code_ptr += 16;
1050 1031 }
1051 1032 else {
1052 1033 tcg_abort ();
... ... @@ -1061,7 +1042,10 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
1061 1042 tcg_out_b (s, 0, l->u.value);
1062 1043 }
1063 1044 else {
1064   - tcg_out32 (s, B);
  1045 + uint32_t val = *(uint32_t *) s->code_ptr;
  1046 +
  1047 + /* Thanks to Andrzej Zaborowski */
  1048 + tcg_out32 (s, B | (val & 0x3fffffc));
1065 1049 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1066 1050 }
1067 1051 }
... ... @@ -1222,10 +1206,10 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
1222 1206 case INDEX_op_div2_i32:
1223 1207 if (args[0] == args[2] || args[0] == args[3]) {
1224 1208 tcg_out32 (s, DIVW | TAB (0, args[2], args[3]));
  1209 + tcg_out32 (s, MTSPR | RS (0) | CTR);
1225 1210 tcg_out32 (s, MULLW | TAB (0, 0, args[3]));
1226   - tcg_out32 (s, SUBF | TAB (0, 0, args[2]));
1227   - tcg_out32 (s, DIVW | TAB (args[0], args[2], args[3]));
1228   - tcg_out_mov (s, args[1], 0);
  1211 + tcg_out32 (s, SUBF | TAB (args[1], 0, args[2]));
  1212 + tcg_out32 (s, MFSPR | RT (args[0]) | CTR);
1229 1213 }
1230 1214 else {
1231 1215 tcg_out32 (s, DIVW | TAB (args[0], args[2], args[3]));
... ... @@ -1236,10 +1220,10 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
1236 1220 case INDEX_op_divu2_i32:
1237 1221 if (args[0] == args[2] || args[0] == args[3]) {
1238 1222 tcg_out32 (s, DIVWU | TAB (0, args[2], args[3]));
  1223 + tcg_out32 (s, MTSPR | RS (0) | CTR);
1239 1224 tcg_out32 (s, MULLW | TAB (0, 0, args[3]));
1240   - tcg_out32 (s, SUBF | TAB (0, 0, args[2]));
1241   - tcg_out32 (s, DIVWU | TAB (args[0], args[2], args[3]));
1242   - tcg_out_mov (s, args[1], 0);
  1225 + tcg_out32 (s, SUBF | TAB (args[1], 0, args[2]));
  1226 + tcg_out32 (s, MFSPR | RT (args[0]) | CTR);
1243 1227 }
1244 1228 else {
1245 1229 tcg_out32 (s, DIVWU | TAB (args[0], args[2], args[3]));
... ...