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 1232 if (args[0] >> 8)
1233 1233 tcg_out32(s, args[0]);
1234 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 1247 #endif
1243 1248 break;
1244 1249 case INDEX_op_goto_tb:
1245 1250 if (s->tb_jmp_offset) {
1246 1251 /* Direct jump method */
1247   -#if 1
  1252 +#if defined(USE_DIRECT_JUMP)
1248 1253 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1249 1254 tcg_out_b(s, COND_AL, 8);
1250 1255 #else
... ...