Commit fe33867b0dcea3cdbe276402694e15b7166e9a54

Authored by balrog
1 parent 1cb0661e

Don't rely on ARM tcg_out_goto() generating just a single insn.

Otherwise when tb_exit generates a jump beyond the pc-relative range,
tcg_out_goto() spans two/three instructions and we load the tb return
value from a wrong address.  This is #ifdefed out currently because
we take care for the jumps to be local.
Problem spotted by Steffen Liebergeld.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5845 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 13 additions and 8 deletions
tcg/arm/tcg-target.c
@@ -1232,19 +1232,24 @@ static inline void tcg_out_op(TCGContext *s, int opc, @@ -1232,19 +1232,24 @@ static inline void tcg_out_op(TCGContext *s, int opc,
1232 if (args[0] >> 8) 1232 if (args[0] >> 8)
1233 tcg_out32(s, args[0]); 1233 tcg_out32(s, args[0]);
1234 #else 1234 #else
1235 - if (args[0] >> 8)  
1236 - tcg_out_ld32_12(s, COND_AL, 0, 15, 0);  
1237 - else  
1238 - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, 0, 0, args[0]);  
1239 - tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);  
1240 - if (args[0] >> 8)  
1241 - tcg_out32(s, args[0]); 1235 + {
  1236 + uint8_t *ld_ptr = s->code_ptr;
  1237 + if (args[0] >> 8)
  1238 + tcg_out_ld32_12(s, COND_AL, 0, 15, 0);
  1239 + else
  1240 + tcg_out_dat_imm(s, COND_AL, ARITH_MOV, 0, 0, args[0]);
  1241 + tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
  1242 + if (args[0] >> 8) {
  1243 + *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
  1244 + tcg_out32(s, args[0]);
  1245 + }
  1246 + }
1242 #endif 1247 #endif
1243 break; 1248 break;
1244 case INDEX_op_goto_tb: 1249 case INDEX_op_goto_tb:
1245 if (s->tb_jmp_offset) { 1250 if (s->tb_jmp_offset) {
1246 /* Direct jump method */ 1251 /* Direct jump method */
1247 -#if 1 1252 +#if defined(USE_DIRECT_JUMP)
1248 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; 1253 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1249 tcg_out_b(s, COND_AL, 8); 1254 tcg_out_b(s, COND_AL, 8);
1250 #else 1255 #else