translate-all.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Host code generation
  3. *
  4. * Copyright (c) 2003 Fabrice Bellard
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <stdarg.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <inttypes.h>
  24. #include "config.h"
  25. #define NO_CPU_IO_DEFS
  26. #include "cpu.h"
  27. #include "disas.h"
  28. #include "tcg.h"
  29. #include "qemu-timer.h"
  30. /* code generation context */
  31. TCGContext tcg_ctx;
  32. uint16_t gen_opc_buf[OPC_BUF_SIZE];
  33. TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];
  34. target_ulong gen_opc_pc[OPC_BUF_SIZE];
  35. uint16_t gen_opc_icount[OPC_BUF_SIZE];
  36. uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
  37. void cpu_gen_init(void)
  38. {
  39. tcg_context_init(&tcg_ctx);
  40. }
  41. /* return non zero if the very first instruction is invalid so that
  42. the virtual CPU can trigger an exception.
  43. '*gen_code_size_ptr' contains the size of the generated code (host
  44. code).
  45. */
  46. int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr)
  47. {
  48. TCGContext *s = &tcg_ctx;
  49. uint8_t *gen_code_buf;
  50. int gen_code_size;
  51. #ifdef CONFIG_PROFILER
  52. int64_t ti;
  53. #endif
  54. #ifdef CONFIG_PROFILER
  55. s->tb_count1++; /* includes aborted translations because of
  56. exceptions */
  57. ti = profile_getclock();
  58. #endif
  59. tcg_func_start(s);
  60. gen_intermediate_code(env, tb);
  61. /* generate machine code */
  62. gen_code_buf = tb->tc_ptr;
  63. tb->tb_next_offset[0] = 0xffff;
  64. tb->tb_next_offset[1] = 0xffff;
  65. s->tb_next_offset = tb->tb_next_offset;
  66. #ifdef USE_DIRECT_JUMP
  67. s->tb_jmp_offset = tb->tb_jmp_offset;
  68. s->tb_next = NULL;
  69. #else
  70. s->tb_jmp_offset = NULL;
  71. s->tb_next = tb->tb_next;
  72. #endif
  73. #ifdef CONFIG_PROFILER
  74. s->tb_count++;
  75. s->interm_time += profile_getclock() - ti;
  76. s->code_time -= profile_getclock();
  77. #endif
  78. gen_code_size = tcg_gen_code(s, gen_code_buf);
  79. *gen_code_size_ptr = gen_code_size;
  80. #ifdef CONFIG_PROFILER
  81. s->code_time += profile_getclock();
  82. s->code_in_len += tb->size;
  83. s->code_out_len += gen_code_size;
  84. #endif
  85. #ifdef DEBUG_DISAS
  86. if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
  87. qemu_log("OUT: [size=%d]\n", *gen_code_size_ptr);
  88. log_disas(tb->tc_ptr, *gen_code_size_ptr);
  89. qemu_log("\n");
  90. qemu_log_flush();
  91. }
  92. #endif
  93. return 0;
  94. }
  95. /* The cpu state corresponding to 'searched_pc' is restored.
  96. */
  97. int cpu_restore_state(TranslationBlock *tb,
  98. CPUArchState *env, uintptr_t searched_pc)
  99. {
  100. TCGContext *s = &tcg_ctx;
  101. int j;
  102. uintptr_t tc_ptr;
  103. #ifdef CONFIG_PROFILER
  104. int64_t ti;
  105. #endif
  106. #ifdef CONFIG_PROFILER
  107. ti = profile_getclock();
  108. #endif
  109. tcg_func_start(s);
  110. gen_intermediate_code_pc(env, tb);
  111. if (use_icount) {
  112. /* Reset the cycle counter to the start of the block. */
  113. env->icount_decr.u16.low += tb->icount;
  114. /* Clear the IO flag. */
  115. env->can_do_io = 0;
  116. }
  117. /* find opc index corresponding to search_pc */
  118. tc_ptr = (uintptr_t)tb->tc_ptr;
  119. if (searched_pc < tc_ptr)
  120. return -1;
  121. s->tb_next_offset = tb->tb_next_offset;
  122. #ifdef USE_DIRECT_JUMP
  123. s->tb_jmp_offset = tb->tb_jmp_offset;
  124. s->tb_next = NULL;
  125. #else
  126. s->tb_jmp_offset = NULL;
  127. s->tb_next = tb->tb_next;
  128. #endif
  129. j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr);
  130. if (j < 0)
  131. return -1;
  132. /* now find start of instruction before */
  133. while (gen_opc_instr_start[j] == 0)
  134. j--;
  135. env->icount_decr.u16.low -= gen_opc_icount[j];
  136. restore_state_to_opc(env, tb, j);
  137. #ifdef CONFIG_PROFILER
  138. s->restore_time += profile_getclock() - ti;
  139. s->restore_count++;
  140. #endif
  141. return 0;
  142. }