Build tcg/ once for system and once for user.

Unmap perf_marker.
 Remove left over _link_error() definitions.
 -----BEGIN PGP SIGNATURE-----
 
 iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmR+QekdHHJpY2hhcmQu
 aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV8NJwf+PE6ShfN+N65hwt0w
 mgIrWNadgnXezEyaUdEuzLre9Ln9uD9Are948xIGPTVoLyr2wEr+Ma9dFI+GpTHY
 8C0b5v0SfHBBIK+wJb7VNcEdssRXVTcpikmmYv9IRpFTT8349bCdvJhuwojU5cyx
 NGgq9ydJ/dEUDtmVU6EnOyLCDSHg2mc+KPVWhjXaVbVPTyP6Xmb0BwSSUt1t5NQK
 Zw7E6G4z7QYXa7GNPTtXSWzTH3y9bSLQNj3jzHfJ6DPW23zxhFjCPhJYl1ecOHVF
 pxXEEIjieHQxdlm3kg+tcCoZSJ6OXESNzu2D8zk8Kf6xJjMItTQOOuokWM6mBX4y
 VbQoXg==
 =8vrl
 -----END PGP SIGNATURE-----

Merge tag 'pull-tcg-20230605' of https://gitlab.com/rth7680/qemu into staging

Build tcg/ once for system and once for user.
Unmap perf_marker.
Remove left over _link_error() definitions.

# -----BEGIN PGP SIGNATURE-----
#
# iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmR+QekdHHJpY2hhcmQu
# aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV8NJwf+PE6ShfN+N65hwt0w
# mgIrWNadgnXezEyaUdEuzLre9Ln9uD9Are948xIGPTVoLyr2wEr+Ma9dFI+GpTHY
# 8C0b5v0SfHBBIK+wJb7VNcEdssRXVTcpikmmYv9IRpFTT8349bCdvJhuwojU5cyx
# NGgq9ydJ/dEUDtmVU6EnOyLCDSHg2mc+KPVWhjXaVbVPTyP6Xmb0BwSSUt1t5NQK
# Zw7E6G4z7QYXa7GNPTtXSWzTH3y9bSLQNj3jzHfJ6DPW23zxhFjCPhJYl1ecOHVF
# pxXEEIjieHQxdlm3kg+tcCoZSJ6OXESNzu2D8zk8Kf6xJjMItTQOOuokWM6mBX4y
# VbQoXg==
# =8vrl
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 05 Jun 2023 01:13:29 PM PDT
# gpg:                using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg:                issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate]

* tag 'pull-tcg-20230605' of https://gitlab.com/rth7680/qemu: (52 commits)
  tcg/tcg-op-vec: Remove left over _link_error() definitions
  accel/tcg: Unmap perf_marker
  tcg: Build once for system and once for user-only
  exec/poison: Do not poison CONFIG_SOFTMMU
  plugins: Drop unused headers from exec/plugin-gen.h
  plugins: Move plugin_insn_append to translator.c
  tcg: Remove target-specific headers from tcg.[ch]
  tcg: Move env defines out of NEED_CPU_H in helper-head.h
  tcg: Fix PAGE/PROT confusion
  accel/tcg: Tidy includes for translator.[ch]
  target/arm: Add missing include of exec/exec-all.h
  target/*: Add missing includes of exec/translation-block.h
  target/mips: Tidy helpers for translation
  target/arm: Tidy helpers for translation
  accel/tcg: Move translator_fake_ldb out of line
  target/ppc: Inline gen_icount_io_start()
  accel/tcg: Introduce translator_io_start
  accel/tcg: Move most of gen-icount.h into translator.c
  include/exec: Remove CODE_GEN_AVG_BLOCK_SIZE
  tcg: Spit out exec/translation-block.h
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-06-05 13:16:56 -07:00
commit 369081c455
135 changed files with 3088 additions and 2782 deletions

View file

@ -154,6 +154,8 @@ F: include/exec/exec-all.h
F: include/exec/tb-flush.h
F: include/exec/target_long.h
F: include/exec/helper*.h
F: include/exec/helper*.h.inc
F: include/exec/helper-info.c.inc
F: include/sysemu/cpus.h
F: include/sysemu/tcg.h
F: include/hw/core/tcg-cpu-ops.h
@ -2865,7 +2867,6 @@ F: ui/cocoa.m
Main loop
M: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
F: include/exec/gen-icount.h
F: include/qemu/main-loop.h
F: include/sysemu/runstate.h
F: include/sysemu/runstate-action.h

View file

@ -297,7 +297,7 @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
{
if (qemu_log_in_addr_range(pc)) {
qemu_log_mask(CPU_LOG_EXEC,
"Trace %d: %p [" TARGET_FMT_lx
"Trace %d: %p [%08" PRIx64
"/" TARGET_FMT_lx "/%08x/%08x] %s\n",
cpu->cpu_index, tb->tc.ptr, tb->cs_base, pc,
tb->flags, tb->cflags, lookup_symbol(pc));

View file

@ -29,7 +29,7 @@
#include "tcg/tcg.h"
#include "qemu/error-report.h"
#include "exec/log.h"
#include "exec/helper-proto.h"
#include "exec/helper-proto-common.h"
#include "qemu/atomic.h"
#include "qemu/atomic128.h"
#include "exec/translate-all.h"
@ -40,7 +40,7 @@
#include "qemu/plugin-memory.h"
#endif
#include "tcg/tcg-ldst.h"
#include "exec/helper-proto.h"
#include "tcg/oversized-guest.h"
/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
/* #define DEBUG_TLB */
@ -1000,11 +1000,15 @@ static void tlb_reset_dirty_range_locked(CPUTLBEntry *tlb_entry,
addr &= TARGET_PAGE_MASK;
addr += tlb_entry->addend;
if ((addr - start) < length) {
#if TCG_OVERSIZED_GUEST
#if TARGET_LONG_BITS == 32
uint32_t *ptr_write = (uint32_t *)&tlb_entry->addr_write;
ptr_write += HOST_BIG_ENDIAN;
qatomic_set(ptr_write, *ptr_write | TLB_NOTDIRTY);
#elif TCG_OVERSIZED_GUEST
tlb_entry->addr_write |= TLB_NOTDIRTY;
#else
qatomic_set(&tlb_entry->addr_write,
tlb_entry->addr_write | TLB_NOTDIRTY);
tlb_entry->addr_write | TLB_NOTDIRTY);
#endif
}
}

View file

@ -15,6 +15,7 @@
#include "sysemu/cpus.h"
#include "sysemu/cpu-timers.h"
#include "sysemu/tcg.h"
#include "tcg/tcg.h"
#include "internal.h"

View file

@ -111,6 +111,8 @@ static void write_perfmap_entry(const void *start, size_t insn,
}
static FILE *jitdump;
static size_t perf_marker_size;
static void *perf_marker = MAP_FAILED;
#define JITHEADER_MAGIC 0x4A695444
#define JITHEADER_VERSION 1
@ -190,7 +192,6 @@ void perf_enable_jitdump(void)
{
struct jitheader header;
char jitdump_file[32];
void *perf_marker;
if (!use_rt_clock) {
warn_report("CLOCK_MONOTONIC is not available, proceeding without jitdump");
@ -210,7 +211,8 @@ void perf_enable_jitdump(void)
* PERF_RECORD_MMAP or PERF_RECORD_MMAP2 event is of the form jit-%d.dump
* and will process it as a jitdump file.
*/
perf_marker = mmap(NULL, qemu_real_host_page_size(), PROT_READ | PROT_EXEC,
perf_marker_size = qemu_real_host_page_size();
perf_marker = mmap(NULL, perf_marker_size, PROT_READ | PROT_EXEC,
MAP_PRIVATE, fileno(jitdump), 0);
if (perf_marker == MAP_FAILED) {
warn_report("Could not map %s: %s, proceeding without jitdump",
@ -311,7 +313,8 @@ void perf_report_code(uint64_t guest_pc, TranslationBlock *tb,
const void *start)
{
struct debuginfo_query *q;
size_t insn;
size_t insn, start_words;
uint64_t *gen_insn_data;
if (!perfmap && !jitdump) {
return;
@ -325,9 +328,12 @@ void perf_report_code(uint64_t guest_pc, TranslationBlock *tb,
debuginfo_lock();
/* Query debuginfo for each guest instruction. */
gen_insn_data = tcg_ctx->gen_insn_data;
start_words = tcg_ctx->insn_start_words;
for (insn = 0; insn < tb->icount; insn++) {
/* FIXME: This replicates the restore_state_to_opc() logic. */
q[insn].address = tcg_ctx->gen_insn_data[insn][0];
q[insn].address = gen_insn_data[insn * start_words + 0];
if (tb_cflags(tb) & CF_PCREL) {
q[insn].address |= (guest_pc & TARGET_PAGE_MASK);
} else {
@ -368,6 +374,11 @@ void perf_exit(void)
perfmap = NULL;
}
if (perf_marker != MAP_FAILED) {
munmap(perf_marker, perf_marker_size);
perf_marker = MAP_FAILED;
}
if (jitdump) {
fclose(jitdump);
jitdump = NULL;

View file

@ -43,12 +43,18 @@
* CPU's index into a TCG temp, since the first callback did it already.
*/
#include "qemu/osdep.h"
#include "cpu.h"
#include "tcg/tcg.h"
#include "tcg/tcg-temp-internal.h"
#include "tcg/tcg-op.h"
#include "exec/exec-all.h"
#include "exec/plugin-gen.h"
#include "exec/translator.h"
#include "exec/helper-proto-common.h"
#define HELPER_H "accel/tcg/plugin-helpers.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
#ifdef CONFIG_SOFTMMU
# define CONFIG_SOFTMMU_GATE 1

View file

@ -32,7 +32,7 @@
#include "qemu/guest-random.h"
#include "exec/exec-all.h"
#include "hw/boards.h"
#include "tcg/tcg.h"
#include "tcg-accel-ops.h"
#include "tcg-accel-ops-mttcg.h"

View file

@ -32,7 +32,7 @@
#include "qemu/notify.h"
#include "qemu/guest-random.h"
#include "exec/exec-all.h"
#include "tcg/tcg.h"
#include "tcg-accel-ops.h"
#include "tcg-accel-ops-rr.h"
#include "tcg-accel-ops-icount.h"

View file

@ -28,6 +28,7 @@
#include "exec/replay-core.h"
#include "sysemu/cpu-timers.h"
#include "tcg/tcg.h"
#include "tcg/oversized-guest.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/accel.h"

View file

@ -20,7 +20,7 @@
#include "qemu/osdep.h"
#include "qemu/host-utils.h"
#include "cpu.h"
#include "exec/helper-proto.h"
#include "exec/helper-proto-common.h"
#include "tcg/tcg-gvec-desc.h"

View file

@ -24,13 +24,17 @@
#include "qemu/osdep.h"
#include "qemu/host-utils.h"
#include "cpu.h"
#include "exec/helper-proto.h"
#include "exec/helper-proto-common.h"
#include "exec/cpu_ldst.h"
#include "exec/exec-all.h"
#include "disas/disas.h"
#include "exec/log.h"
#include "tcg/tcg.h"
#define HELPER_H "accel/tcg/tcg-runtime.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
/* 32-bit helpers */
int32_t HELPER(div_i32)(int32_t arg1, int32_t arg2)

View file

@ -19,7 +19,6 @@
#include "qemu/osdep.h"
#define NO_CPU_IO_DEFS
#include "trace.h"
#include "disas/disas.h"
#include "exec/exec-all.h"
@ -64,6 +63,7 @@
#include "tb-context.h"
#include "internal.h"
#include "perf.h"
#include "tcg/insn-start-words.h"
TBContext tb_ctx;
@ -127,22 +127,26 @@ static int64_t decode_sleb128(const uint8_t **pp)
static int encode_search(TranslationBlock *tb, uint8_t *block)
{
uint8_t *highwater = tcg_ctx->code_gen_highwater;
uint64_t *insn_data = tcg_ctx->gen_insn_data;
uint16_t *insn_end_off = tcg_ctx->gen_insn_end_off;
uint8_t *p = block;
int i, j, n;
for (i = 0, n = tb->icount; i < n; ++i) {
uint64_t prev;
uint64_t prev, curr;
for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
if (i == 0) {
prev = (!(tb_cflags(tb) & CF_PCREL) && j == 0 ? tb->pc : 0);
} else {
prev = tcg_ctx->gen_insn_data[i - 1][j];
prev = insn_data[(i - 1) * TARGET_INSN_START_WORDS + j];
}
p = encode_sleb128(p, tcg_ctx->gen_insn_data[i][j] - prev);
curr = insn_data[i * TARGET_INSN_START_WORDS + j];
p = encode_sleb128(p, curr - prev);
}
prev = (i == 0 ? 0 : tcg_ctx->gen_insn_end_off[i - 1]);
p = encode_sleb128(p, tcg_ctx->gen_insn_end_off[i] - prev);
prev = (i == 0 ? 0 : insn_end_off[i - 1]);
curr = insn_end_off[i];
p = encode_sleb128(p, curr - prev);
/* Test for (pending) buffer overflow. The assumption is that any
one row beginning below the high water mark cannot overrun
@ -350,11 +354,19 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
tb_set_page_addr0(tb, phys_pc);
tb_set_page_addr1(tb, -1);
tcg_ctx->gen_tb = tb;
tcg_ctx->addr_type = TCG_TYPE_TL;
tcg_ctx->addr_type = TARGET_LONG_BITS == 32 ? TCG_TYPE_I32 : TCG_TYPE_I64;
#ifdef CONFIG_SOFTMMU
tcg_ctx->page_bits = TARGET_PAGE_BITS;
tcg_ctx->page_mask = TARGET_PAGE_MASK;
tcg_ctx->tlb_dyn_max_bits = CPU_TLB_DYN_MAX_BITS;
tcg_ctx->tlb_fast_offset =
(int)offsetof(ArchCPU, neg.tlb.f) - (int)offsetof(ArchCPU, env);
#endif
tcg_ctx->insn_start_words = TARGET_INSN_START_WORDS;
#ifdef TCG_GUEST_DEFAULT_MO
tcg_ctx->guest_mo = TCG_GUEST_DEFAULT_MO;
#else
tcg_ctx->guest_mo = TCG_MO_ALL;
#endif
tb_overflow:
@ -449,7 +461,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
fprintf(logfile, "OUT: [size=%d]\n", gen_code_size);
fprintf(logfile,
" -- guest addr 0x%016" PRIx64 " + tb prologue\n",
tcg_ctx->gen_insn_data[insn][0]);
tcg_ctx->gen_insn_data[insn * TARGET_INSN_START_WORDS]);
chunk_start = tcg_ctx->gen_insn_end_off[insn];
disas(logfile, tb->tc.ptr, chunk_start);
@ -462,7 +474,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
size_t chunk_end = tcg_ctx->gen_insn_end_off[insn];
if (chunk_end > chunk_start) {
fprintf(logfile, " -- guest addr 0x%016" PRIx64 "\n",
tcg_ctx->gen_insn_data[insn][0]);
tcg_ctx->gen_insn_data[insn * TARGET_INSN_START_WORDS]);
disas(logfile, tb->tc.ptr + chunk_start,
chunk_end - chunk_start);
chunk_start = chunk_end;

View file

@ -8,15 +8,114 @@
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "tcg/tcg.h"
#include "tcg/tcg-op.h"
#include "exec/exec-all.h"
#include "exec/gen-icount.h"
#include "exec/log.h"
#include "exec/translator.h"
#include "exec/translate-all.h"
#include "exec/plugin-gen.h"
#include "exec/replay-core.h"
#include "tcg/tcg-op-common.h"
static void gen_io_start(void)
{
tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
offsetof(ArchCPU, parent_obj.can_do_io) -
offsetof(ArchCPU, env));
}
bool translator_io_start(DisasContextBase *db)
{
uint32_t cflags = tb_cflags(db->tb);
if (!(cflags & CF_USE_ICOUNT)) {
return false;
}
if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) {
/* Already started in translator_loop. */
return true;
}
gen_io_start();
/*
* Ensure that this instruction will be the last in the TB.
* The target may override this to something more forceful.
*/
if (db->is_jmp == DISAS_NEXT) {
db->is_jmp = DISAS_TOO_MANY;
}
return true;
}
static TCGOp *gen_tb_start(uint32_t cflags)
{
TCGv_i32 count = tcg_temp_new_i32();
TCGOp *icount_start_insn = NULL;
tcg_gen_ld_i32(count, cpu_env,
offsetof(ArchCPU, neg.icount_decr.u32) -
offsetof(ArchCPU, env));
if (cflags & CF_USE_ICOUNT) {
/*
* We emit a sub with a dummy immediate argument. Keep the insn index
* of the sub so that we later (when we know the actual insn count)
* can update the argument with the actual insn count.
*/
tcg_gen_sub_i32(count, count, tcg_constant_i32(0));
icount_start_insn = tcg_last_op();
}
/*
* Emit the check against icount_decr.u32 to see if we should exit
* unless we suppress the check with CF_NOIRQ. If we are using
* icount and have suppressed interruption the higher level code
* should have ensured we don't run more instructions than the
* budget.
*/
if (cflags & CF_NOIRQ) {
tcg_ctx->exitreq_label = NULL;
} else {
tcg_ctx->exitreq_label = gen_new_label();
tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label);
}
if (cflags & CF_USE_ICOUNT) {
tcg_gen_st16_i32(count, cpu_env,
offsetof(ArchCPU, neg.icount_decr.u16.low) -
offsetof(ArchCPU, env));
/*
* cpu->can_do_io is cleared automatically here at the beginning of
* each translation block. The cost is minimal and only paid for
* -icount, plus it would be very easy to forget doing it in the
* translator. Doing it here means we don't need a gen_io_end() to
* go with gen_io_start().
*/
tcg_gen_st_i32(tcg_constant_i32(0), cpu_env,
offsetof(ArchCPU, parent_obj.can_do_io) -
offsetof(ArchCPU, env));
}
return icount_start_insn;
}
static void gen_tb_end(const TranslationBlock *tb, uint32_t cflags,
TCGOp *icount_start_insn, int num_insns)
{
if (cflags & CF_USE_ICOUNT) {
/*
* Update the num_insn immediate parameter now that we know
* the actual insn count.
*/
tcg_set_insn_param(icount_start_insn, 2,
tcgv_i32_arg(tcg_constant_i32(num_insns)));
}
if (tcg_ctx->exitreq_label) {
gen_set_label(tcg_ctx->exitreq_label);
tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED);
}
}
bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
{
@ -34,6 +133,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
const TranslatorOps *ops, DisasContextBase *db)
{
uint32_t cflags = tb_cflags(tb);
TCGOp *icount_start_insn;
bool plugin_enabled;
/* Initialize DisasContext */
@ -55,7 +155,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
/* Start translating. */
gen_tb_start(db->tb);
icount_start_insn = gen_tb_start(cflags);
ops->tb_start(db, cpu);
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
@ -112,7 +212,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
/* Emit code to exit the TB, as indicated by db->is_jmp. */
ops->tb_stop(db, cpu);
gen_tb_end(db->tb, db->num_insns);
gen_tb_end(tb, cflags, icount_start_insn, db->num_insns);
if (plugin_enabled) {
plugin_gen_tb_end(cpu);
@ -185,6 +285,27 @@ static void *translator_access(CPUArchState *env, DisasContextBase *db,
return host + (pc - base);
}
static void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
{
#ifdef CONFIG_PLUGIN
struct qemu_plugin_insn *insn = tcg_ctx->plugin_insn;
abi_ptr off;
if (insn == NULL) {
return;
}
off = pc - insn->vaddr;
if (off < insn->data->len) {
g_byte_array_set_size(insn->data, off);
} else if (off > insn->data->len) {
/* we have an unexpected gap */
g_assert_not_reached();
}
insn->data = g_byte_array_append(insn->data, from, size);
#endif
}
uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
{
uint8_t ret;
@ -243,3 +364,8 @@ uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
plugin_insn_append(pc, &plug, sizeof(ret));
return ret;
}
void translator_fake_ldb(uint8_t insn8, abi_ptr pc)
{
plugin_insn_append(pc, &insn8, sizeof(insn8));
}

View file

@ -314,6 +314,9 @@ CPUArchState *cpu_copy(CPUArchState *env);
*
* Use TARGET_PAGE_BITS_MIN so that these bits are constant
* when TARGET_PAGE_BITS_VARY is in effect.
*
* The count, if not the placement of these bits is known
* to tcg/tcg-op-ldst.c, check_max_alignment().
*/
/* Zero if TLB entry is valid. */
#define TLB_INVALID_MASK (1 << (TARGET_PAGE_BITS_MIN - 1))

View file

@ -61,16 +61,11 @@
#define NB_MMU_MODES 16
#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
#include "exec/tlb-common.h"
/* use a fully associative victim tlb of 8 entries */
#define CPU_VTLB_SIZE 8
#if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32
#define CPU_TLB_ENTRY_BITS 4
#else
#define CPU_TLB_ENTRY_BITS 5
#endif
#define CPU_TLB_DYN_MIN_BITS 6
#define CPU_TLB_DYN_DEFAULT_BITS 8
@ -94,34 +89,6 @@
# endif
# endif
/* Minimalized TLB entry for use by TCG fast path. */
typedef struct CPUTLBEntry {
/* bit TARGET_LONG_BITS to TARGET_PAGE_BITS : virtual address
bit TARGET_PAGE_BITS-1..4 : Nonzero for accesses that should not
go directly to ram.
bit 3 : indicates that the entry is invalid
bit 2..0 : zero
*/
union {
struct {
target_ulong addr_read;
target_ulong addr_write;
target_ulong addr_code;
/* Addend to virtual address to get host address. IO accesses
use the corresponding iotlb value. */
uintptr_t addend;
};
/*
* Padding to get a power of two size, as well as index
* access to addr_{read,write,code}.
*/
target_ulong addr_idx[(1 << CPU_TLB_ENTRY_BITS) / TARGET_LONG_SIZE];
};
} CPUTLBEntry;
QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
#endif /* !CONFIG_USER_ONLY && CONFIG_TCG */
#if !defined(CONFIG_USER_ONLY)
@ -195,17 +162,6 @@ typedef struct CPUTLBDesc {
CPUTLBEntryFull *fulltlb;
} CPUTLBDesc;
/*
* Data elements that are per MMU mode, accessed by the fast path.
* The structure is aligned to aid loading the pair with one insn.
*/
typedef struct CPUTLBDescFast {
/* Contains (n_entries - 1) << CPU_TLB_ENTRY_BITS */
uintptr_t mask;
/* The array of tlb entries itself. */
CPUTLBEntry *table;
} CPUTLBDescFast QEMU_ALIGNED(2 * sizeof(void *));
/*
* Data elements that are shared between all MMU modes.
*/
@ -241,10 +197,6 @@ typedef struct CPUTLB {
CPUTLBDescFast f[NB_MMU_MODES];
} CPUTLB;
/* This will be used by TCG backends to compute offsets. */
#define TLB_MASK_TABLE_OFS(IDX) \
((int)offsetof(ArchCPU, neg.tlb.f[IDX]) - (int)offsetof(ArchCPU, env))
#else
typedef struct CPUTLB { } CPUTLB;

View file

@ -326,26 +326,32 @@ static inline void clear_helper_retaddr(void)
#else
/* Needed for TCG_OVERSIZED_GUEST */
#include "tcg/tcg.h"
#include "tcg/oversized-guest.h"
static inline target_ulong tlb_read_idx(const CPUTLBEntry *entry,
MMUAccessType access_type)
{
/* Do not rearrange the CPUTLBEntry structure members. */
QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_read) !=
MMU_DATA_LOAD * TARGET_LONG_SIZE);
MMU_DATA_LOAD * sizeof(uint64_t));
QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_write) !=
MMU_DATA_STORE * TARGET_LONG_SIZE);
MMU_DATA_STORE * sizeof(uint64_t));
QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_code) !=
MMU_INST_FETCH * TARGET_LONG_SIZE);
MMU_INST_FETCH * sizeof(uint64_t));
const target_ulong *ptr = &entry->addr_idx[access_type];
#if TCG_OVERSIZED_GUEST
return *ptr;
#if TARGET_LONG_BITS == 32
/* Use qatomic_read, in case of addr_write; only care about low bits. */
const uint32_t *ptr = (uint32_t *)&entry->addr_idx[access_type];
ptr += HOST_BIG_ENDIAN;
return qatomic_read(ptr);
#else
const uint64_t *ptr = &entry->addr_idx[access_type];
# if TCG_OVERSIZED_GUEST
return *ptr;
# else
/* ofs might correspond to .addr_write, so use qatomic_read */
return qatomic_read(ptr);
# endif
#endif
}

View file

@ -24,20 +24,9 @@
#ifdef CONFIG_TCG
#include "exec/cpu_ldst.h"
#endif
#include "qemu/interval-tree.h"
#include "exec/translation-block.h"
#include "qemu/clang-tsa.h"
/* Page tracking code uses ram addresses in system mode, and virtual
addresses in userspace mode. Define tb_page_addr_t to be an appropriate
type. */
#if defined(CONFIG_USER_ONLY)
typedef abi_ulong tb_page_addr_t;
#define TB_PAGE_ADDR_FMT TARGET_ABI_FMT_lx
#else
typedef ram_addr_t tb_page_addr_t;
#define TB_PAGE_ADDR_FMT RAM_ADDR_FMT
#endif
/**
* cpu_unwind_state_data:
* @cpu: the cpu context
@ -478,135 +467,6 @@ int probe_access_full(CPUArchState *env, target_ulong addr, int size,
CPUTLBEntryFull **pfull, uintptr_t retaddr);
#endif
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
/* Estimated block size for TB allocation. */
/* ??? The following is based on a 2015 survey of x86_64 host output.
Better would seem to be some sort of dynamically sized TB array,
adapting to the block sizes actually being produced. */
#if defined(CONFIG_SOFTMMU)
#define CODE_GEN_AVG_BLOCK_SIZE 400
#else
#define CODE_GEN_AVG_BLOCK_SIZE 150
#endif
/*
* Translation Cache-related fields of a TB.
* This struct exists just for convenience; we keep track of TB's in a binary
* search tree, and the only fields needed to compare TB's in the tree are
* @ptr and @size.
* Note: the address of search data can be obtained by adding @size to @ptr.
*/
struct tb_tc {
const void *ptr; /* pointer to the translated code */
size_t size;
};
struct TranslationBlock {
/*
* Guest PC corresponding to this block. This must be the true
* virtual address. Therefore e.g. x86 stores EIP + CS_BASE, and
* targets like Arm, MIPS, HP-PA, which reuse low bits for ISA or
* privilege, must store those bits elsewhere.
*
* If CF_PCREL, the opcodes for the TranslationBlock are written
* such that the TB is associated only with the physical page and
* may be run in any virtual address context. In this case, PC
* must always be taken from ENV in a target-specific manner.
* Unwind information is taken as offsets from the page, to be
* deposited into the "current" PC.
*/
target_ulong pc;
/*
* Target-specific data associated with the TranslationBlock, e.g.:
* x86: the original user, the Code Segment virtual base,
* arm: an extension of tb->flags,
* s390x: instruction data for EXECUTE,
* sparc: the next pc of the instruction queue (for delay slots).
*/
target_ulong cs_base;
uint32_t flags; /* flags defining in which context the code was generated */
uint32_t cflags; /* compile flags */
/* Note that TCG_MAX_INSNS is 512; we validate this match elsewhere. */
#define CF_COUNT_MASK 0x000001ff
#define CF_NO_GOTO_TB 0x00000200 /* Do not chain with goto_tb */
#define CF_NO_GOTO_PTR 0x00000400 /* Do not chain with goto_ptr */
#define CF_SINGLE_STEP 0x00000800 /* gdbstub single-step in effect */
#define CF_LAST_IO 0x00008000 /* Last insn may be an IO access. */
#define CF_MEMI_ONLY 0x00010000 /* Only instrument memory ops */
#define CF_USE_ICOUNT 0x00020000
#define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */
#define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */
#define CF_NOIRQ 0x00100000 /* Generate an uninterruptible TB */
#define CF_PCREL 0x00200000 /* Opcodes in TB are PC-relative */
#define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */
#define CF_CLUSTER_SHIFT 24
/*
* Above fields used for comparing
*/
/* size of target code for this block (1 <= size <= TARGET_PAGE_SIZE) */
uint16_t size;
uint16_t icount;
struct tb_tc tc;
/*
* Track tb_page_addr_t intervals that intersect this TB.
* For user-only, the virtual addresses are always contiguous,
* and we use a unified interval tree. For system, we use a
* linked list headed in each PageDesc. Within the list, the lsb
* of the previous pointer tells the index of page_next[], and the
* list is protected by the PageDesc lock(s).
*/
#ifdef CONFIG_USER_ONLY
IntervalTreeNode itree;
#else
uintptr_t page_next[2];
tb_page_addr_t page_addr[2];
#endif
/* jmp_lock placed here to fill a 4-byte hole. Its documentation is below */
QemuSpin jmp_lock;
/* The following data are used to directly call another TB from
* the code of this one. This can be done either by emitting direct or
* indirect native jump instructions. These jumps are reset so that the TB
* just continues its execution. The TB can be linked to another one by
* setting one of the jump targets (or patching the jump instruction). Only
* two of such jumps are supported.
*/
#define TB_JMP_OFFSET_INVALID 0xffff /* indicates no jump generated */
uint16_t jmp_reset_offset[2]; /* offset of original jump target */
uint16_t jmp_insn_offset[2]; /* offset of direct jump insn */
uintptr_t jmp_target_addr[2]; /* target address */
/*
* Each TB has a NULL-terminated list (jmp_list_head) of incoming jumps.
* Each TB can have two outgoing jumps, and therefore can participate
* in two lists. The list entries are kept in jmp_list_next[2]. The least
* significant bit (LSB) of the pointers in these lists is used to encode
* which of the two list entries is to be used in the pointed TB.
*
* List traversals are protected by jmp_lock. The destination TB of each
* outgoing jump is kept in jmp_dest[] so that the appropriate jmp_lock
* can be acquired from any origin TB.
*
* jmp_dest[] are tagged pointers as well. The LSB is set when the TB is
* being invalidated, so that no further outgoing jumps from it can be set.
*
* jmp_lock also protects the CF_INVALID cflag; a jump must not be chained
* to a destination TB that has CF_INVALID set.
*/
uintptr_t jmp_list_head;
uintptr_t jmp_list_next[2];
uintptr_t jmp_dest[2];
};
/* Hide the qatomic_read to make code a little easier on the eyes */
static inline uint32_t tb_cflags(const TranslationBlock *tb)
{

View file

@ -1,83 +0,0 @@
#ifndef GEN_ICOUNT_H
#define GEN_ICOUNT_H
#include "exec/exec-all.h"
/* Helpers for instruction counting code generation. */
static TCGOp *icount_start_insn;
static inline void gen_io_start(void)
{
tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
offsetof(ArchCPU, parent_obj.can_do_io) -
offsetof(ArchCPU, env));
}
static inline void gen_tb_start(const TranslationBlock *tb)
{
TCGv_i32 count = tcg_temp_new_i32();
tcg_gen_ld_i32(count, cpu_env,
offsetof(ArchCPU, neg.icount_decr.u32) -
offsetof(ArchCPU, env));
if (tb_cflags(tb) & CF_USE_ICOUNT) {
/*
* We emit a sub with a dummy immediate argument. Keep the insn index
* of the sub so that we later (when we know the actual insn count)
* can update the argument with the actual insn count.
*/
tcg_gen_sub_i32(count, count, tcg_constant_i32(0));
icount_start_insn = tcg_last_op();
}
/*
* Emit the check against icount_decr.u32 to see if we should exit
* unless we suppress the check with CF_NOIRQ. If we are using
* icount and have suppressed interruption the higher level code
* should have ensured we don't run more instructions than the
* budget.
*/
if (tb_cflags(tb) & CF_NOIRQ) {
tcg_ctx->exitreq_label = NULL;
} else {
tcg_ctx->exitreq_label = gen_new_label();
tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label);
}
if (tb_cflags(tb) & CF_USE_ICOUNT) {
tcg_gen_st16_i32(count, cpu_env,
offsetof(ArchCPU, neg.icount_decr.u16.low) -
offsetof(ArchCPU, env));
/*
* cpu->can_do_io is cleared automatically here at the beginning of
* each translation block. The cost is minimal and only paid for
* -icount, plus it would be very easy to forget doing it in the
* translator. Doing it here means we don't need a gen_io_end() to
* go with gen_io_start().
*/
tcg_gen_st_i32(tcg_constant_i32(0), cpu_env,
offsetof(ArchCPU, parent_obj.can_do_io) -
offsetof(ArchCPU, env));
}
}
static inline void gen_tb_end(const TranslationBlock *tb, int num_insns)
{
if (tb_cflags(tb) & CF_USE_ICOUNT) {
/*
* Update the num_insn immediate parameter now that we know
* the actual insn count.
*/
tcg_set_insn_param(icount_start_insn, 2,
tcgv_i32_arg(tcg_constant_i32(num_insns)));
}
if (tcg_ctx->exitreq_label) {
gen_set_label(tcg_ctx->exitreq_label);
tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED);
}
}
#endif

View file

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Helper file for declaring TCG helper functions.
* This one expands generation functions for tcg opcodes.
*/
#ifndef HELPER_GEN_COMMON_H
#define HELPER_GEN_COMMON_H
#define HELPER_H "accel/tcg/tcg-runtime.h"
#include "exec/helper-gen.h.inc"
#undef HELPER_H
#define HELPER_H "accel/tcg/plugin-helpers.h"
#include "exec/helper-gen.h.inc"
#undef HELPER_H
#endif /* HELPER_GEN_COMMON_H */

View file

@ -1,95 +1,16 @@
/* Helper file for declaring TCG helper functions.
This one expands generation functions for tcg opcodes. */
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Helper file for declaring TCG helper functions.
* This one expands generation functions for tcg opcodes.
*/
#ifndef HELPER_GEN_H
#define HELPER_GEN_H
#include "exec/helper-head.h"
#include "exec/helper-gen-common.h"
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
static inline void glue(gen_helper_, name)(dh_retvar_decl0(ret)) \
{ \
tcg_gen_callN(HELPER(name), dh_retvar(ret), 0, NULL); \
}
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1)) \
{ \
TCGTemp *args[1] = { dh_arg(t1, 1) }; \
tcg_gen_callN(HELPER(name), dh_retvar(ret), 1, args); \
}
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2)) \
{ \
TCGTemp *args[2] = { dh_arg(t1, 1), dh_arg(t2, 2) }; \
tcg_gen_callN(HELPER(name), dh_retvar(ret), 2, args); \
}
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \
{ \
TCGTemp *args[3] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3) }; \
tcg_gen_callN(HELPER(name), dh_retvar(ret), 3, args); \
}
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \
dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) \
{ \
TCGTemp *args[4] = { dh_arg(t1, 1), dh_arg(t2, 2), \
dh_arg(t3, 3), dh_arg(t4, 4) }; \
tcg_gen_callN(HELPER(name), dh_retvar(ret), 4, args); \
}
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) \
{ \
TCGTemp *args[5] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
dh_arg(t4, 4), dh_arg(t5, 5) }; \
tcg_gen_callN(HELPER(name), dh_retvar(ret), 5, args); \
}
#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6)) \
{ \
TCGTemp *args[6] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6) }; \
tcg_gen_callN(HELPER(name), dh_retvar(ret), 6, args); \
}
#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7)\
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6), \
dh_arg_decl(t7, 7)) \
{ \
TCGTemp *args[7] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6), \
dh_arg(t7, 7) }; \
tcg_gen_callN(HELPER(name), dh_retvar(ret), 7, args); \
}
#include "helper.h"
#include "accel/tcg/tcg-runtime.h"
#include "accel/tcg/plugin-helpers.h"
#undef DEF_HELPER_FLAGS_0
#undef DEF_HELPER_FLAGS_1
#undef DEF_HELPER_FLAGS_2
#undef DEF_HELPER_FLAGS_3
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
#undef DEF_HELPER_FLAGS_6
#undef DEF_HELPER_FLAGS_7
#undef GEN_HELPER
#define HELPER_H "helper.h"
#include "exec/helper-gen.h.inc"
#undef HELPER_H
#endif /* HELPER_GEN_H */

View file

@ -0,0 +1,102 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Helper file for declaring TCG helper functions.
* This one expands generation functions for tcg opcodes.
* Define HELPER_H for the header file to be expanded,
* and static inline to change from global file scope.
*/
#include "tcg/tcg.h"
#include "tcg/helper-info.h"
#include "exec/helper-head.h"
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
extern TCGHelperInfo glue(helper_info_, name); \
static inline void glue(gen_helper_, name)(dh_retvar_decl0(ret)) \
{ \
tcg_gen_call0(&glue(helper_info_, name), dh_retvar(ret)); \
}
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
extern TCGHelperInfo glue(helper_info_, name); \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1)) \
{ \
tcg_gen_call1(&glue(helper_info_, name), dh_retvar(ret), \
dh_arg(t1, 1)); \
}
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
extern TCGHelperInfo glue(helper_info_, name); \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2)) \
{ \
tcg_gen_call2(&glue(helper_info_, name), dh_retvar(ret), \
dh_arg(t1, 1), dh_arg(t2, 2)); \
}
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
extern TCGHelperInfo glue(helper_info_, name); \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \
{ \
tcg_gen_call3(&glue(helper_info_, name), dh_retvar(ret), \
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3)); \
}
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
extern TCGHelperInfo glue(helper_info_, name); \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \
dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) \
{ \
tcg_gen_call4(&glue(helper_info_, name), dh_retvar(ret), \
dh_arg(t1, 1), dh_arg(t2, 2), \
dh_arg(t3, 3), dh_arg(t4, 4)); \
}
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
extern TCGHelperInfo glue(helper_info_, name); \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) \
{ \
tcg_gen_call5(&glue(helper_info_, name), dh_retvar(ret), \
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
dh_arg(t4, 4), dh_arg(t5, 5)); \
}
#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
extern TCGHelperInfo glue(helper_info_, name); \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6)) \
{ \
tcg_gen_call6(&glue(helper_info_, name), dh_retvar(ret), \
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6)); \
}
#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7)\
extern TCGHelperInfo glue(helper_info_, name); \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6), \
dh_arg_decl(t7, 7)) \
{ \
tcg_gen_call7(&glue(helper_info_, name), dh_retvar(ret), \
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6), \
dh_arg(t7, 7)); \
}
#include HELPER_H
#undef DEF_HELPER_FLAGS_0
#undef DEF_HELPER_FLAGS_1
#undef DEF_HELPER_FLAGS_2
#undef DEF_HELPER_FLAGS_3
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
#undef DEF_HELPER_FLAGS_6
#undef DEF_HELPER_FLAGS_7

View file

@ -1,18 +1,6 @@
/* Helper file for declaring TCG helper functions.
Used by other helper files.
Targets should use DEF_HELPER_N and DEF_HELPER_FLAGS_N to declare helper
functions. Names should be specified without the helper_ prefix, and
the return and argument types specified. 3 basic types are understood
(i32, i64 and ptr). Additional aliases are provided for convenience and
to match the types used by the C helper implementation.
The target helper.h should be included in all files that use/define
helper functions. THis will ensure that function prototypes are
consistent. In addition it should be included an extra two times for
helper.c, defining:
GEN_HELPER 1 to produce op generation functions (gen_helper_*)
GEN_HELPER 2 to do runtime registration helper functions.
/*
* Helper file for declaring TCG helper functions.
* Used by other helper files.
*/
#ifndef EXEC_HELPER_HEAD_H
@ -34,6 +22,7 @@
#define dh_alias_f64 i64
#define dh_alias_ptr ptr
#define dh_alias_cptr ptr
#define dh_alias_env ptr
#define dh_alias_void void
#define dh_alias_noreturn noreturn
#define dh_alias(t) glue(dh_alias_, t)
@ -49,6 +38,7 @@
#define dh_ctype_f64 float64
#define dh_ctype_ptr void *
#define dh_ctype_cptr const void *
#define dh_ctype_env CPUArchState *
#define dh_ctype_void void
#define dh_ctype_noreturn G_NORETURN void
#define dh_ctype(t) dh_ctype_##t
@ -64,9 +54,6 @@
# endif
# endif
# define dh_ctype_tl target_ulong
# define dh_alias_env ptr
# define dh_ctype_env CPUArchState *
# define dh_typecode_env dh_typecode_ptr
#endif
/* We can't use glue() here because it falls foul of C preprocessor
@ -108,6 +95,7 @@
#define dh_typecode_f32 dh_typecode_i32
#define dh_typecode_f64 dh_typecode_i64
#define dh_typecode_cptr dh_typecode_ptr
#define dh_typecode_env dh_typecode_ptr
#define dh_typecode(t) dh_typecode_##t
#define dh_callflag_i32 0

View file

@ -0,0 +1,96 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Helper file for declaring TCG helper functions.
* This one expands info structures for tcg helpers.
* Define HELPER_H for the header file to be expanded.
*/
#include "tcg/tcg.h"
#include "tcg/helper-info.h"
#include "exec/helper-head.h"
/*
* Need one more level of indirection before stringification
* to get all the macros expanded first.
*/
#define str(s) #s
#define DEF_HELPER_FLAGS_0(NAME, FLAGS, RET) \
TCGHelperInfo glue(helper_info_, NAME) = { \
.func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(RET), \
.typemask = dh_typemask(RET, 0) \
};
#define DEF_HELPER_FLAGS_1(NAME, FLAGS, RET, T1) \
TCGHelperInfo glue(helper_info_, NAME) = { \
.func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(RET), \
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
};
#define DEF_HELPER_FLAGS_2(NAME, FLAGS, RET, T1, T2) \
TCGHelperInfo glue(helper_info_, NAME) = { \
.func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(RET), \
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
| dh_typemask(T2, 2) \
};
#define DEF_HELPER_FLAGS_3(NAME, FLAGS, RET, T1, T2, T3) \
TCGHelperInfo glue(helper_info_, NAME) = { \
.func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(RET), \
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
};
#define DEF_HELPER_FLAGS_4(NAME, FLAGS, RET, T1, T2, T3, T4) \
TCGHelperInfo glue(helper_info_, NAME) = { \
.func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(RET), \
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
| dh_typemask(T4, 4) \
};
#define DEF_HELPER_FLAGS_5(NAME, FLAGS, RET, T1, T2, T3, T4, T5) \
TCGHelperInfo glue(helper_info_, NAME) = { \
.func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(RET), \
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
| dh_typemask(T4, 4) | dh_typemask(T5, 5) \
};
#define DEF_HELPER_FLAGS_6(NAME, FLAGS, RET, T1, T2, T3, T4, T5, T6) \
TCGHelperInfo glue(helper_info_, NAME) = { \
.func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(RET), \
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
| dh_typemask(T4, 4) | dh_typemask(T5, 5) \
| dh_typemask(T6, 6) \
};
#define DEF_HELPER_FLAGS_7(NAME, FLAGS, RET, T1, T2, T3, T4, T5, T6, T7) \
TCGHelperInfo glue(helper_info_, NAME) = { \
.func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(RET), \
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
| dh_typemask(T4, 4) | dh_typemask(T5, 5) \
| dh_typemask(T6, 6) | dh_typemask(T7, 7) \
};
#include HELPER_H
#undef str
#undef DEF_HELPER_FLAGS_0
#undef DEF_HELPER_FLAGS_1
#undef DEF_HELPER_FLAGS_2
#undef DEF_HELPER_FLAGS_3
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
#undef DEF_HELPER_FLAGS_6
#undef DEF_HELPER_FLAGS_7

View file

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Helper file for declaring TCG helper functions.
* This one expands prototypes for the helper functions.
*/
#ifndef HELPER_PROTO_COMMON_H
#define HELPER_PROTO_COMMON_H
#define HELPER_H "accel/tcg/tcg-runtime.h"
#include "exec/helper-proto.h.inc"
#undef HELPER_H
#define HELPER_H "accel/tcg/plugin-helpers.h"
#include "exec/helper-proto.h.inc"
#undef HELPER_H
#endif /* HELPER_PROTO_COMMON_H */

View file

@ -1,71 +1,16 @@
/* Helper file for declaring TCG helper functions.
This one expands prototypes for the helper functions. */
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Helper file for declaring TCG helper functions.
* This one expands prototypes for the helper functions.
*/
#ifndef HELPER_PROTO_H
#define HELPER_PROTO_H
#include "exec/helper-head.h"
#include "exec/helper-proto-common.h"
/*
* Work around an issue with --enable-lto, in which GCC's ipa-split pass
* decides to split out the noreturn code paths that raise an exception,
* taking the __builtin_return_address() along into the new function,
* where it no longer computes a value that returns to TCG generated code.
* Despite the name, the noinline attribute affects splitter, so this
* prevents the optimization in question. Given that helpers should not
* otherwise be called directly, this should have any other visible effect.
*
* See https://gitlab.com/qemu-project/qemu/-/issues/1454
*/
#define DEF_HELPER_ATTR __attribute__((noinline))
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
dh_ctype(ret) HELPER(name) (void) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), \
dh_ctype(t3)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4), dh_ctype(t5)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4), dh_ctype(t5), \
dh_ctype(t6)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4), dh_ctype(t5), dh_ctype(t6), \
dh_ctype(t7)) DEF_HELPER_ATTR;
#define IN_HELPER_PROTO
#include "helper.h"
#include "accel/tcg/tcg-runtime.h"
#include "accel/tcg/plugin-helpers.h"
#undef IN_HELPER_PROTO
#undef DEF_HELPER_FLAGS_0
#undef DEF_HELPER_FLAGS_1
#undef DEF_HELPER_FLAGS_2
#undef DEF_HELPER_FLAGS_3
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
#undef DEF_HELPER_FLAGS_6
#undef DEF_HELPER_FLAGS_7
#undef DEF_HELPER_ATTR
#define HELPER_H "helper.h"
#include "exec/helper-proto.h.inc"
#undef HELPER_H
#endif /* HELPER_PROTO_H */

View file

@ -0,0 +1,68 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Helper file for declaring TCG helper functions.
* This one expands prototypes for the helper functions.
* Define HELPER_H for the header file to be expanded.
*/
#include "exec/helper-head.h"
/*
* Work around an issue with --enable-lto, in which GCC's ipa-split pass
* decides to split out the noreturn code paths that raise an exception,
* taking the __builtin_return_address() along into the new function,
* where it no longer computes a value that returns to TCG generated code.
* Despite the name, the noinline attribute affects splitter, so this
* prevents the optimization in question. Given that helpers should not
* otherwise be called directly, this should not have any other visible effect.
*
* See https://gitlab.com/qemu-project/qemu/-/issues/1454
*/
#define DEF_HELPER_ATTR __attribute__((noinline))
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
dh_ctype(ret) HELPER(name) (void) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), \
dh_ctype(t3)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4), dh_ctype(t5)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4), dh_ctype(t5), \
dh_ctype(t6)) DEF_HELPER_ATTR;
#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4), dh_ctype(t5), dh_ctype(t6), \
dh_ctype(t7)) DEF_HELPER_ATTR;
#define IN_HELPER_PROTO
#include HELPER_H
#undef IN_HELPER_PROTO
#undef DEF_HELPER_FLAGS_0
#undef DEF_HELPER_FLAGS_1
#undef DEF_HELPER_FLAGS_2
#undef DEF_HELPER_FLAGS_3
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
#undef DEF_HELPER_FLAGS_6
#undef DEF_HELPER_FLAGS_7
#undef DEF_HELPER_ATTR

View file

@ -1,75 +0,0 @@
/* Helper file for declaring TCG helper functions.
This one defines data structures private to tcg.c. */
#ifndef HELPER_TCG_H
#define HELPER_TCG_H
#include "exec/helper-head.h"
/* Need one more level of indirection before stringification
to get all the macros expanded first. */
#define str(s) #s
#define DEF_HELPER_FLAGS_0(NAME, FLAGS, ret) \
{ .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \
.typemask = dh_typemask(ret, 0) },
#define DEF_HELPER_FLAGS_1(NAME, FLAGS, ret, t1) \
{ .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) },
#define DEF_HELPER_FLAGS_2(NAME, FLAGS, ret, t1, t2) \
{ .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_typemask(t2, 2) },
#define DEF_HELPER_FLAGS_3(NAME, FLAGS, ret, t1, t2, t3) \
{ .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_typemask(t2, 2) | dh_typemask(t3, 3) },
#define DEF_HELPER_FLAGS_4(NAME, FLAGS, ret, t1, t2, t3, t4) \
{ .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) },
#define DEF_HELPER_FLAGS_5(NAME, FLAGS, ret, t1, t2, t3, t4, t5) \
{ .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) \
| dh_typemask(t5, 5) },
#define DEF_HELPER_FLAGS_6(NAME, FLAGS, ret, t1, t2, t3, t4, t5, t6) \
{ .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) \
| dh_typemask(t5, 5) | dh_typemask(t6, 6) },
#define DEF_HELPER_FLAGS_7(NAME, FLAGS, ret, t1, t2, t3, t4, t5, t6, t7) \
{ .func = HELPER(NAME), .name = str(NAME), .flags = FLAGS, \
.typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) \
| dh_typemask(t5, 5) | dh_typemask(t6, 6) | dh_typemask(t7, 7) },
#include "helper.h"
#include "accel/tcg/tcg-runtime.h"
#include "accel/tcg/plugin-helpers.h"
#undef str
#undef DEF_HELPER_FLAGS_0
#undef DEF_HELPER_FLAGS_1
#undef DEF_HELPER_FLAGS_2
#undef DEF_HELPER_FLAGS_3
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
#undef DEF_HELPER_FLAGS_6
#undef DEF_HELPER_FLAGS_7
#endif /* HELPER_TCG_H */

View file

@ -12,8 +12,6 @@
#ifndef QEMU_PLUGIN_GEN_H
#define QEMU_PLUGIN_GEN_H
#include "exec/cpu_ldst.h"
#include "qemu/plugin.h"
#include "tcg/tcg.h"
struct DisasContextBase;
@ -29,25 +27,6 @@ void plugin_gen_insn_end(void);
void plugin_gen_disable_mem_helpers(void);
void plugin_gen_empty_mem_callback(TCGv_i64 addr, uint32_t info);
static inline void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
{
struct qemu_plugin_insn *insn = tcg_ctx->plugin_insn;
abi_ptr off;
if (insn == NULL) {
return;
}
off = pc - insn->vaddr;
if (off < insn->data->len) {
g_byte_array_set_size(insn->data, off);
} else if (off > insn->data->len) {
/* we have an unexpected gap */
g_assert_not_reached();
}
insn->data = g_byte_array_append(insn->data, from, size);
}
#else /* !CONFIG_PLUGIN */
static inline bool
@ -72,9 +51,6 @@ static inline void plugin_gen_disable_mem_helpers(void)
static inline void plugin_gen_empty_mem_callback(TCGv_i64 addr, uint32_t info)
{ }
static inline void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
{ }
#endif /* CONFIG_PLUGIN */
#endif /* QEMU_PLUGIN_GEN_H */

View file

@ -85,7 +85,6 @@
#pragma GCC poison CONFIG_HVF
#pragma GCC poison CONFIG_LINUX_USER
#pragma GCC poison CONFIG_KVM
#pragma GCC poison CONFIG_SOFTMMU
#pragma GCC poison CONFIG_WHPX
#pragma GCC poison CONFIG_XEN

56
include/exec/tlb-common.h Normal file
View file

@ -0,0 +1,56 @@
/*
* Common definitions for the softmmu tlb
*
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EXEC_TLB_COMMON_H
#define EXEC_TLB_COMMON_H 1
#define CPU_TLB_ENTRY_BITS 5
/* Minimalized TLB entry for use by TCG fast path. */
typedef union CPUTLBEntry {
struct {
uint64_t addr_read;
uint64_t addr_write;
uint64_t addr_code;
/*
* Addend to virtual address to get host address. IO accesses
* use the corresponding iotlb value.
*/
uintptr_t addend;
};
/*
* Padding to get a power of two size, as well as index
* access to addr_{read,write,code}.
*/
uint64_t addr_idx[(1 << CPU_TLB_ENTRY_BITS) / sizeof(uint64_t)];
} CPUTLBEntry;
QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
/*
* Data elements that are per MMU mode, accessed by the fast path.
* The structure is aligned to aid loading the pair with one insn.
*/
typedef struct CPUTLBDescFast {
/* Contains (n_entries - 1) << CPU_TLB_ENTRY_BITS */
uintptr_t mask;
/* The array of tlb entries itself. */
CPUTLBEntry *table;
} CPUTLBDescFast QEMU_ALIGNED(2 * sizeof(void *));
#endif /* EXEC_TLB_COMMON_H */

View file

@ -0,0 +1,149 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Definition of TranslationBlock.
* Copyright (c) 2003 Fabrice Bellard
*/
#ifndef EXEC_TRANSLATION_BLOCK_H
#define EXEC_TRANSLATION_BLOCK_H
#include "qemu/atomic.h"
#include "qemu/thread.h"
#include "qemu/interval-tree.h"
#include "exec/cpu-common.h"
#include "exec/target_page.h"
/*
* Page tracking code uses ram addresses in system mode, and virtual
* addresses in userspace mode. Define tb_page_addr_t to be an
* appropriate type.
*/
#if defined(CONFIG_USER_ONLY)
typedef vaddr tb_page_addr_t;
#define TB_PAGE_ADDR_FMT "%" VADDR_PRIx
#else
typedef ram_addr_t tb_page_addr_t;
#define TB_PAGE_ADDR_FMT RAM_ADDR_FMT
#endif
/*
* Translation Cache-related fields of a TB.
* This struct exists just for convenience; we keep track of TB's in a binary
* search tree, and the only fields needed to compare TB's in the tree are
* @ptr and @size.
* Note: the address of search data can be obtained by adding @size to @ptr.
*/
struct tb_tc {
const void *ptr; /* pointer to the translated code */
size_t size;
};
struct TranslationBlock {
/*
* Guest PC corresponding to this block. This must be the true
* virtual address. Therefore e.g. x86 stores EIP + CS_BASE, and
* targets like Arm, MIPS, HP-PA, which reuse low bits for ISA or
* privilege, must store those bits elsewhere.
*
* If CF_PCREL, the opcodes for the TranslationBlock are written
* such that the TB is associated only with the physical page and
* may be run in any virtual address context. In this case, PC
* must always be taken from ENV in a target-specific manner.
* Unwind information is taken as offsets from the page, to be
* deposited into the "current" PC.
*/
vaddr pc;
/*
* Target-specific data associated with the TranslationBlock, e.g.:
* x86: the original user, the Code Segment virtual base,
* arm: an extension of tb->flags,
* s390x: instruction data for EXECUTE,
* sparc: the next pc of the instruction queue (for delay slots).
*/
uint64_t cs_base;
uint32_t flags; /* flags defining in which context the code was generated */
uint32_t cflags; /* compile flags */
/* Note that TCG_MAX_INSNS is 512; we validate this match elsewhere. */
#define CF_COUNT_MASK 0x000001ff
#define CF_NO_GOTO_TB 0x00000200 /* Do not chain with goto_tb */
#define CF_NO_GOTO_PTR 0x00000400 /* Do not chain with goto_ptr */
#define CF_SINGLE_STEP 0x00000800 /* gdbstub single-step in effect */
#define CF_LAST_IO 0x00008000 /* Last insn may be an IO access. */
#define CF_MEMI_ONLY 0x00010000 /* Only instrument memory ops */
#define CF_USE_ICOUNT 0x00020000
#define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */
#define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */
#define CF_NOIRQ 0x00100000 /* Generate an uninterruptible TB */
#define CF_PCREL 0x00200000 /* Opcodes in TB are PC-relative */
#define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */
#define CF_CLUSTER_SHIFT 24
/*
* Above fields used for comparing
*/
/* size of target code for this block (1 <= size <= TARGET_PAGE_SIZE) */
uint16_t size;
uint16_t icount;
struct tb_tc tc;
/*
* Track tb_page_addr_t intervals that intersect this TB.
* For user-only, the virtual addresses are always contiguous,
* and we use a unified interval tree. For system, we use a
* linked list headed in each PageDesc. Within the list, the lsb
* of the previous pointer tells the index of page_next[], and the
* list is protected by the PageDesc lock(s).
*/
#ifdef CONFIG_USER_ONLY
IntervalTreeNode itree;
#else
uintptr_t page_next[2];
tb_page_addr_t page_addr[2];
#endif
/* jmp_lock placed here to fill a 4-byte hole. Its documentation is below */
QemuSpin jmp_lock;
/* The following data are used to directly call another TB from
* the code of this one. This can be done either by emitting direct or
* indirect native jump instructions. These jumps are reset so that the TB
* just continues its execution. The TB can be linked to another one by
* setting one of the jump targets (or patching the jump instruction). Only
* two of such jumps are supported.
*/
#define TB_JMP_OFFSET_INVALID 0xffff /* indicates no jump generated */
uint16_t jmp_reset_offset[2]; /* offset of original jump target */
uint16_t jmp_insn_offset[2]; /* offset of direct jump insn */
uintptr_t jmp_target_addr[2]; /* target address */
/*
* Each TB has a NULL-terminated list (jmp_list_head) of incoming jumps.
* Each TB can have two outgoing jumps, and therefore can participate
* in two lists. The list entries are kept in jmp_list_next[2]. The least
* significant bit (LSB) of the pointers in these lists is used to encode
* which of the two list entries is to be used in the pointed TB.
*
* List traversals are protected by jmp_lock. The destination TB of each
* outgoing jump is kept in jmp_dest[] so that the appropriate jmp_lock
* can be acquired from any origin TB.
*
* jmp_dest[] are tagged pointers as well. The LSB is set when the TB is
* being invalidated, so that no further outgoing jumps from it can be set.
*
* jmp_lock also protects the CF_INVALID cflag; a jump must not be chained
* to a destination TB that has CF_INVALID set.
*/
uintptr_t jmp_list_head;
uintptr_t jmp_list_next[2];
uintptr_t jmp_dest[2];
};
/* The alignment given to TranslationBlock during allocation. */
#define CODE_GEN_ALIGN 16
#endif /* EXEC_TRANSLATION_BLOCK_H */

View file

@ -18,13 +18,8 @@
* member in your target-specific DisasContext.
*/
#include "qemu/bswap.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
#include "exec/plugin-gen.h"
#include "exec/translate-all.h"
#include "tcg/tcg.h"
#include "exec/cpu_ldst.h" /* for abi_ptr */
/**
* gen_intermediate_code
@ -160,6 +155,16 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
*/
bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest);
/**
* translator_io_start
* @db: Disassembly context
*
* If icount is enabled, set cpu->can_to_io, adjust db->is_jmp to
* DISAS_TOO_MANY if it is still DISAS_NEXT, and return true.
* Otherwise return false.
*/
bool translator_io_start(DisasContextBase *db);
/*
* Translator Load Functions
*
@ -219,12 +224,7 @@ translator_ldq_swap(CPUArchState *env, DisasContextBase *db,
* re-synthesised for s390x "ex"). It ensures we update other areas of
* the translator with details of the executed instruction.
*/
static inline void translator_fake_ldb(uint8_t insn8, abi_ptr pc)
{
plugin_insn_append(pc, &insn8, sizeof(insn8));
}
void translator_fake_ldb(uint8_t insn8, abi_ptr pc);
/*
* Return whether addr is on the same page as where disassembly started.

View file

@ -131,6 +131,7 @@ typedef struct ReservedRegion ReservedRegion;
typedef struct SavedIOTLB SavedIOTLB;
typedef struct SHPCDevice SHPCDevice;
typedef struct SSIBus SSIBus;
typedef struct TCGHelperInfo TCGHelperInfo;
typedef struct TranslationBlock TranslationBlock;
typedef struct VirtIODevice VirtIODevice;
typedef struct Visitor Visitor;

64
include/tcg/helper-info.h Normal file
View file

@ -0,0 +1,64 @@
/*
* TCG Helper Infomation Structure
*
* Copyright (c) 2023 Linaro Ltd
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef TCG_HELPER_INFO_H
#define TCG_HELPER_INFO_H
#ifdef CONFIG_TCG_INTERPRETER
#include <ffi.h>
#endif
/*
* Describe the calling convention of a given argument type.
*/
typedef enum {
TCG_CALL_RET_NORMAL, /* by registers */
TCG_CALL_RET_BY_REF, /* for i128, by reference */
TCG_CALL_RET_BY_VEC, /* for i128, by vector register */
} TCGCallReturnKind;
typedef enum {
TCG_CALL_ARG_NORMAL, /* by registers (continuing onto stack) */
TCG_CALL_ARG_EVEN, /* like normal, but skipping odd slots */
TCG_CALL_ARG_EXTEND, /* for i32, as a sign/zero-extended i64 */
TCG_CALL_ARG_EXTEND_U, /* ... as a zero-extended i64 */
TCG_CALL_ARG_EXTEND_S, /* ... as a sign-extended i64 */
TCG_CALL_ARG_BY_REF, /* for i128, by reference, first */
TCG_CALL_ARG_BY_REF_N, /* ... by reference, subsequent */
} TCGCallArgumentKind;
typedef struct TCGCallArgumentLoc {
TCGCallArgumentKind kind : 8;
unsigned arg_slot : 8;
unsigned ref_slot : 8;
unsigned arg_idx : 4;
unsigned tmp_subindex : 2;
} TCGCallArgumentLoc;
struct TCGHelperInfo {
void *func;
const char *name;
/* Used with g_once_init_enter. */
#ifdef CONFIG_TCG_INTERPRETER
ffi_cif *cif;
#else
uintptr_t init;
#endif
unsigned typemask : 32;
unsigned flags : 8;
unsigned nr_in : 8;
unsigned nr_out : 8;
TCGCallReturnKind out_kind : 8;
/* Maximum physical arguments are constrained by TCG_TYPE_I128. */
TCGCallArgumentLoc in[MAX_CALL_IARGS * (128 / TCG_TARGET_REG_BITS)];
};
#endif /* TCG_HELPER_INFO_H */

View file

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: MIT */
/*
* Define TARGET_INSN_START_WORDS
* Copyright (c) 2008 Fabrice Bellard
*/
#ifndef TARGET_INSN_START_WORDS
#include "cpu.h"
#ifndef TARGET_INSN_START_EXTRA_WORDS
# define TARGET_INSN_START_WORDS 1
#else
# define TARGET_INSN_START_WORDS (1 + TARGET_INSN_START_EXTRA_WORDS)
#endif
#endif /* TARGET_INSN_START_WORDS */

View file

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: MIT */
/*
* Define TCG_OVERSIZED_GUEST
* Copyright (c) 2008 Fabrice Bellard
*/
#ifndef EXEC_TCG_OVERSIZED_GUEST_H
#define EXEC_TCG_OVERSIZED_GUEST_H
#include "tcg-target-reg-bits.h"
#include "cpu-param.h"
/*
* Oversized TCG guests make things like MTTCG hard
* as we can't use atomics for cputlb updates.
*/
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
#define TCG_OVERSIZED_GUEST 1
#else
#define TCG_OVERSIZED_GUEST 0
#endif
#endif

996
include/tcg/tcg-op-common.h Normal file
View file

@ -0,0 +1,996 @@
/* SPDX-License-Identifier: MIT */
/*
* Target independent opcode generation functions.
*
* Copyright (c) 2008 Fabrice Bellard
*/
#ifndef TCG_TCG_OP_COMMON_H
#define TCG_TCG_OP_COMMON_H
#include "tcg/tcg.h"
#include "exec/helper-proto-common.h"
#include "exec/helper-gen-common.h"
/* Basic output routines. Not for general consumption. */
void tcg_gen_op1(TCGOpcode, TCGArg);
void tcg_gen_op2(TCGOpcode, TCGArg, TCGArg);
void tcg_gen_op3(TCGOpcode, TCGArg, TCGArg, TCGArg);
void tcg_gen_op4(TCGOpcode, TCGArg, TCGArg, TCGArg, TCGArg);
void tcg_gen_op5(TCGOpcode, TCGArg, TCGArg, TCGArg, TCGArg, TCGArg);
void tcg_gen_op6(TCGOpcode, TCGArg, TCGArg, TCGArg, TCGArg, TCGArg, TCGArg);
void vec_gen_2(TCGOpcode, TCGType, unsigned, TCGArg, TCGArg);
void vec_gen_3(TCGOpcode, TCGType, unsigned, TCGArg, TCGArg, TCGArg);
void vec_gen_4(TCGOpcode, TCGType, unsigned, TCGArg, TCGArg, TCGArg, TCGArg);
static inline void tcg_gen_op1_i32(TCGOpcode opc, TCGv_i32 a1)
{
tcg_gen_op1(opc, tcgv_i32_arg(a1));
}
static inline void tcg_gen_op1_i64(TCGOpcode opc, TCGv_i64 a1)
{
tcg_gen_op1(opc, tcgv_i64_arg(a1));
}
static inline void tcg_gen_op1i(TCGOpcode opc, TCGArg a1)
{
tcg_gen_op1(opc, a1);
}
static inline void tcg_gen_op2_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2)
{
tcg_gen_op2(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2));
}
static inline void tcg_gen_op2_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2)
{
tcg_gen_op2(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2));
}
static inline void tcg_gen_op2i_i32(TCGOpcode opc, TCGv_i32 a1, TCGArg a2)
{
tcg_gen_op2(opc, tcgv_i32_arg(a1), a2);
}
static inline void tcg_gen_op2i_i64(TCGOpcode opc, TCGv_i64 a1, TCGArg a2)
{
tcg_gen_op2(opc, tcgv_i64_arg(a1), a2);
}
static inline void tcg_gen_op2ii(TCGOpcode opc, TCGArg a1, TCGArg a2)
{
tcg_gen_op2(opc, a1, a2);
}
static inline void tcg_gen_op3_i32(TCGOpcode opc, TCGv_i32 a1,
TCGv_i32 a2, TCGv_i32 a3)
{
tcg_gen_op3(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), tcgv_i32_arg(a3));
}
static inline void tcg_gen_op3_i64(TCGOpcode opc, TCGv_i64 a1,
TCGv_i64 a2, TCGv_i64 a3)
{
tcg_gen_op3(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), tcgv_i64_arg(a3));
}
static inline void tcg_gen_op3i_i32(TCGOpcode opc, TCGv_i32 a1,
TCGv_i32 a2, TCGArg a3)
{
tcg_gen_op3(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), a3);
}
static inline void tcg_gen_op3i_i64(TCGOpcode opc, TCGv_i64 a1,
TCGv_i64 a2, TCGArg a3)
{
tcg_gen_op3(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), a3);
}
static inline void tcg_gen_ldst_op_i32(TCGOpcode opc, TCGv_i32 val,
TCGv_ptr base, TCGArg offset)
{
tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_ptr_arg(base), offset);
}
static inline void tcg_gen_ldst_op_i64(TCGOpcode opc, TCGv_i64 val,
TCGv_ptr base, TCGArg offset)
{
tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_ptr_arg(base), offset);
}
static inline void tcg_gen_op4_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2,
TCGv_i32 a3, TCGv_i32 a4)
{
tcg_gen_op4(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2),
tcgv_i32_arg(a3), tcgv_i32_arg(a4));
}
static inline void tcg_gen_op4_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2,
TCGv_i64 a3, TCGv_i64 a4)
{
tcg_gen_op4(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2),
tcgv_i64_arg(a3), tcgv_i64_arg(a4));
}
static inline void tcg_gen_op4i_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2,
TCGv_i32 a3, TCGArg a4)
{
tcg_gen_op4(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2),
tcgv_i32_arg(a3), a4);
}
static inline void tcg_gen_op4i_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2,
TCGv_i64 a3, TCGArg a4)
{
tcg_gen_op4(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2),
tcgv_i64_arg(a3), a4);
}
static inline void tcg_gen_op4ii_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2,
TCGArg a3, TCGArg a4)
{
tcg_gen_op4(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), a3, a4);
}
static inline void tcg_gen_op4ii_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2,
TCGArg a3, TCGArg a4)
{
tcg_gen_op4(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), a3, a4);
}
static inline void tcg_gen_op5_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2,
TCGv_i32 a3, TCGv_i32 a4, TCGv_i32 a5)
{
tcg_gen_op5(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2),
tcgv_i32_arg(a3), tcgv_i32_arg(a4), tcgv_i32_arg(a5));
}
static inline void tcg_gen_op5_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2,
TCGv_i64 a3, TCGv_i64 a4, TCGv_i64 a5)
{
tcg_gen_op5(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2),
tcgv_i64_arg(a3), tcgv_i64_arg(a4), tcgv_i64_arg(a5));
}
static inline void tcg_gen_op5i_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2,
TCGv_i32 a3, TCGv_i32 a4, TCGArg a5)
{
tcg_gen_op5(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2),
tcgv_i32_arg(a3), tcgv_i32_arg(a4), a5);
}
static inline void tcg_gen_op5i_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2,
TCGv_i64 a3, TCGv_i64 a4, TCGArg a5)
{
tcg_gen_op5(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2),
tcgv_i64_arg(a3), tcgv_i64_arg(a4), a5);
}
static inline void tcg_gen_op5ii_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2,
TCGv_i32 a3, TCGArg a4, TCGArg a5)
{
tcg_gen_op5(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2),
tcgv_i32_arg(a3), a4, a5);
}
static inline void tcg_gen_op5ii_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2,
TCGv_i64 a3, TCGArg a4, TCGArg a5)
{
tcg_gen_op5(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2),
tcgv_i64_arg(a3), a4, a5);
}
static inline void tcg_gen_op6_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2,
TCGv_i32 a3, TCGv_i32 a4,
TCGv_i32 a5, TCGv_i32 a6)
{
tcg_gen_op6(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2),
tcgv_i32_arg(a3), tcgv_i32_arg(a4), tcgv_i32_arg(a5),
tcgv_i32_arg(a6));
}
static inline void tcg_gen_op6_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2,
TCGv_i64 a3, TCGv_i64 a4,
TCGv_i64 a5, TCGv_i64 a6)
{
tcg_gen_op6(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2),
tcgv_i64_arg(a3), tcgv_i64_arg(a4), tcgv_i64_arg(a5),
tcgv_i64_arg(a6));
}
static inline void tcg_gen_op6i_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2,
TCGv_i32 a3, TCGv_i32 a4,
TCGv_i32 a5, TCGArg a6)
{
tcg_gen_op6(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2),
tcgv_i32_arg(a3), tcgv_i32_arg(a4), tcgv_i32_arg(a5), a6);
}
static inline void tcg_gen_op6i_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2,
TCGv_i64 a3, TCGv_i64 a4,
TCGv_i64 a5, TCGArg a6)
{
tcg_gen_op6(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2),
tcgv_i64_arg(a3), tcgv_i64_arg(a4), tcgv_i64_arg(a5), a6);
}
static inline void tcg_gen_op6ii_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2,
TCGv_i32 a3, TCGv_i32 a4,
TCGArg a5, TCGArg a6)
{
tcg_gen_op6(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2),
tcgv_i32_arg(a3), tcgv_i32_arg(a4), a5, a6);
}
static inline void tcg_gen_op6ii_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2,
TCGv_i64 a3, TCGv_i64 a4,
TCGArg a5, TCGArg a6)
{
tcg_gen_op6(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2),
tcgv_i64_arg(a3), tcgv_i64_arg(a4), a5, a6);
}
/* Generic ops. */
static inline void gen_set_label(TCGLabel *l)
{
l->present = 1;
tcg_gen_op1(INDEX_op_set_label, label_arg(l));
}
void tcg_gen_br(TCGLabel *l);
void tcg_gen_mb(TCGBar);
/**
* tcg_gen_exit_tb() - output exit_tb TCG operation
* @tb: The TranslationBlock from which we are exiting
* @idx: Direct jump slot index, or exit request
*
* See tcg/README for more info about this TCG operation.
* See also tcg.h and the block comment above TB_EXIT_MASK.
*
* For a normal exit from the TB, back to the main loop, @tb should
* be NULL and @idx should be 0. Otherwise, @tb should be valid and
* @idx should be one of the TB_EXIT_ values.
*/
void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx);
/**
* tcg_gen_goto_tb() - output goto_tb TCG operation
* @idx: Direct jump slot index (0 or 1)
*
* See tcg/README for more info about this TCG operation.
*
* NOTE: In softmmu emulation, direct jumps with goto_tb are only safe within
* the pages this TB resides in because we don't take care of direct jumps when
* address mapping changes, e.g. in tlb_flush(). In user mode, there's only a
* static address translation, so the destination address is always valid, TBs
* are always invalidated properly, and direct jumps are reset when mapping
* changes.
*/
void tcg_gen_goto_tb(unsigned idx);
/**
* tcg_gen_lookup_and_goto_ptr() - look up the current TB, jump to it if valid
* @addr: Guest address of the target TB
*
* If the TB is not valid, jump to the epilogue.
*
* This operation is optional. If the TCG backend does not implement goto_ptr,
* this op is equivalent to calling tcg_gen_exit_tb() with 0 as the argument.
*/
void tcg_gen_lookup_and_goto_ptr(void);
static inline void tcg_gen_plugin_cb_start(unsigned from, unsigned type,
unsigned wr)
{
tcg_gen_op3(INDEX_op_plugin_cb_start, from, type, wr);
}
static inline void tcg_gen_plugin_cb_end(void)
{
tcg_emit_op(INDEX_op_plugin_cb_end, 0);
}
/* 32 bit ops */
void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg);
void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2);
void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_clz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2);
void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2);
void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg);
void tcg_gen_ctpop_i32(TCGv_i32 a1, TCGv_i32 a2);
void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
unsigned int ofs, unsigned int len);
void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
unsigned int ofs, unsigned int len);
void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
unsigned int ofs, unsigned int len);
void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg,
unsigned int ofs, unsigned int len);
void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah,
unsigned int ofs);
void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, TCGLabel *);
void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, TCGLabel *);
void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, int32_t arg2);
void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2);
void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh);
void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh);
void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_mulsu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg);
void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg);
void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg);
void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg);
void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags);
void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg);
void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg);
void tcg_gen_smin_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_smax_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_umin_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_umax_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_abs_i32(TCGv_i32, TCGv_i32);
/* Replicate a value of size @vece from @in to all the lanes in @out */
void tcg_gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in);
static inline void tcg_gen_discard_i32(TCGv_i32 arg)
{
tcg_gen_op1_i32(INDEX_op_discard, arg);
}
static inline void tcg_gen_mov_i32(TCGv_i32 ret, TCGv_i32 arg)
{
if (ret != arg) {
tcg_gen_op2_i32(INDEX_op_mov_i32, ret, arg);
}
}
static inline void tcg_gen_ld8u_i32(TCGv_i32 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i32(INDEX_op_ld8u_i32, ret, arg2, offset);
}
static inline void tcg_gen_ld8s_i32(TCGv_i32 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i32(INDEX_op_ld8s_i32, ret, arg2, offset);
}
static inline void tcg_gen_ld16u_i32(TCGv_i32 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i32(INDEX_op_ld16u_i32, ret, arg2, offset);
}
static inline void tcg_gen_ld16s_i32(TCGv_i32 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i32(INDEX_op_ld16s_i32, ret, arg2, offset);
}
static inline void tcg_gen_ld_i32(TCGv_i32 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i32(INDEX_op_ld_i32, ret, arg2, offset);
}
static inline void tcg_gen_st8_i32(TCGv_i32 arg1, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i32(INDEX_op_st8_i32, arg1, arg2, offset);
}
static inline void tcg_gen_st16_i32(TCGv_i32 arg1, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i32(INDEX_op_st16_i32, arg1, arg2, offset);
}
static inline void tcg_gen_st_i32(TCGv_i32 arg1, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i32(INDEX_op_st_i32, arg1, arg2, offset);
}
static inline void tcg_gen_add_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
tcg_gen_op3_i32(INDEX_op_add_i32, ret, arg1, arg2);
}
static inline void tcg_gen_sub_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
tcg_gen_op3_i32(INDEX_op_sub_i32, ret, arg1, arg2);
}
static inline void tcg_gen_and_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
tcg_gen_op3_i32(INDEX_op_and_i32, ret, arg1, arg2);
}
static inline void tcg_gen_or_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
tcg_gen_op3_i32(INDEX_op_or_i32, ret, arg1, arg2);
}
static inline void tcg_gen_xor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
tcg_gen_op3_i32(INDEX_op_xor_i32, ret, arg1, arg2);
}
static inline void tcg_gen_shl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
tcg_gen_op3_i32(INDEX_op_shl_i32, ret, arg1, arg2);
}
static inline void tcg_gen_shr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
tcg_gen_op3_i32(INDEX_op_shr_i32, ret, arg1, arg2);
}
static inline void tcg_gen_sar_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
tcg_gen_op3_i32(INDEX_op_sar_i32, ret, arg1, arg2);
}
static inline void tcg_gen_mul_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
tcg_gen_op3_i32(INDEX_op_mul_i32, ret, arg1, arg2);
}
static inline void tcg_gen_neg_i32(TCGv_i32 ret, TCGv_i32 arg)
{
if (TCG_TARGET_HAS_neg_i32) {
tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg);
} else {
tcg_gen_subfi_i32(ret, 0, arg);
}
}
static inline void tcg_gen_not_i32(TCGv_i32 ret, TCGv_i32 arg)
{
if (TCG_TARGET_HAS_not_i32) {
tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg);
} else {
tcg_gen_xori_i32(ret, arg, -1);
}
}
/* 64 bit ops */
void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg);
void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2);
void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_clz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_ctz_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_clzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2);
void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2);
void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_ctpop_i64(TCGv_i64 a1, TCGv_i64 a2);
void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
unsigned int ofs, unsigned int len);
void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
unsigned int ofs, unsigned int len);
void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
unsigned int ofs, unsigned int len);
void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg,
unsigned int ofs, unsigned int len);
void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah,
unsigned int ofs);
void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, TCGLabel *);
void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *);
void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, int64_t arg2);
void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2);
void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh);
void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh);
void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags);
void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags);
void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_hswap_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_wswap_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_smin_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_smax_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_umin_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_umax_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_abs_i64(TCGv_i64, TCGv_i64);
/* Replicate a value of size @vece from @in to all the lanes in @out */
void tcg_gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in);
#if TCG_TARGET_REG_BITS == 64
static inline void tcg_gen_discard_i64(TCGv_i64 arg)
{
tcg_gen_op1_i64(INDEX_op_discard, arg);
}
static inline void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
{
if (ret != arg) {
tcg_gen_op2_i64(INDEX_op_mov_i64, ret, arg);
}
}
static inline void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i64(INDEX_op_ld8u_i64, ret, arg2, offset);
}
static inline void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i64(INDEX_op_ld8s_i64, ret, arg2, offset);
}
static inline void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i64(INDEX_op_ld16u_i64, ret, arg2, offset);
}
static inline void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i64(INDEX_op_ld16s_i64, ret, arg2, offset);
}
static inline void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i64(INDEX_op_ld32u_i64, ret, arg2, offset);
}
static inline void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i64(INDEX_op_ld32s_i64, ret, arg2, offset);
}
static inline void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i64(INDEX_op_ld_i64, ret, arg2, offset);
}
static inline void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i64(INDEX_op_st8_i64, arg1, arg2, offset);
}
static inline void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i64(INDEX_op_st16_i64, arg1, arg2, offset);
}
static inline void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i64(INDEX_op_st32_i64, arg1, arg2, offset);
}
static inline void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2,
tcg_target_long offset)
{
tcg_gen_ldst_op_i64(INDEX_op_st_i64, arg1, arg2, offset);
}
static inline void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
tcg_gen_op3_i64(INDEX_op_add_i64, ret, arg1, arg2);
}
static inline void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
tcg_gen_op3_i64(INDEX_op_sub_i64, ret, arg1, arg2);
}
static inline void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
tcg_gen_op3_i64(INDEX_op_and_i64, ret, arg1, arg2);
}
static inline void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
tcg_gen_op3_i64(INDEX_op_or_i64, ret, arg1, arg2);
}
static inline void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
tcg_gen_op3_i64(INDEX_op_xor_i64, ret, arg1, arg2);
}
static inline void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
tcg_gen_op3_i64(INDEX_op_shl_i64, ret, arg1, arg2);
}
static inline void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
tcg_gen_op3_i64(INDEX_op_shr_i64, ret, arg1, arg2);
}
static inline void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
tcg_gen_op3_i64(INDEX_op_sar_i64, ret, arg1, arg2);
}
static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
tcg_gen_op3_i64(INDEX_op_mul_i64, ret, arg1, arg2);
}
#else /* TCG_TARGET_REG_BITS == 32 */
void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset);
void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset);
void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset);
void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_discard_i64(TCGv_i64 arg);
void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg);
void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset);
void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
#endif /* TCG_TARGET_REG_BITS */
static inline void tcg_gen_neg_i64(TCGv_i64 ret, TCGv_i64 arg)
{
if (TCG_TARGET_HAS_neg_i64) {
tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg);
} else {
tcg_gen_subfi_i64(ret, 0, arg);
}
}
/* Size changing operations. */
void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg);
void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg);
void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high);
void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg);
void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg);
void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg);
void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg);
void tcg_gen_mov_i128(TCGv_i128 dst, TCGv_i128 src);
void tcg_gen_extr_i128_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i128 arg);
void tcg_gen_concat_i64_i128(TCGv_i128 ret, TCGv_i64 lo, TCGv_i64 hi);
static inline void tcg_gen_concat32_i64(TCGv_i64 ret, TCGv_i64 lo, TCGv_i64 hi)
{
tcg_gen_deposit_i64(ret, lo, hi, 32, 32);
}
/* Local load/store bit ops */
void tcg_gen_qemu_ld_i32_chk(TCGv_i32, TCGTemp *, TCGArg, MemOp, TCGType);
void tcg_gen_qemu_st_i32_chk(TCGv_i32, TCGTemp *, TCGArg, MemOp, TCGType);
void tcg_gen_qemu_ld_i64_chk(TCGv_i64, TCGTemp *, TCGArg, MemOp, TCGType);
void tcg_gen_qemu_st_i64_chk(TCGv_i64, TCGTemp *, TCGArg, MemOp, TCGType);
void tcg_gen_qemu_ld_i128_chk(TCGv_i128, TCGTemp *, TCGArg, MemOp, TCGType);
void tcg_gen_qemu_st_i128_chk(TCGv_i128, TCGTemp *, TCGArg, MemOp, TCGType);
/* Atomic ops */
void tcg_gen_atomic_cmpxchg_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_cmpxchg_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_cmpxchg_i128_chk(TCGv_i128, TCGTemp *, TCGv_i128,
TCGv_i128, TCGArg, MemOp, TCGType);
void tcg_gen_nonatomic_cmpxchg_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_nonatomic_cmpxchg_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_nonatomic_cmpxchg_i128_chk(TCGv_i128, TCGTemp *, TCGv_i128,
TCGv_i128, TCGArg, MemOp, TCGType);
void tcg_gen_atomic_xchg_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_xchg_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_add_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_add_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_and_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_and_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_or_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_or_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_xor_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_xor_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_smin_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_smin_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_umin_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_umin_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_smax_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_smax_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_umax_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_fetch_umax_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_add_fetch_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_add_fetch_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_and_fetch_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_and_fetch_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_or_fetch_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_or_fetch_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_xor_fetch_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_xor_fetch_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_smin_fetch_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_smin_fetch_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_umin_fetch_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_umin_fetch_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_smax_fetch_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_smax_fetch_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_umax_fetch_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
TCGArg, MemOp, TCGType);
void tcg_gen_atomic_umax_fetch_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
TCGArg, MemOp, TCGType);
/* Vector ops */
void tcg_gen_mov_vec(TCGv_vec, TCGv_vec);
void tcg_gen_dup_i32_vec(unsigned vece, TCGv_vec, TCGv_i32);
void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec, TCGv_i64);
void tcg_gen_dup_mem_vec(unsigned vece, TCGv_vec, TCGv_ptr, tcg_target_long);
void tcg_gen_dupi_vec(unsigned vece, TCGv_vec, uint64_t);
void tcg_gen_add_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_sub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_mul_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_and_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_or_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_xor_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_andc_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_orc_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_nand_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_nor_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_eqv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_not_vec(unsigned vece, TCGv_vec r, TCGv_vec a);
void tcg_gen_neg_vec(unsigned vece, TCGv_vec r, TCGv_vec a);
void tcg_gen_abs_vec(unsigned vece, TCGv_vec r, TCGv_vec a);
void tcg_gen_ssadd_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_usadd_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_sssub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_ussub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_smin_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_umin_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_smax_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_umax_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
void tcg_gen_shli_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i);
void tcg_gen_shri_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i);
void tcg_gen_sari_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i);
void tcg_gen_rotli_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i);
void tcg_gen_rotri_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i);
void tcg_gen_shls_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 s);
void tcg_gen_shrs_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 s);
void tcg_gen_sars_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 s);
void tcg_gen_rotls_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 s);
void tcg_gen_shlv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec s);
void tcg_gen_shrv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec s);
void tcg_gen_sarv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec s);
void tcg_gen_rotlv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec s);
void tcg_gen_rotrv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec s);
void tcg_gen_cmp_vec(TCGCond cond, unsigned vece, TCGv_vec r,
TCGv_vec a, TCGv_vec b);
void tcg_gen_bitsel_vec(unsigned vece, TCGv_vec r, TCGv_vec a,
TCGv_vec b, TCGv_vec c);
void tcg_gen_cmpsel_vec(TCGCond cond, unsigned vece, TCGv_vec r,
TCGv_vec a, TCGv_vec b, TCGv_vec c, TCGv_vec d);
void tcg_gen_ld_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset);
void tcg_gen_st_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset);
void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
/* Host pointer ops */
#if UINTPTR_MAX == UINT32_MAX
# define PTR i32
# define NAT TCGv_i32
#else
# define PTR i64
# define NAT TCGv_i64
#endif
static inline void tcg_gen_ld_ptr(TCGv_ptr r, TCGv_ptr a, intptr_t o)
{
glue(tcg_gen_ld_,PTR)((NAT)r, a, o);
}
static inline void tcg_gen_st_ptr(TCGv_ptr r, TCGv_ptr a, intptr_t o)
{
glue(tcg_gen_st_, PTR)((NAT)r, a, o);
}
static inline void tcg_gen_discard_ptr(TCGv_ptr a)
{
glue(tcg_gen_discard_,PTR)((NAT)a);
}
static inline void tcg_gen_add_ptr(TCGv_ptr r, TCGv_ptr a, TCGv_ptr b)
{
glue(tcg_gen_add_,PTR)((NAT)r, (NAT)a, (NAT)b);
}
static inline void tcg_gen_addi_ptr(TCGv_ptr r, TCGv_ptr a, intptr_t b)
{
glue(tcg_gen_addi_,PTR)((NAT)r, (NAT)a, b);
}
static inline void tcg_gen_mov_ptr(TCGv_ptr d, TCGv_ptr s)
{
glue(tcg_gen_mov_,PTR)((NAT)d, (NAT)s);
}
static inline void tcg_gen_movi_ptr(TCGv_ptr d, intptr_t s)
{
glue(tcg_gen_movi_,PTR)((NAT)d, s);
}
static inline void tcg_gen_brcondi_ptr(TCGCond cond, TCGv_ptr a,
intptr_t b, TCGLabel *label)
{
glue(tcg_gen_brcondi_,PTR)(cond, (NAT)a, b, label);
}
static inline void tcg_gen_ext_i32_ptr(TCGv_ptr r, TCGv_i32 a)
{
#if UINTPTR_MAX == UINT32_MAX
tcg_gen_mov_i32((NAT)r, a);
#else
tcg_gen_ext_i32_i64((NAT)r, a);
#endif
}
static inline void tcg_gen_trunc_i64_ptr(TCGv_ptr r, TCGv_i64 a)
{
#if UINTPTR_MAX == UINT32_MAX
tcg_gen_extrl_i64_i32((NAT)r, a);
#else
tcg_gen_mov_i64((NAT)r, a);
#endif
}
static inline void tcg_gen_extu_ptr_i64(TCGv_i64 r, TCGv_ptr a)
{
#if UINTPTR_MAX == UINT32_MAX
tcg_gen_extu_i32_i64(r, (NAT)a);
#else
tcg_gen_mov_i64(r, (NAT)a);
#endif
}
static inline void tcg_gen_trunc_ptr_i32(TCGv_i32 r, TCGv_ptr a)
{
#if UINTPTR_MAX == UINT32_MAX
tcg_gen_mov_i32(r, (NAT)a);
#else
tcg_gen_extrl_i64_i32(r, (NAT)a);
#endif
}
#undef PTR
#undef NAT
#endif /* TCG_TCG_OP_COMMON_H */

View file

@ -0,0 +1,426 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Target independent generic vector operation expansion
*
* Copyright (c) 2018 Linaro
*/
#ifndef TCG_TCG_OP_GVEC_COMMON_H
#define TCG_TCG_OP_GVEC_COMMON_H
/*
* "Generic" vectors. All operands are given as offsets from ENV,
* and therefore cannot also be allocated via tcg_global_mem_new_*.
* OPRSZ is the byte size of the vector upon which the operation is performed.
* MAXSZ is the byte size of the full vector; bytes beyond OPSZ are cleared.
*
* All sizes must be 8 or any multiple of 16.
* When OPRSZ is 8, the alignment may be 8, otherwise must be 16.
* Operands may completely, but not partially, overlap.
*/
/* Expand a call to a gvec-style helper, with pointers to two vector
operands, and a descriptor (see tcg-gvec-desc.h). */
typedef void gen_helper_gvec_2(TCGv_ptr, TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz, int32_t data,
gen_helper_gvec_2 *fn);
/* Similarly, passing an extra data value. */
typedef void gen_helper_gvec_2i(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_i32);
void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, TCGv_i64 c,
uint32_t oprsz, uint32_t maxsz, int32_t data,
gen_helper_gvec_2i *fn);
/* Similarly, passing an extra pointer (e.g. env or float_status). */
typedef void gen_helper_gvec_2_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs,
TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz,
int32_t data, gen_helper_gvec_2_ptr *fn);
/* Similarly, with three vector operands. */
typedef void gen_helper_gvec_3(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t oprsz, uint32_t maxsz, int32_t data,
gen_helper_gvec_3 *fn);
/* Similarly, with four vector operands. */
typedef void gen_helper_gvec_4(TCGv_ptr, TCGv_ptr, TCGv_ptr,
TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t cofs, uint32_t oprsz, uint32_t maxsz,
int32_t data, gen_helper_gvec_4 *fn);
/* Similarly, with five vector operands. */
typedef void gen_helper_gvec_5(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr,
TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t cofs, uint32_t xofs, uint32_t oprsz,
uint32_t maxsz, int32_t data, gen_helper_gvec_5 *fn);
typedef void gen_helper_gvec_3_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr,
TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_3_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz,
int32_t data, gen_helper_gvec_3_ptr *fn);
typedef void gen_helper_gvec_4_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr,
TCGv_ptr, TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_4_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t cofs, TCGv_ptr ptr, uint32_t oprsz,
uint32_t maxsz, int32_t data,
gen_helper_gvec_4_ptr *fn);
typedef void gen_helper_gvec_5_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr,
TCGv_ptr, TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_5_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t cofs, uint32_t eofs, TCGv_ptr ptr,
uint32_t oprsz, uint32_t maxsz, int32_t data,
gen_helper_gvec_5_ptr *fn);
/* Expand a gvec operation. Either inline or out-of-line depending on
the actual vector size and the operations supported by the host. */
typedef struct {
/* Expand inline as a 64-bit or 32-bit integer.
Only one of these will be non-NULL. */
void (*fni8)(TCGv_i64, TCGv_i64);
void (*fni4)(TCGv_i32, TCGv_i32);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec);
/* Expand out-of-line helper w/descriptor. */
gen_helper_gvec_2 *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The data argument to the out-of-line helper. */
int32_t data;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Load dest as a 2nd source operand. */
bool load_dest;
} GVecGen2;
typedef struct {
/* Expand inline as a 64-bit or 32-bit integer.
Only one of these will be non-NULL. */
void (*fni8)(TCGv_i64, TCGv_i64, int64_t);
void (*fni4)(TCGv_i32, TCGv_i32, int32_t);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, int64_t);
/* Expand out-of-line helper w/descriptor, data in descriptor. */
gen_helper_gvec_2 *fno;
/* Expand out-of-line helper w/descriptor, data as argument. */
gen_helper_gvec_2i *fnoi;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Load dest as a 3rd source operand. */
bool load_dest;
} GVecGen2i;
typedef struct {
/* Expand inline as a 64-bit or 32-bit integer.
Only one of these will be non-NULL. */
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64);
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec);
/* Expand out-of-line helper w/descriptor. */
gen_helper_gvec_2i *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The data argument to the out-of-line helper. */
uint32_t data;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Load scalar as 1st source operand. */
bool scalar_first;
} GVecGen2s;
typedef struct {
/* Expand inline as a 64-bit or 32-bit integer.
Only one of these will be non-NULL. */
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64);
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec);
/* Expand out-of-line helper w/descriptor. */
gen_helper_gvec_3 *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The data argument to the out-of-line helper. */
int32_t data;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Load dest as a 3rd source operand. */
bool load_dest;
} GVecGen3;
typedef struct {
/*
* Expand inline as a 64-bit or 32-bit integer. Only one of these will be
* non-NULL.
*/
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64, int64_t);
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32, int32_t);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, int64_t);
/* Expand out-of-line helper w/descriptor, data in descriptor. */
gen_helper_gvec_3 *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Load dest as a 3rd source operand. */
bool load_dest;
} GVecGen3i;
typedef struct {
/* Expand inline as a 64-bit or 32-bit integer.
Only one of these will be non-NULL. */
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64);
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, TCGv_vec);
/* Expand out-of-line helper w/descriptor. */
gen_helper_gvec_4 *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The data argument to the out-of-line helper. */
int32_t data;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Write aofs as a 2nd dest operand. */
bool write_aofs;
} GVecGen4;
typedef struct {
/*
* Expand inline as a 64-bit or 32-bit integer. Only one of these will be
* non-NULL.
*/
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64, int64_t);
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32, int32_t);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, TCGv_vec, int64_t);
/* Expand out-of-line helper w/descriptor, data in descriptor. */
gen_helper_gvec_4 *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
} GVecGen4i;
void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz, const GVecGen2 *);
void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t maxsz, int64_t c, const GVecGen2i *);
void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t maxsz, TCGv_i64 c, const GVecGen2s *);
void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t oprsz, uint32_t maxsz, const GVecGen3 *);
void tcg_gen_gvec_3i(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t oprsz, uint32_t maxsz, int64_t c,
const GVecGen3i *);
void tcg_gen_gvec_4(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs,
uint32_t oprsz, uint32_t maxsz, const GVecGen4 *);
void tcg_gen_gvec_4i(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs,
uint32_t oprsz, uint32_t maxsz, int64_t c,
const GVecGen4i *);
/* Expand a specific vector operation. */
void tcg_gen_gvec_mov(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_neg(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_abs(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_add(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sub(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_addi(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_muli(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_adds(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_subs(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_muls(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
/* Saturated arithmetic. */
void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sssub(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_usadd(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
/* Min/max. */
void tcg_gen_gvec_smin(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_umin(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_smax(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_umax(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_and(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_or(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_xor(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_nand(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_nor(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_eqv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_andi(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_xori(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_ori(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_andcs(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t s, uint32_t m);
void tcg_gen_gvec_dup_imm(unsigned vece, uint32_t dofs, uint32_t s,
uint32_t m, uint64_t imm);
void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t s,
uint32_t m, TCGv_i32);
void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t s,
uint32_t m, TCGv_i64);
void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotli(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotri(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_shls(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_shrs(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sars(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotls(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotrs(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
/*
* Perform vector shift by vector element, modulo the element size.
* E.g. D[i] = A[i] << (B[i] % (8 << vece)).
*/
void tcg_gen_gvec_shlv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_shrv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sarv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotlv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotrv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs,
uint32_t aofs, uint32_t bofs,
uint32_t oprsz, uint32_t maxsz);
/*
* Perform vector bit select: d = (b & a) | (c & ~a).
*/
void tcg_gen_gvec_bitsel(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t cofs,
uint32_t oprsz, uint32_t maxsz);
/*
* 64-bit vector operations. Use these when the register has been allocated
* with tcg_global_mem_new_i64, and so we cannot also address it via pointer.
* OPRSZ = MAXSZ = 8.
*/
void tcg_gen_vec_neg8_i64(TCGv_i64 d, TCGv_i64 a);
void tcg_gen_vec_neg16_i64(TCGv_i64 d, TCGv_i64 a);
void tcg_gen_vec_neg32_i64(TCGv_i64 d, TCGv_i64 a);
void tcg_gen_vec_add8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_add16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_add32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_sub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_sub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_sub32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_shl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_shl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_shr8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_shr16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_sar8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_sar16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_rotl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c);
void tcg_gen_vec_rotl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c);
/* 32-bit vector operations. */
void tcg_gen_vec_add8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
void tcg_gen_vec_add16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
void tcg_gen_vec_sub8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
void tcg_gen_vec_sub16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
void tcg_gen_vec_shl8i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
void tcg_gen_vec_shl16i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
void tcg_gen_vec_shr8i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
void tcg_gen_vec_shr16i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
void tcg_gen_vec_sar8i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
void tcg_gen_vec_sar16i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
#endif

View file

@ -1,447 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Generic vector operation expansion
* Target dependent generic vector operation expansion
*
* Copyright (c) 2018 Linaro
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TCG_TCG_OP_GVEC_H
#define TCG_TCG_OP_GVEC_H
/*
* "Generic" vectors. All operands are given as offsets from ENV,
* and therefore cannot also be allocated via tcg_global_mem_new_*.
* OPRSZ is the byte size of the vector upon which the operation is performed.
* MAXSZ is the byte size of the full vector; bytes beyond OPSZ are cleared.
*
* All sizes must be 8 or any multiple of 16.
* When OPRSZ is 8, the alignment may be 8, otherwise must be 16.
* Operands may completely, but not partially, overlap.
*/
#include "tcg/tcg-op-gvec-common.h"
/* Expand a call to a gvec-style helper, with pointers to two vector
operands, and a descriptor (see tcg-gvec-desc.h). */
typedef void gen_helper_gvec_2(TCGv_ptr, TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz, int32_t data,
gen_helper_gvec_2 *fn);
/* Similarly, passing an extra data value. */
typedef void gen_helper_gvec_2i(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_i32);
void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, TCGv_i64 c,
uint32_t oprsz, uint32_t maxsz, int32_t data,
gen_helper_gvec_2i *fn);
/* Similarly, passing an extra pointer (e.g. env or float_status). */
typedef void gen_helper_gvec_2_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs,
TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz,
int32_t data, gen_helper_gvec_2_ptr *fn);
/* Similarly, with three vector operands. */
typedef void gen_helper_gvec_3(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t oprsz, uint32_t maxsz, int32_t data,
gen_helper_gvec_3 *fn);
/* Similarly, with four vector operands. */
typedef void gen_helper_gvec_4(TCGv_ptr, TCGv_ptr, TCGv_ptr,
TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t cofs, uint32_t oprsz, uint32_t maxsz,
int32_t data, gen_helper_gvec_4 *fn);
/* Similarly, with five vector operands. */
typedef void gen_helper_gvec_5(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr,
TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t cofs, uint32_t xofs, uint32_t oprsz,
uint32_t maxsz, int32_t data, gen_helper_gvec_5 *fn);
typedef void gen_helper_gvec_3_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr,
TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_3_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz,
int32_t data, gen_helper_gvec_3_ptr *fn);
typedef void gen_helper_gvec_4_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr,
TCGv_ptr, TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_4_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t cofs, TCGv_ptr ptr, uint32_t oprsz,
uint32_t maxsz, int32_t data,
gen_helper_gvec_4_ptr *fn);
typedef void gen_helper_gvec_5_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr,
TCGv_ptr, TCGv_ptr, TCGv_i32);
void tcg_gen_gvec_5_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t cofs, uint32_t eofs, TCGv_ptr ptr,
uint32_t oprsz, uint32_t maxsz, int32_t data,
gen_helper_gvec_5_ptr *fn);
/* Expand a gvec operation. Either inline or out-of-line depending on
the actual vector size and the operations supported by the host. */
typedef struct {
/* Expand inline as a 64-bit or 32-bit integer.
Only one of these will be non-NULL. */
void (*fni8)(TCGv_i64, TCGv_i64);
void (*fni4)(TCGv_i32, TCGv_i32);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec);
/* Expand out-of-line helper w/descriptor. */
gen_helper_gvec_2 *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The data argument to the out-of-line helper. */
int32_t data;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Load dest as a 2nd source operand. */
bool load_dest;
} GVecGen2;
typedef struct {
/* Expand inline as a 64-bit or 32-bit integer.
Only one of these will be non-NULL. */
void (*fni8)(TCGv_i64, TCGv_i64, int64_t);
void (*fni4)(TCGv_i32, TCGv_i32, int32_t);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, int64_t);
/* Expand out-of-line helper w/descriptor, data in descriptor. */
gen_helper_gvec_2 *fno;
/* Expand out-of-line helper w/descriptor, data as argument. */
gen_helper_gvec_2i *fnoi;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Load dest as a 3rd source operand. */
bool load_dest;
} GVecGen2i;
typedef struct {
/* Expand inline as a 64-bit or 32-bit integer.
Only one of these will be non-NULL. */
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64);
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec);
/* Expand out-of-line helper w/descriptor. */
gen_helper_gvec_2i *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The data argument to the out-of-line helper. */
uint32_t data;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Load scalar as 1st source operand. */
bool scalar_first;
} GVecGen2s;
typedef struct {
/* Expand inline as a 64-bit or 32-bit integer.
Only one of these will be non-NULL. */
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64);
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec);
/* Expand out-of-line helper w/descriptor. */
gen_helper_gvec_3 *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The data argument to the out-of-line helper. */
int32_t data;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Load dest as a 3rd source operand. */
bool load_dest;
} GVecGen3;
typedef struct {
/*
* Expand inline as a 64-bit or 32-bit integer. Only one of these will be
* non-NULL.
*/
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64, int64_t);
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32, int32_t);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, int64_t);
/* Expand out-of-line helper w/descriptor, data in descriptor. */
gen_helper_gvec_3 *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Load dest as a 3rd source operand. */
bool load_dest;
} GVecGen3i;
typedef struct {
/* Expand inline as a 64-bit or 32-bit integer.
Only one of these will be non-NULL. */
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64);
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, TCGv_vec);
/* Expand out-of-line helper w/descriptor. */
gen_helper_gvec_4 *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The data argument to the out-of-line helper. */
int32_t data;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
/* Write aofs as a 2nd dest operand. */
bool write_aofs;
} GVecGen4;
typedef struct {
/*
* Expand inline as a 64-bit or 32-bit integer. Only one of these will be
* non-NULL.
*/
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64, int64_t);
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32, int32_t);
/* Expand inline with a host vector type. */
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, TCGv_vec, int64_t);
/* Expand out-of-line helper w/descriptor, data in descriptor. */
gen_helper_gvec_4 *fno;
/* The optional opcodes, if any, utilized by .fniv. */
const TCGOpcode *opt_opc;
/* The vector element size, if applicable. */
uint8_t vece;
/* Prefer i64 to v64. */
bool prefer_i64;
} GVecGen4i;
void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz, const GVecGen2 *);
void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t maxsz, int64_t c, const GVecGen2i *);
void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t maxsz, TCGv_i64 c, const GVecGen2s *);
void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t oprsz, uint32_t maxsz, const GVecGen3 *);
void tcg_gen_gvec_3i(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t oprsz, uint32_t maxsz, int64_t c,
const GVecGen3i *);
void tcg_gen_gvec_4(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs,
uint32_t oprsz, uint32_t maxsz, const GVecGen4 *);
void tcg_gen_gvec_4i(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs,
uint32_t oprsz, uint32_t maxsz, int64_t c,
const GVecGen4i *);
/* Expand a specific vector operation. */
void tcg_gen_gvec_mov(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_neg(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_abs(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_add(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sub(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_addi(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_muli(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_adds(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_subs(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_muls(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
/* Saturated arithmetic. */
void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sssub(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_usadd(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
/* Min/max. */
void tcg_gen_gvec_smin(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_umin(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_smax(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_umax(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_and(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_or(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_xor(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_nand(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_nor(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_eqv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_andi(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_xori(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_ori(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_andcs(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t s, uint32_t m);
void tcg_gen_gvec_dup_imm(unsigned vece, uint32_t dofs, uint32_t s,
uint32_t m, uint64_t imm);
void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t s,
uint32_t m, TCGv_i32);
void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t s,
uint32_t m, TCGv_i64);
#if TARGET_LONG_BITS == 64
# define tcg_gen_gvec_dup_tl tcg_gen_gvec_dup_i64
#else
# define tcg_gen_gvec_dup_tl tcg_gen_gvec_dup_i32
#ifndef TARGET_LONG_BITS
#error must include QEMU headers
#endif
void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotli(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotri(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_shls(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_shrs(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sars(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotls(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotrs(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
/*
* Perform vector shift by vector element, modulo the element size.
* E.g. D[i] = A[i] << (B[i] % (8 << vece)).
*/
void tcg_gen_gvec_shlv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_shrv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sarv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotlv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotrv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs,
uint32_t aofs, uint32_t bofs,
uint32_t oprsz, uint32_t maxsz);
/*
* Perform vector bit select: d = (b & a) | (c & ~a).
*/
void tcg_gen_gvec_bitsel(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t cofs,
uint32_t oprsz, uint32_t maxsz);
/*
* 64-bit vector operations. Use these when the register has been allocated
* with tcg_global_mem_new_i64, and so we cannot also address it via pointer.
* OPRSZ = MAXSZ = 8.
*/
void tcg_gen_vec_neg8_i64(TCGv_i64 d, TCGv_i64 a);
void tcg_gen_vec_neg16_i64(TCGv_i64 d, TCGv_i64 a);
void tcg_gen_vec_neg32_i64(TCGv_i64 d, TCGv_i64 a);
void tcg_gen_vec_add8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_add16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_add32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_sub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_sub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_sub32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void tcg_gen_vec_shl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_shl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_shr8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_shr16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_sar8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_sar16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
void tcg_gen_vec_rotl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c);
void tcg_gen_vec_rotl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c);
/* 32-bit vector operations. */
void tcg_gen_vec_add8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
void tcg_gen_vec_add16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
void tcg_gen_vec_sub8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
void tcg_gen_vec_sub16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
void tcg_gen_vec_shl8i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
void tcg_gen_vec_shl16i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
void tcg_gen_vec_shr8i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
void tcg_gen_vec_shr16i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
void tcg_gen_vec_sar8i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
void tcg_gen_vec_sar16i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
#if TARGET_LONG_BITS == 64
#define tcg_gen_gvec_dup_tl tcg_gen_gvec_dup_i64
#define tcg_gen_vec_add8_tl tcg_gen_vec_add8_i64
#define tcg_gen_vec_sub8_tl tcg_gen_vec_sub8_i64
#define tcg_gen_vec_add16_tl tcg_gen_vec_add16_i64
@ -454,8 +28,8 @@ void tcg_gen_vec_sar16i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
#define tcg_gen_vec_shl16i_tl tcg_gen_vec_shl16i_i64
#define tcg_gen_vec_shr16i_tl tcg_gen_vec_shr16i_i64
#define tcg_gen_vec_sar16i_tl tcg_gen_vec_sar16i_i64
#else
#elif TARGET_LONG_BITS == 32
#define tcg_gen_gvec_dup_tl tcg_gen_gvec_dup_i32
#define tcg_gen_vec_add8_tl tcg_gen_vec_add8_i32
#define tcg_gen_vec_sub8_tl tcg_gen_vec_sub8_i32
#define tcg_gen_vec_add16_tl tcg_gen_vec_add16_i32
@ -468,6 +42,8 @@ void tcg_gen_vec_sar16i_i32(TCGv_i32 d, TCGv_i32 a, int32_t);
#define tcg_gen_vec_shl16i_tl tcg_gen_vec_shl16i_i32
#define tcg_gen_vec_shr16i_tl tcg_gen_vec_shr16i_i32
#define tcg_gen_vec_sar16i_tl tcg_gen_vec_sar16i_i32
#else
# error
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -188,9 +188,9 @@ DEF(mulsh_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_mulsh_i64))
#define DATA64_ARGS (TCG_TARGET_REG_BITS == 64 ? 1 : 2)
/* QEMU specific */
DEF(insn_start, 0, 0, DATA64_ARGS * TARGET_INSN_START_WORDS,
TCG_OPF_NOT_PRESENT)
/* There are tcg_ctx->insn_start_words here, not just one. */
DEF(insn_start, 0, 0, DATA64_ARGS, TCG_OPF_NOT_PRESENT)
DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
DEF(goto_ptr, 0, 1, 0, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)

View file

@ -25,13 +25,13 @@
#ifndef TCG_H
#define TCG_H
#include "cpu.h"
#include "exec/memop.h"
#include "exec/memopidx.h"
#include "qemu/bitops.h"
#include "qemu/plugin.h"
#include "qemu/queue.h"
#include "tcg/tcg-mo.h"
#include "tcg-target-reg-bits.h"
#include "tcg-target.h"
#include "tcg/tcg-cond.h"
#include "tcg/debug-assert.h"
@ -44,17 +44,6 @@
#define CPU_TEMP_BUF_NLONGS 128
#define TCG_STATIC_FRAME_SIZE (CPU_TEMP_BUF_NLONGS * sizeof(long))
/* Default target word size to pointer size. */
#ifndef TCG_TARGET_REG_BITS
# if UINTPTR_MAX == UINT32_MAX
# define TCG_TARGET_REG_BITS 32
# elif UINTPTR_MAX == UINT64_MAX
# define TCG_TARGET_REG_BITS 64
# else
# error Unknown pointer size for tcg target
# endif
#endif
#if TCG_TARGET_REG_BITS == 32
typedef int32_t tcg_target_long;
typedef uint32_t tcg_target_ulong;
@ -69,15 +58,6 @@ typedef uint64_t tcg_target_ulong;
#error unsupported
#endif
/* Oversized TCG guests make things like MTTCG hard
* as we can't use atomics for cputlb updates.
*/
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
#define TCG_OVERSIZED_GUEST 1
#else
#define TCG_OVERSIZED_GUEST 0
#endif
#if TCG_TARGET_NB_REGS <= 32
typedef uint32_t TCGRegSet;
#elif TCG_TARGET_NB_REGS <= 64
@ -192,12 +172,6 @@ typedef uint64_t TCGRegSet;
#define TCG_TARGET_HAS_v256 0
#endif
#ifndef TARGET_INSN_START_EXTRA_WORDS
# define TARGET_INSN_START_WORDS 1
#else
# define TARGET_INSN_START_WORDS (1 + TARGET_INSN_START_EXTRA_WORDS)
#endif
typedef enum TCGOpcode {
#define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name,
#include "tcg/tcg-opc.h"
@ -292,13 +266,6 @@ typedef enum TCGType {
#else
TCG_TYPE_PTR = TCG_TYPE_I64,
#endif
/* An alias for the size of the target "long", aka register. */
#if TARGET_LONG_BITS == 64
TCG_TYPE_TL = TCG_TYPE_I64,
#else
TCG_TYPE_TL = TCG_TYPE_I32,
#endif
} TCGType;
/**
@ -337,10 +304,6 @@ static inline unsigned get_alignment_bits(MemOp memop)
/* A specific alignment requirement. */
a = a >> MO_ASHIFT;
}
#if defined(CONFIG_SOFTMMU)
/* The requested alignment cannot overlap the TLB flags. */
tcg_debug_assert((TLB_FLAGS_MASK & ((1 << a) - 1)) == 0);
#endif
return a;
}
@ -383,13 +346,6 @@ typedef struct TCGv_i128_d *TCGv_i128;
typedef struct TCGv_ptr_d *TCGv_ptr;
typedef struct TCGv_vec_d *TCGv_vec;
typedef TCGv_ptr TCGv_env;
#if TARGET_LONG_BITS == 32
#define TCGv TCGv_i32
#elif TARGET_LONG_BITS == 64
#define TCGv TCGv_i64
#else
#error Unhandled TARGET_LONG_BITS value
#endif
/* call flags */
/* Helper does not read globals (either directly or through an exception). It
@ -554,10 +510,13 @@ struct TCGContext {
TCGType addr_type; /* TCG_TYPE_I32 or TCG_TYPE_I64 */
#ifdef CONFIG_SOFTMMU
int tlb_fast_offset;
int page_mask;
uint8_t page_bits;
uint8_t tlb_dyn_max_bits;
#endif
uint8_t insn_start_words;
TCGBar guest_mo;
TCGRegSet reserved_regs;
intptr_t current_frame_offset;
@ -629,7 +588,7 @@ struct TCGContext {
TCGTemp *reg_to_temp[TCG_TARGET_NB_REGS];
uint16_t gen_insn_end_off[TCG_MAX_INSNS];
uint64_t gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS];
uint64_t *gen_insn_data;
/* Exit to translator on overflow. */
sigjmp_buf jmp_trans;
@ -662,13 +621,6 @@ static inline void *tcg_splitwx_to_rw(const void *rx)
}
#endif
static inline size_t temp_idx(TCGTemp *ts)
{
ptrdiff_t n = ts - tcg_ctx->temps;
tcg_debug_assert(n >= 0 && n < tcg_ctx->nb_temps);
return n;
}
static inline TCGArg temp_arg(TCGTemp *ts)
{
return (uintptr_t)ts;
@ -679,16 +631,25 @@ static inline TCGTemp *arg_temp(TCGArg a)
return (TCGTemp *)(uintptr_t)a;
}
/* Using the offset of a temporary, relative to TCGContext, rather than
its index means that we don't use 0. That leaves offset 0 free for
a NULL representation without having to leave index 0 unused. */
#ifdef CONFIG_DEBUG_TCG
size_t temp_idx(TCGTemp *ts);
TCGTemp *tcgv_i32_temp(TCGv_i32 v);
#else
static inline size_t temp_idx(TCGTemp *ts)
{
return ts - tcg_ctx->temps;
}
/*
* Using the offset of a temporary, relative to TCGContext, rather than
* its index means that we don't use 0. That leaves offset 0 free for
* a NULL representation without having to leave index 0 unused.
*/
static inline TCGTemp *tcgv_i32_temp(TCGv_i32 v)
{
uintptr_t o = (uintptr_t)v;
TCGTemp *t = (void *)tcg_ctx + o;
tcg_debug_assert(offsetof(TCGContext, temps[temp_idx(t)]) == o);
return t;
return (void *)tcg_ctx + (uintptr_t)v;
}
#endif
static inline TCGTemp *tcgv_i64_temp(TCGv_i64 v)
{
@ -969,7 +930,19 @@ typedef struct TCGTargetOpDef {
bool tcg_op_supported(TCGOpcode op);
void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args);
void tcg_gen_call0(TCGHelperInfo *, TCGTemp *ret);
void tcg_gen_call1(TCGHelperInfo *, TCGTemp *ret, TCGTemp *);
void tcg_gen_call2(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *);
void tcg_gen_call3(TCGHelperInfo *, TCGTemp *ret, TCGTemp *,
TCGTemp *, TCGTemp *);
void tcg_gen_call4(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
TCGTemp *, TCGTemp *);
void tcg_gen_call5(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
TCGTemp *, TCGTemp *, TCGTemp *);
void tcg_gen_call6(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *);
void tcg_gen_call7(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *);
TCGOp *tcg_emit_op(TCGOpcode opc, unsigned nargs);
void tcg_op_remove(TCGContext *s, TCGOp *op);
@ -1188,18 +1161,6 @@ uint64_t dup_const(unsigned vece, uint64_t c);
: (qemu_build_not_reached_always(), 0)) \
: dup_const(VECE, C))
#if TARGET_LONG_BITS == 64
# define dup_const_tl dup_const
#else
# define dup_const_tl(VECE, C) \
(__builtin_constant_p(VECE) \
? ( (VECE) == MO_8 ? 0x01010101ul * (uint8_t)(C) \
: (VECE) == MO_16 ? 0x00010001ul * (uint16_t)(C) \
: (VECE) == MO_32 ? 0x00000001ul * (uint32_t)(C) \
: (qemu_build_not_reached_always(), 0)) \
: (target_long)dup_const(VECE, C))
#endif
#ifdef CONFIG_DEBUG_TCG
void tcg_assert_listed_vecop(TCGOpcode);
#else

View file

@ -4,11 +4,12 @@ if test $# = 0; then
exit 0
fi
# Create list of config switches that should be poisoned in common code...
# but filter out CONFIG_TCG and CONFIG_USER_ONLY which are special.
# Create list of config switches that should be poisoned in common code,
# but filter out several which are handled manually.
exec sed -n \
-e' /CONFIG_TCG/d' \
-e '/CONFIG_USER_ONLY/d' \
-e '/CONFIG_SOFTMMU/d' \
-e '/^#define / {' \
-e 's///' \
-e 's/ .*//' \

View file

@ -30,6 +30,9 @@
#include "exec/translator.h"
#include "exec/log.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
#undef ALPHA_DEBUG_DISAS
#define CONFIG_SOFTFLOAT_INLINE
@ -93,8 +96,6 @@ static TCGv cpu_lock_value;
static TCGv cpu_pal_ir[31];
#endif
#include "exec/gen-icount.h"
void alpha_translate_init(void)
{
#define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUAlphaState, V) }
@ -1233,8 +1234,7 @@ static DisasJumpType gen_mfpr(DisasContext *ctx, TCGv va, int regno)
case 249: /* VMTIME */
helper = gen_helper_get_vmtime;
do_helper:
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
if (translator_io_start(&ctx->base)) {
helper(va);
return DISAS_PC_STALE;
} else {
@ -1295,8 +1295,7 @@ static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
case 251:
/* ALARM */
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
if (translator_io_start(&ctx->base)) {
ret = DISAS_PC_STALE;
}
gen_helper_set_alarm(cpu_env, vb);
@ -2332,13 +2331,10 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
case 0xC000:
/* RPCC */
va = dest_gpr(ctx, ra);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
gen_helper_load_pcc(va, cpu_env);
if (translator_io_start(&ctx->base)) {
ret = DISAS_PC_STALE;
} else {
gen_helper_load_pcc(va, cpu_env);
}
gen_helper_load_pcc(va, cpu_env);
break;
case 0xE000:
/* RC */

View file

@ -67,8 +67,8 @@ enum {
ARM_CP_ALIAS = 1 << 8,
/*
* Flag: Register does I/O and therefore its accesses need to be marked
* with gen_io_start() and also end the TB. In particular, registers which
* implement clocks or timers require this.
* with translator_io_start() and also end the TB. In particular,
* registers which implement clocks or timers require this.
*/
ARM_CP_IO = 1 << 9,
/*

View file

@ -14,6 +14,7 @@
#include "cpu.h"
#include "internals.h"
#include "idau.h"
#include "tcg/oversized-guest.h"
typedef struct S1Translate {
@ -418,6 +419,7 @@ static uint64_t arm_casq_ptw(CPUARMState *env, uint64_t old_val,
uint64_t new_val, S1Translate *ptw,
ARMMMUFaultInfo *fi)
{
#ifdef TARGET_AARCH64
uint64_t cur_val;
void *host = ptw->out_host;
@ -473,7 +475,7 @@ static uint64_t arm_casq_ptw(CPUARMState *env, uint64_t old_val,
* we know that TCG_OVERSIZED_GUEST is set, which means that we are
* running in round-robin mode and could only race with dma i/o.
*/
#ifndef TCG_OVERSIZED_GUEST
#if !TCG_OVERSIZED_GUEST
# error "Unexpected configuration"
#endif
bool locked = qemu_mutex_iothread_locked();
@ -497,6 +499,10 @@ static uint64_t arm_casq_ptw(CPUARMState *env, uint64_t old_val,
#endif
return cur_val;
#else
/* AArch32 does not have FEAT_HADFS. */
g_assert_not_reached();
#endif
}
static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,

View file

@ -18,23 +18,13 @@
*/
#include "qemu/osdep.h"
#include "cpu.h"
#include "exec/exec-all.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "qemu/log.h"
#include "arm_ldst.h"
#include "translate.h"
#include "internals.h"
#include "qemu/host-utils.h"
#include "semihosting/semihost.h"
#include "exec/gen-icount.h"
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
#include "exec/log.h"
#include "cpregs.h"
#include "translate-a64.h"
#include "qemu/atomic128.h"
#include "qemu/log.h"
#include "disas/disas.h"
#include "arm_ldst.h"
#include "semihosting/semihost.h"
#include "cpregs.h"
static TCGv_i64 cpu_X[32];
static TCGv_i64 cpu_pc;
@ -1554,9 +1544,7 @@ static bool trans_ERET(DisasContext *s, arg_ERET *a)
tcg_gen_ld_i64(dst, cpu_env,
offsetof(CPUARMState, elr_el[s->current_el]));
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&s->base);
gen_helper_exception_return(cpu_env, dst);
/* Must exit loop to check un-masked IRQs */
@ -1584,9 +1572,8 @@ static bool trans_ERETA(DisasContext *s, arg_reta *a)
offsetof(CPUARMState, elr_el[s->current_el]));
dst = auth_branch_target(s, dst, cpu_X[31], !a->m);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&s->base);
gen_helper_exception_return(cpu_env, dst);
/* Must exit loop to check un-masked IRQs */
@ -2046,6 +2033,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
uint32_t key = ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP,
crn, crm, op0, op1, op2);
const ARMCPRegInfo *ri = get_arm_cp_reginfo(s->cp_regs, key);
bool need_exit_tb = false;
TCGv_ptr tcg_ri = NULL;
TCGv_i64 tcg_rt;
@ -2173,8 +2161,9 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
return;
}
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
gen_io_start();
if (ri->type & ARM_CP_IO) {
/* I/O operations must end the TB here (whether read or write) */
need_exit_tb = translator_io_start(&s->base);
}
tcg_rt = cpu_reg(s, rt);
@ -2204,10 +2193,6 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
}
}
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
/* I/O operations must end the TB here (whether read or write) */
s->base.is_jmp = DISAS_UPDATE_EXIT;
}
if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
/*
* A write to any coprocessor regiser that ends a TB
@ -2219,6 +2204,9 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
* but allow this to be suppressed by the register definition
* (usually only necessary to work around guest bugs).
*/
need_exit_tb = true;
}
if (need_exit_tb) {
s->base.is_jmp = DISAS_UPDATE_EXIT;
}
}

View file

@ -18,8 +18,6 @@
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "translate.h"
#include "translate-a32.h"

View file

@ -18,10 +18,6 @@
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "exec/exec-all.h"
#include "exec/gen-icount.h"
#include "translate.h"
#include "translate-a32.h"

View file

@ -21,10 +21,6 @@
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "exec/exec-all.h"
#include "exec/gen-icount.h"
#include "translate.h"
#include "translate-a32.h"

View file

@ -18,15 +18,8 @@
*/
#include "qemu/osdep.h"
#include "cpu.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "tcg/tcg-gvec-desc.h"
#include "translate.h"
#include "exec/helper-gen.h"
#include "translate-a64.h"
#include "fpu/softfloat.h"
/*
* Include the generated decoder.

View file

@ -18,18 +18,7 @@
*/
#include "qemu/osdep.h"
#include "cpu.h"
#include "exec/exec-all.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "tcg/tcg-gvec-desc.h"
#include "qemu/log.h"
#include "arm_ldst.h"
#include "translate.h"
#include "internals.h"
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
#include "exec/log.h"
#include "translate-a64.h"
#include "fpu/softfloat.h"

View file

@ -21,10 +21,6 @@
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "exec/exec-all.h"
#include "exec/gen-icount.h"
#include "translate.h"
#include "translate-a32.h"
@ -117,9 +113,8 @@ static void gen_preserve_fp_state(DisasContext *s, bool skip_context_update)
* so we must mark it as an IO operation for icount (and cause
* this to be the last insn in the TB).
*/
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
if (translator_io_start(&s->base)) {
s->base.is_jmp = DISAS_UPDATE_EXIT;
gen_io_start();
}
gen_helper_v7m_preserve_fp_state(cpu_env);
/*

View file

@ -20,21 +20,18 @@
*/
#include "qemu/osdep.h"
#include "cpu.h"
#include "internals.h"
#include "disas/disas.h"
#include "exec/exec-all.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "translate.h"
#include "translate-a32.h"
#include "qemu/log.h"
#include "qemu/bitops.h"
#include "disas/disas.h"
#include "arm_ldst.h"
#include "semihosting/semihost.h"
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
#include "exec/log.h"
#include "cpregs.h"
#include "exec/helper-proto.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
@ -47,9 +44,6 @@
#define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
#define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
#include "translate.h"
#include "translate-a32.h"
/* These are TCG temporaries used only by the legacy iwMMXt decoder */
static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
/* These are TCG globals which alias CPUARMState fields */
@ -58,8 +52,6 @@ TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
TCGv_i64 cpu_exclusive_addr;
TCGv_i64 cpu_exclusive_val;
#include "exec/gen-icount.h"
static const char * const regnames[] =
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
@ -2908,9 +2900,7 @@ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
* appropriately depending on the new Thumb bit, so it must
* be called after storing the new PC.
*/
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&s->base);
gen_helper_cpsr_write_eret(cpu_env, cpsr);
/* Must exit loop to check un-masked IRQs */
s->base.is_jmp = DISAS_EXIT;
@ -4559,7 +4549,7 @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
uint32_t key = ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2);
const ARMCPRegInfo *ri = get_arm_cp_reginfo(s->cp_regs, key);
TCGv_ptr tcg_ri = NULL;
bool need_exit_tb;
bool need_exit_tb = false;
uint32_t syndrome;
/*
@ -4704,8 +4694,9 @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
g_assert_not_reached();
}
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
gen_io_start();
if (ri->type & ARM_CP_IO) {
/* I/O operations must end the TB here (whether read or write) */
need_exit_tb = translator_io_start(&s->base);
}
if (isread) {
@ -4787,10 +4778,6 @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
}
}
/* I/O operations must end the TB here (whether read or write) */
need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) &&
(ri->type & ARM_CP_IO));
if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
/*
* A write to any coprocessor register that ends a TB
@ -8047,9 +8034,7 @@ static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
if (exc_return) {
/* Restore CPSR from SPSR. */
tmp = load_cpu_field(spsr);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&s->base);
gen_helper_cpsr_write_eret(cpu_env, tmp);
/* Must exit loop to check un-masked IRQs */
s->base.is_jmp = DISAS_EXIT;

View file

@ -1,7 +1,12 @@
#ifndef TARGET_ARM_TRANSLATE_H
#define TARGET_ARM_TRANSLATE_H
#include "cpu.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "exec/exec-all.h"
#include "exec/translator.h"
#include "exec/helper-gen.h"
#include "internals.h"

View file

@ -24,6 +24,7 @@
#include "exec/exec-all.h"
#include "cpu.h"
#include "disas/dis-asm.h"
#include "tcg/debug-assert.h"
static void avr_cpu_set_pc(CPUState *cs, vaddr value)
{

View file

@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "cpu.h"
#include "hw/core/tcg-cpu-ops.h"
#include "exec/exec-all.h"

View file

@ -29,7 +29,11 @@
#include "exec/helper-gen.h"
#include "exec/log.h"
#include "exec/translator.h"
#include "exec/gen-icount.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
/*
* Define if you want a BREAK instruction translated to a breakpoint

View file

@ -34,11 +34,13 @@
#include "exec/translator.h"
#include "crisv32-decode.h"
#include "qemu/qemu-print.h"
#include "exec/helper-gen.h"
#include "exec/log.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
#define DISAS_CRIS 0
#if DISAS_CRIS
@ -86,8 +88,6 @@ static TCGv env_btaken;
static TCGv env_btarget;
static TCGv env_pc;
#include "exec/gen-icount.h"
/* This is the state at translation time. */
typedef struct DisasContext {
DisasContextBase base;

View file

@ -20,6 +20,7 @@
#include "internal.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "exec/helper-gen.h"
#include "insn.h"
#include "opcodes.h"
#include "translate.h"

View file

@ -843,13 +843,14 @@ int main(int argc, char **argv)
fputs("#include \"qemu/log.h\"\n", output_file);
fputs("#include \"cpu.h\"\n", output_file);
fputs("#include \"internal.h\"\n", output_file);
fputs("#include \"tcg/tcg.h\"\n", output_file);
fputs("#include \"tcg/tcg-op.h\"\n", output_file);
fputs("#include \"exec/helper-gen.h\"\n", output_file);
fputs("#include \"insn.h\"\n", output_file);
fputs("#include \"opcodes.h\"\n", output_file);
fputs("#include \"translate.h\"\n", output_file);
fputs("#define QEMU_GENERATE\n", output_file);
fputs("#include \"genptr.h\"\n", output_file);
fputs("#include \"tcg/tcg.h\"\n", output_file);
fputs("#include \"macros.h\"\n", output_file);
fprintf(output_file, "#include \"%s\"\n", argv[ARG_INDEX_EMITTER_H]);

View file

@ -20,6 +20,9 @@
#include "cpu.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "exec/helper-gen.h"
#include "exec/helper-proto.h"
#include "exec/translation-block.h"
#include "exec/cpu_ldst.h"
#include "exec/log.h"
#include "internal.h"
@ -30,6 +33,10 @@
#include "genptr.h"
#include "printinsn.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
#include "analyze_funcs_generated.c.inc"
typedef void (*AnalyzeInsn)(DisasContext *ctx);

View file

@ -29,6 +29,11 @@
#include "exec/translator.h"
#include "exec/log.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
/* Since we have a distinction between register size and address size,
we need to redefine all of these. */
@ -359,8 +364,6 @@ static TCGv_reg cpu_psw_v;
static TCGv_reg cpu_psw_cb;
static TCGv_reg cpu_psw_cb_msb;
#include "exec/gen-icount.h"
void hppa_translate_init(void)
{
#define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUHPPAState, V) }
@ -2085,8 +2088,7 @@ static bool trans_mfctl(DisasContext *ctx, arg_mfctl *a)
/* FIXME: Respect PSW_S bit. */
nullify_over(ctx);
tmp = dest_gpr(ctx, rt);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
if (translator_io_start(&ctx->base)) {
gen_helper_read_interval_timer(tmp);
ctx->base.is_jmp = DISAS_IAQ_N_STALE;
} else {

View file

@ -28,6 +28,9 @@
#include "monitor/monitor.h"
#endif
#include "qemu/log.h"
#ifdef CONFIG_TCG
#include "tcg/insn-start-words.h"
#endif
void cpu_sync_avx_hflag(CPUX86State *env)
{

View file

@ -34,6 +34,11 @@
#include "exec/log.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
#define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 0x02
#define PREFIX_LOCK 0x04
@ -73,8 +78,6 @@ static TCGv cpu_seg_base[6];
static TCGv_i64 cpu_bndl[4];
static TCGv_i64 cpu_bndu[4];
#include "exec/gen-icount.h"
typedef struct DisasContext {
DisasContextBase base;
@ -3928,10 +3931,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
!(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
goto illegal_op;
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
s->base.is_jmp = DISAS_TOO_MANY;
}
translator_io_start(&s->base);
gen_helper_rdrand(s->T0, cpu_env);
rm = (modrm & 7) | REX_B(s);
gen_op_mov_reg_v(s, dflag, rm, s->T0);
@ -4969,10 +4969,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
SVM_IOIO_TYPE_MASK | SVM_IOIO_STR_MASK)) {
break;
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
s->base.is_jmp = DISAS_TOO_MANY;
}
translator_io_start(&s->base);
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz_ins(s, ot);
} else {
@ -4987,10 +4984,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_STR_MASK)) {
break;
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
s->base.is_jmp = DISAS_TOO_MANY;
}
translator_io_start(&s->base);
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz_outs(s, ot);
} else {
@ -5009,10 +5003,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_TYPE_MASK)) {
break;
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
s->base.is_jmp = DISAS_TOO_MANY;
}
translator_io_start(&s->base);
gen_helper_in_func(ot, s->T1, s->tmp2_i32);
gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
gen_bpt_io(s, s->tmp2_i32, ot);
@ -5025,10 +5016,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (!gen_check_io(s, ot, s->tmp2_i32, 0)) {
break;
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
s->base.is_jmp = DISAS_TOO_MANY;
}
translator_io_start(&s->base);
gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
@ -5042,10 +5030,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_TYPE_MASK)) {
break;
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
s->base.is_jmp = DISAS_TOO_MANY;
}
translator_io_start(&s->base);
gen_helper_in_func(ot, s->T1, s->tmp2_i32);
gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
gen_bpt_io(s, s->tmp2_i32, ot);
@ -5058,10 +5043,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (!gen_check_io(s, ot, s->tmp2_i32, 0)) {
break;
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
s->base.is_jmp = DISAS_TOO_MANY;
}
translator_io_start(&s->base);
gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
@ -5669,10 +5651,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0x131: /* rdtsc */
gen_update_cc_op(s);
gen_update_eip_cur(s);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
s->base.is_jmp = DISAS_TOO_MANY;
}
translator_io_start(&s->base);
gen_helper_rdtsc(cpu_env);
break;
case 0x133: /* rdpmc */
@ -6128,10 +6107,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
gen_update_cc_op(s);
gen_update_eip_cur(s);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
s->base.is_jmp = DISAS_TOO_MANY;
}
translator_io_start(&s->base);
gen_helper_rdtscp(cpu_env);
break;
@ -6485,10 +6461,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
ot = (CODE64(s) ? MO_64 : MO_32);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
s->base.is_jmp = DISAS_TOO_MANY;
}
translator_io_start(&s->base);
if (b & 2) {
gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0 + reg);
gen_op_mov_v_reg(s, ot, s->T0, rm);

View file

@ -39,9 +39,7 @@ static bool gen_rdtime(DisasContext *ctx, arg_rr *a,
TCGv dst1 = gpr_dst(ctx, a->rd, EXT_NONE);
TCGv dst2 = gpr_dst(ctx, a->rj, EXT_NONE);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_rdtime_d(dst1, cpu_env);
if (word) {
tcg_gen_sextract_tl(dst1, dst1, high ? 32 : 0, 32);

View file

@ -185,9 +185,7 @@ static bool check_csr_flags(DisasContext *ctx, const CSRInfo *csr, bool write)
if ((csr->flags & CSRFL_READONLY) && write) {
return false;
}
if ((csr->flags & CSRFL_IO) &&
(tb_cflags(ctx->base.tb) & CF_USE_ICOUNT)) {
gen_io_start();
if ((csr->flags & CSRFL_IO) && translator_io_start(&ctx->base)) {
ctx->base.is_jmp = DISAS_EXIT_UPDATE;
} else if ((csr->flags & CSRFL_EXITTB) && write) {
ctx->base.is_jmp = DISAS_EXIT_UPDATE;

View file

@ -9,11 +9,10 @@
#include "cpu.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "exec/translation-block.h"
#include "exec/translator.h"
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
#include "exec/log.h"
#include "qemu/qemu-print.h"
#include "fpu/softfloat.h"
@ -24,7 +23,9 @@
TCGv cpu_gpr[32], cpu_pc;
static TCGv cpu_lladdr, cpu_llval;
#include "exec/gen-icount.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
#define DISAS_STOP DISAS_TARGET_0
#define DISAS_EXIT DISAS_TARGET_1

View file

@ -34,6 +34,9 @@
#include "exec/log.h"
#include "fpu/softfloat.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
//#define DEBUG_DISPATCH 1
@ -62,8 +65,6 @@ static TCGv NULL_QREG;
/* Used to distinguish stores from bad addressing modes. */
static TCGv store_dummy;
#include "exec/gen-icount.h"
void m68k_tcg_init(void)
{
char *p;

View file

@ -31,6 +31,10 @@
#include "exec/log.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
#define EXTRACT_FIELD(src, start, end) \
(((src) >> start) & ((1 << (end - start + 1)) - 1))
@ -54,8 +58,6 @@ static TCGv_i32 cpu_iflags;
static TCGv cpu_res_addr;
static TCGv_i32 cpu_res_val;
#include "exec/gen-icount.h"
/* This is the state at translation time. */
typedef struct DisasContext {
DisasContextBase base;

View file

@ -11,11 +11,8 @@
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "exec/helper-gen.h"
#include "translate.h"
#include "fpu_helper.h"
#include "internal.h"
static int elm_n(DisasContext *ctx, int x);
static int elm_df(DisasContext *ctx, int x);

View file

@ -16,8 +16,6 @@
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "exec/helper-gen.h"
#include "translate.h"
/*

View file

@ -7,10 +7,8 @@
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "exec/helper-gen.h"
#include "translate.h"
#include "tcg/tcg-op-gvec.h"
/* Include the auto-generated decoder. */
#include "decode-octeon.c.inc"

View file

@ -9,8 +9,6 @@
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "exec/helper-gen.h"
#include "translate.h"
/* Include the auto-generated decoders. */

View file

@ -23,19 +23,19 @@
*/
#include "qemu/osdep.h"
#include "cpu.h"
#include "internal.h"
#include "tcg/tcg-op.h"
#include "exec/translator.h"
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
#include "semihosting/semihost.h"
#include "trace.h"
#include "exec/log.h"
#include "qemu/qemu-print.h"
#include "fpu_helper.h"
#include "translate.h"
#include "internal.h"
#include "exec/helper-proto.h"
#include "exec/translation-block.h"
#include "semihosting/semihost.h"
#include "trace.h"
#include "disas/disas.h"
#include "fpu_helper.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
/*
* Many sysemu-only helpers are not reachable for user-only.
@ -1210,8 +1210,6 @@ static TCGv_i32 hflags;
TCGv_i32 fpu_fcr0, fpu_fcr31;
TCGv_i64 fpu_f64[32];
#include "exec/gen-icount.h"
static const char regnames_HI[][4] = {
"HI0", "HI1", "HI2", "HI3",
};
@ -5665,9 +5663,8 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
switch (sel) {
case CP0_REG09__COUNT:
/* Mark as an IO operation because we read the time. */
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_mfc0_count(arg, cpu_env);
/*
* Break the TB to be able to take timer interrupts immediately
@ -6106,14 +6103,13 @@ cp0_unimplemented:
static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
{
const char *register_name = "invalid";
bool icount;
if (sel != 0) {
check_insn(ctx, ISA_MIPS_R1);
}
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
icount = translator_io_start(&ctx->base);
switch (reg) {
case CP0_REGISTER_00:
@ -6851,7 +6847,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
trace_mips_translate_c0("mtc0", register_name, reg, sel);
/* For simplicity assume that all writes can cause interrupts. */
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
if (icount) {
/*
* DISAS_STOP isn't sufficient, we need to ensure we break out of
* translated code to check for pending interrupts.
@ -7168,9 +7164,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
switch (sel) {
case CP0_REG09__COUNT:
/* Mark as an IO operation because we read the time. */
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_mfc0_count(arg, cpu_env);
/*
* Break the TB to be able to take timer interrupts immediately
@ -7596,14 +7590,13 @@ cp0_unimplemented:
static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
{
const char *register_name = "invalid";
bool icount;
if (sel != 0) {
check_insn(ctx, ISA_MIPS_R1);
}
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
icount = translator_io_start(&ctx->base);
switch (reg) {
case CP0_REGISTER_00:
@ -8331,7 +8324,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
trace_mips_translate_c0("dmtc0", register_name, reg, sel);
/* For simplicity assume that all writes can cause interrupts. */
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
if (icount) {
/*
* DISAS_STOP isn't sufficient, we need to ensure we break out of
* translated code to check for pending interrupts.
@ -11142,9 +11135,7 @@ void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
gen_store_gpr(t0, rt);
break;
case 2:
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_rdhwr_cc(t0, cpu_env);
gen_store_gpr(t0, rt);
/*

View file

@ -8,8 +8,11 @@
#ifndef TARGET_MIPS_TRANSLATE_H
#define TARGET_MIPS_TRANSLATE_H
#include "qemu/log.h"
#include "cpu.h"
#include "tcg/tcg-op.h"
#include "exec/translator.h"
#include "exec/helper-gen.h"
#include "qemu/log.h"
#define MIPS_DEBUG_DISAS 0

View file

@ -11,7 +11,6 @@
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "translate.h"
bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa)

View file

@ -8,10 +8,8 @@
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "exec/helper-gen.h"
#include "translate.h"
#include "tcg/tcg-op-gvec.h"
/* Include the auto-generated decoder. */
#include "decode-tx79.c.inc"

View file

@ -10,10 +10,7 @@
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "exec/helper-gen.h"
#include "translate.h"
#include "internal.h"
/* Include the auto-generated decoder. */
#include "decode-vr54xx.c.inc"

View file

@ -32,9 +32,13 @@
#include "exec/cpu_ldst.h"
#include "exec/translator.h"
#include "qemu/qemu-print.h"
#include "exec/gen-icount.h"
#include "semihosting/semihost.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
/* is_jmp field values */
#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */

View file

@ -26,6 +26,7 @@
#ifndef CONFIG_USER_ONLY
#include "hw/boards.h"
#endif
#include "tcg/insn-start-words.h"
#define TO_SPR(group, number) (((group) << 11) + (number))

View file

@ -31,10 +31,14 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
#include "exec/gen-icount.h"
#include "exec/log.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
/* is_jmp field values */
#define DISAS_EXIT DISAS_TARGET_0 /* force exit to main loop */
#define DISAS_JUMP DISAS_TARGET_1 /* exit via jmp_pc/jmp_pc_imm */
@ -823,8 +827,7 @@ static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
check_r0_write(dc, a->d);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
if (translator_io_start(&dc->base)) {
if (dc->delayed_branch) {
tcg_gen_mov_tl(cpu_pc, jmp_pc);
tcg_gen_discard_tl(jmp_pc);
@ -843,9 +846,8 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
{
TCGv spr = tcg_temp_new();
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
/*
* For SR, we will need to exit the TB to recognize the new
* exception state. For NPC, in theory this counts as a branch

View file

@ -1394,7 +1394,6 @@ void ppc_store_msr(CPUPPCState *env, target_ulong value);
void ppc_cpu_list(void);
/* Time-base and decrementer management */
#ifndef NO_CPU_IO_DEFS
uint64_t cpu_ppc_load_tbl(CPUPPCState *env);
uint32_t cpu_ppc_load_tbu(CPUPPCState *env);
void cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value);
@ -1435,7 +1434,6 @@ int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
ppcmas_tlb_t *tlb);
#endif
#endif
void ppc_store_fpscr(CPUPPCState *env, target_ulong val);
void helper_hfscr_facility_check(CPUPPCState *env, uint32_t bit,

View file

@ -103,9 +103,9 @@ static void write_MMCR0_common(DisasContext *ctx, TCGv val)
/*
* helper_store_mmcr0 will make clock based operations that
* will cause 'bad icount read' errors if we do not execute
* gen_icount_io_start() beforehand.
* translator_io_start() beforehand.
*/
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_mmcr0(cpu_env, val);
/*
@ -179,7 +179,7 @@ void spr_read_PMC(DisasContext *ctx, int gprn, int sprn)
{
TCGv_i32 t_sprn = tcg_constant_i32(sprn);
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_read_pmc(cpu_gpr[gprn], cpu_env, t_sprn);
}
@ -212,7 +212,7 @@ void spr_write_PMC(DisasContext *ctx, int sprn, int gprn)
{
TCGv_i32 t_sprn = tcg_constant_i32(sprn);
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_pmc(cpu_env, t_sprn, cpu_gpr[gprn]);
}
@ -248,7 +248,7 @@ void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_mmcr1(cpu_env, cpu_gpr[gprn]);
}
#else

View file

@ -41,6 +41,10 @@
#include "qemu/qemu-print.h"
#include "qapi/error.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
#define CPU_SINGLE_STEP 0x1
#define CPU_BRANCH_STEP 0x2
@ -76,8 +80,6 @@ static TCGv cpu_reserve_val2;
static TCGv cpu_fpscr;
static TCGv_i32 cpu_access_type;
#include "exec/gen-icount.h"
void ppc_translate_init(void)
{
int i;
@ -294,24 +296,10 @@ static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
ctx->base.is_jmp = DISAS_NORETURN;
}
static void gen_icount_io_start(DisasContext *ctx)
{
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
/*
* An I/O instruction must be last in the TB.
* Chain to the next TB, and let the code from gen_tb_start
* decide if we need to return to the main loop.
* Doing this first also allows this value to be overridden.
*/
ctx->base.is_jmp = DISAS_TOO_MANY;
}
}
#if !defined(CONFIG_USER_ONLY)
static void gen_ppc_maybe_interrupt(DisasContext *ctx)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_ppc_maybe_interrupt(cpu_env);
}
#endif
@ -548,13 +536,13 @@ void spr_write_ureg(DisasContext *ctx, int sprn, int gprn)
#if !defined(CONFIG_USER_ONLY)
void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_decr(cpu_gpr[gprn], cpu_env);
}
void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_decr(cpu_env, cpu_gpr[gprn]);
}
#endif
@ -563,13 +551,13 @@ void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
/* Time base */
void spr_read_tbl(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_tbl(cpu_gpr[gprn], cpu_env);
}
void spr_read_tbu(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_tbu(cpu_gpr[gprn], cpu_env);
}
@ -586,13 +574,13 @@ void spr_read_atbu(DisasContext *ctx, int gprn, int sprn)
#if !defined(CONFIG_USER_ONLY)
void spr_write_tbl(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_tbl(cpu_env, cpu_gpr[gprn]);
}
void spr_write_tbu(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_tbu(cpu_env, cpu_gpr[gprn]);
}
@ -609,44 +597,44 @@ void spr_write_atbu(DisasContext *ctx, int sprn, int gprn)
#if defined(TARGET_PPC64)
void spr_read_purr(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
}
void spr_write_purr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_purr(cpu_env, cpu_gpr[gprn]);
}
/* HDECR */
void spr_read_hdecr(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_hdecr(cpu_gpr[gprn], cpu_env);
}
void spr_write_hdecr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_hdecr(cpu_env, cpu_gpr[gprn]);
}
void spr_read_vtb(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_vtb(cpu_gpr[gprn], cpu_env);
}
void spr_write_vtb(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_vtb(cpu_env, cpu_gpr[gprn]);
}
void spr_write_tbu40(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_tbu40(cpu_env, cpu_gpr[gprn]);
}
@ -791,19 +779,19 @@ void spr_write_dpdes(DisasContext *ctx, int sprn, int gprn)
#if !defined(CONFIG_USER_ONLY)
void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_40x_pit(cpu_gpr[gprn], cpu_env);
}
void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_40x_pit(cpu_env, cpu_gpr[gprn]);
}
void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_store_spr(sprn, cpu_gpr[gprn]);
gen_helper_store_40x_dbcr0(cpu_env, cpu_gpr[gprn]);
/* We must stop translation as we may have rebooted */
@ -812,19 +800,19 @@ void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn)
void spr_write_40x_sler(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_40x_sler(cpu_env, cpu_gpr[gprn]);
}
void spr_write_40x_tcr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_40x_tcr(cpu_env, cpu_gpr[gprn]);
}
void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_40x_tsr(cpu_env, cpu_gpr[gprn]);
}
@ -837,13 +825,13 @@ void spr_write_40x_pid(DisasContext *ctx, int sprn, int gprn)
void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_booke_tcr(cpu_env, cpu_gpr[gprn]);
}
void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_booke_tsr(cpu_env, cpu_gpr[gprn]);
}
#endif
@ -2469,7 +2457,7 @@ static void gen_darn(DisasContext *ctx)
if (l > 2) {
tcg_gen_movi_i64(cpu_gpr[rD(ctx->opcode)], -1);
} else {
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
if (l == 0) {
gen_helper_darn32(cpu_gpr[rD(ctx->opcode)]);
} else {
@ -4063,7 +4051,7 @@ static void pmu_count_insns(DisasContext *ctx)
* running with icount and we do not handle it beforehand,
* the helper can trigger a 'bad icount read'.
*/
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
/* Avoid helper calls when only PMC5-6 are enabled. */
if (!ctx->pmc_other) {
@ -4376,7 +4364,7 @@ static void gen_rfi(DisasContext *ctx)
}
/* Restore CPU state */
CHK_SV(ctx);
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_update_cfar(ctx, ctx->cia);
gen_helper_rfi(cpu_env);
ctx->base.is_jmp = DISAS_EXIT;
@ -4391,7 +4379,7 @@ static void gen_rfid(DisasContext *ctx)
#else
/* Restore CPU state */
CHK_SV(ctx);
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_update_cfar(ctx, ctx->cia);
gen_helper_rfid(cpu_env);
ctx->base.is_jmp = DISAS_EXIT;
@ -4406,7 +4394,7 @@ static void gen_rfscv(DisasContext *ctx)
#else
/* Restore CPU state */
CHK_SV(ctx);
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_update_cfar(ctx, ctx->cia);
gen_helper_rfscv(cpu_env);
ctx->base.is_jmp = DISAS_EXIT;
@ -4731,7 +4719,7 @@ static void gen_mtmsrd(DisasContext *ctx)
t0 = tcg_temp_new();
t1 = tcg_temp_new();
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
if (ctx->opcode & 0x00010000) {
/* L=1 form only updates EE and RI */
@ -4771,7 +4759,7 @@ static void gen_mtmsr(DisasContext *ctx)
t0 = tcg_temp_new();
t1 = tcg_temp_new();
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
if (ctx->opcode & 0x00010000) {
/* L=1 form only updates EE and RI */
mask &= (1ULL << MSR_RI) | (1ULL << MSR_EE);

View file

@ -16,7 +16,7 @@ static bool trans_RFEBB(DisasContext *ctx, arg_XL_s *arg)
{
REQUIRE_INSNS_FLAGS2(ctx, ISA207S);
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_update_cfar(ctx, ctx->cia);
gen_helper_rfebb(cpu_env, cpu_gpr[arg->s]);

View file

@ -31,6 +31,7 @@
#include "sysemu/cpu-timers.h"
#include "cpu_bits.h"
#include "debug.h"
#include "tcg/oversized-guest.h"
int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
{

View file

@ -77,9 +77,7 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
#ifndef CONFIG_USER_ONLY
if (has_ext(ctx, RVS)) {
decode_save_opc(ctx);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_sret(cpu_pc, cpu_env);
exit_tb(ctx); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
@ -96,9 +94,7 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
{
#ifndef CONFIG_USER_ONLY
decode_save_opc(ctx);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_mret(cpu_pc, cpu_env);
exit_tb(ctx); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;

View file

@ -813,9 +813,7 @@ static bool do_csrr(DisasContext *ctx, int rd, int rc)
TCGv dest = dest_gpr(ctx, rd);
TCGv_i32 csr = tcg_constant_i32(rc);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrr(dest, cpu_env, csr);
gen_set_gpr(ctx, rd, dest);
return do_csr_post(ctx);
@ -825,9 +823,7 @@ static bool do_csrw(DisasContext *ctx, int rc, TCGv src)
{
TCGv_i32 csr = tcg_constant_i32(rc);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrw(cpu_env, csr, src);
return do_csr_post(ctx);
}
@ -837,9 +833,7 @@ static bool do_csrrw(DisasContext *ctx, int rd, int rc, TCGv src, TCGv mask)
TCGv dest = dest_gpr(ctx, rd);
TCGv_i32 csr = tcg_constant_i32(rc);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrrw(dest, cpu_env, csr, src, mask);
gen_set_gpr(ctx, rd, dest);
return do_csr_post(ctx);
@ -851,9 +845,7 @@ static bool do_csrr_i128(DisasContext *ctx, int rd, int rc)
TCGv desth = dest_gprh(ctx, rd);
TCGv_i32 csr = tcg_constant_i32(rc);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrr_i128(destl, cpu_env, csr);
tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
gen_set_gpr128(ctx, rd, destl, desth);
@ -864,9 +856,7 @@ static bool do_csrw_i128(DisasContext *ctx, int rc, TCGv srcl, TCGv srch)
{
TCGv_i32 csr = tcg_constant_i32(rc);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrw_i128(cpu_env, csr, srcl, srch);
return do_csr_post(ctx);
}
@ -878,9 +868,7 @@ static bool do_csrrw_i128(DisasContext *ctx, int rd, int rc,
TCGv desth = dest_gprh(ctx, rd);
TCGv_i32 csr = tcg_constant_i32(rc);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrrw_i128(destl, cpu_env, csr, srcl, srch, maskl, maskh);
tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
gen_set_gpr128(ctx, rd, destl, desth);

View file

@ -33,6 +33,10 @@
#include "instmap.h"
#include "internals.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
/* global register indices */
static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
@ -42,8 +46,6 @@ static TCGv load_val;
static TCGv pm_mask;
static TCGv pm_base;
#include "exec/gen-icount.h"
/*
* If an operation is being performed on less than TARGET_LONG_BITS,
* it may require the inputs to be sign- or zero-extended; which will

View file

@ -24,6 +24,7 @@
#include "exec/exec-all.h"
#include "hw/loader.h"
#include "fpu/softfloat.h"
#include "tcg/debug-assert.h"
static void rx_cpu_set_pc(CPUState *cs, vaddr value)
{

View file

@ -23,6 +23,7 @@
#include "exec/helper-proto.h"
#include "exec/cpu_ldst.h"
#include "fpu/softfloat.h"
#include "tcg/debug-assert.h"
static inline G_NORETURN
void raise_exception(CPURXState *env, int index,

View file

@ -28,6 +28,11 @@
#include "exec/translator.h"
#include "exec/log.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
typedef struct DisasContext {
DisasContextBase base;
CPURXState *env;
@ -68,8 +73,6 @@ static TCGv_i64 cpu_acc;
#define cpu_sp cpu_regs[0]
#include "exec/gen-icount.h"
/* decoder helper */
static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
int i, int n)

View file

@ -38,7 +38,6 @@
#include "qemu/log.h"
#include "qemu/host-utils.h"
#include "exec/cpu_ldst.h"
#include "exec/gen-icount.h"
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
@ -46,6 +45,10 @@
#include "exec/log.h"
#include "qemu/atomic128.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
/* Information that (most) every instruction needs to manipulate. */
typedef struct DisasContext DisasContext;
@ -6350,10 +6353,7 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
/* input/output is the special case for icount mode */
if (unlikely(insn->flags & IF_IO)) {
icount = tb_cflags(s->base.tb) & CF_USE_ICOUNT;
if (icount) {
gen_io_start();
}
icount = translator_io_start(&s->base);
}
}

View file

@ -29,6 +29,10 @@
#include "exec/log.h"
#include "qemu/qemu-print.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
typedef struct DisasContext {
DisasContextBase base;
@ -71,8 +75,6 @@ static TCGv cpu_fregs[32];
/* internal register indexes */
static TCGv cpu_flags, cpu_delayed_pc, cpu_delayed_cond;
#include "exec/gen-icount.h"
void sh4_translate_init(void)
{
int i;
@ -2142,9 +2144,7 @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
/* The entire region has been translated. */
ctx->envflags &= ~TB_FLAG_GUSA_MASK;
ctx->base.pc_next = pc_end;
ctx->base.num_insns += max_insns - 1;
return;
goto done;
fail:
qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n",
@ -2161,8 +2161,19 @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
purposes of accounting within the TB. We might as well report the
entire region consumed via ctx->base.pc_next so that it's immediately
available in the disassembly dump. */
done:
ctx->base.pc_next = pc_end;
ctx->base.num_insns += max_insns - 1;
/*
* Emit insn_start to cover each of the insns in the region.
* This matches an assert in tcg.c making sure that we have
* tb->icount * insn_start.
*/
for (i = 1; i < max_insns; ++i) {
tcg_gen_insn_start(pc + i * 2, ctx->envflags);
}
}
#endif

View file

@ -581,7 +581,6 @@ G_NORETURN void sparc_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
uintptr_t retaddr);
G_NORETURN void cpu_raise_exception_ra(CPUSPARCState *, int, uintptr_t);
#ifndef NO_CPU_IO_DEFS
/* cpu_init.c */
void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
void sparc_cpu_list(void);
@ -637,7 +636,6 @@ static inline int tlb_compare_context(const SparcTLBEntry *tlb,
return compare_masked(context, tlb->tag, MMU_CONTEXT_MASK);
}
#endif
#endif
/* cpu-exec.c */

View file

@ -33,6 +33,9 @@
#include "exec/log.h"
#include "asi.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
#define DYNAMIC_PC 1 /* dynamic pc value */
#define JUMP_PC 2 /* dynamic pc value which takes only two values
@ -63,8 +66,6 @@ static TCGv cpu_wim;
/* Floating point registers */
static TCGv_i64 cpu_fpr[TARGET_DPREGS];
#include "exec/gen-icount.h"
typedef struct DisasContext {
DisasContextBase base;
target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */
@ -3214,16 +3215,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_const = tcg_constant_i32(dc->mem_idx);
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, tick));
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
if (translator_io_start(&dc->base)) {
dc->base.is_jmp = DISAS_EXIT;
}
gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr,
r_const);
gen_store_gpr(dc, rd, cpu_dst);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
/* I/O operations in icount mode must end the TB */
dc->base.is_jmp = DISAS_EXIT;
}
}
break;
case 0x5: /* V9 rdpc */
@ -3266,16 +3263,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_const = tcg_constant_i32(dc->mem_idx);
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, stick));
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
if (translator_io_start(&dc->base)) {
dc->base.is_jmp = DISAS_EXIT;
}
gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr,
r_const);
gen_store_gpr(dc, rd, cpu_dst);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
/* I/O operations in icount mode must end the TB */
dc->base.is_jmp = DISAS_EXIT;
}
}
break;
case 0x19: /* System tick compare */
@ -3396,15 +3389,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_const = tcg_constant_i32(dc->mem_idx);
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, tick));
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
if (translator_io_start(&dc->base)) {
dc->base.is_jmp = DISAS_EXIT;
}
gen_helper_tick_get_count(cpu_tmp0, cpu_env,
r_tickptr, r_const);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
/* I/O operations in icount mode must end the TB */
dc->base.is_jmp = DISAS_EXIT;
}
}
break;
case 5: // tba
@ -4209,10 +4198,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_tickptr = tcg_temp_new_ptr();
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, tick));
if (tb_cflags(dc->base.tb) &
CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_tick_set_limit(r_tickptr,
cpu_tick_cmpr);
/* End TB to handle timer interrupt */
@ -4232,10 +4218,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_tickptr = tcg_temp_new_ptr();
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, stick));
if (tb_cflags(dc->base.tb) &
CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_tick_set_count(r_tickptr,
cpu_tmp0);
/* End TB to handle timer interrupt */
@ -4255,10 +4238,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_tickptr = tcg_temp_new_ptr();
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, stick));
if (tb_cflags(dc->base.tb) &
CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_tick_set_limit(r_tickptr,
cpu_stick_cmpr);
/* End TB to handle timer interrupt */
@ -4366,10 +4346,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_tickptr = tcg_temp_new_ptr();
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, tick));
if (tb_cflags(dc->base.tb) &
CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_tick_set_count(r_tickptr,
cpu_tmp0);
/* End TB to handle timer interrupt */
@ -4381,14 +4358,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
break;
case 6: // pstate
save_state(dc);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
gen_helper_wrpstate(cpu_env, cpu_tmp0);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
/* I/O ops in icount mode must end the TB */
if (translator_io_start(&dc->base)) {
dc->base.is_jmp = DISAS_EXIT;
}
gen_helper_wrpstate(cpu_env, cpu_tmp0);
dc->npc = DYNAMIC_PC;
break;
case 7: // tl
@ -4398,14 +4371,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
dc->npc = DYNAMIC_PC;
break;
case 8: // pil
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
gen_helper_wrpil(cpu_env, cpu_tmp0);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
/* I/O ops in icount mode must end the TB */
if (translator_io_start(&dc->base)) {
dc->base.is_jmp = DISAS_EXIT;
}
gen_helper_wrpil(cpu_env, cpu_tmp0);
break;
case 9: // cwp
gen_helper_wrcwp(cpu_env, cpu_tmp0);
@ -4496,10 +4465,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_tickptr = tcg_temp_new_ptr();
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, hstick));
if (tb_cflags(dc->base.tb) &
CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_tick_set_limit(r_tickptr,
cpu_hstick_cmpr);
/* End TB to handle timer interrupt */
@ -5122,9 +5088,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto priv_insn;
dc->npc = DYNAMIC_PC;
dc->pc = DYNAMIC_PC;
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_done(cpu_env);
goto jmp_insn;
case 1:
@ -5132,9 +5096,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto priv_insn;
dc->npc = DYNAMIC_PC;
dc->pc = DYNAMIC_PC;
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_retry(cpu_env);
goto jmp_insn;
default:

View file

@ -22,6 +22,7 @@
#include "cpu.h"
#include "exec/exec-all.h"
#include "qemu/error-report.h"
#include "tcg/debug-assert.h"
static inline void set_feature(CPUTriCoreState *env, int feature)
{

View file

@ -33,6 +33,11 @@
#include "exec/translator.h"
#include "exec/log.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
/*
* TCG registers
*/
@ -50,8 +55,6 @@ static TCGv cpu_PSW_SV;
static TCGv cpu_PSW_AV;
static TCGv cpu_PSW_SAV;
#include "exec/gen-icount.h"
static const char *regnames_a[] = {
"a0" , "a1" , "a2" , "a3" , "a4" , "a5" ,
"a6" , "a7" , "a8" , "a9" , "sp" , "a11" ,

View file

@ -45,6 +45,10 @@
#include "exec/log.h"
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
struct DisasContext {
DisasContextBase base;
@ -90,8 +94,6 @@ static TCGv_i32 cpu_exclusive_val;
static GHashTable *xtensa_regfile_table;
#include "exec/gen-icount.h"
static char *sr_name[256];
static char *ur_name[256];
@ -573,9 +575,7 @@ static int gen_postprocess(DisasContext *dc, int slot)
#ifndef CONFIG_USER_ONLY
if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) {
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_check_interrupts(cpu_env);
}
#endif
@ -2125,9 +2125,7 @@ static void translate_rsr_ccount(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_update_ccount(cpu_env);
tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]);
#endif
@ -2443,9 +2441,7 @@ static void translate_waiti(DisasContext *dc, const OpcodeArg arg[],
#ifndef CONFIG_USER_ONLY
TCGv_i32 pc = tcg_constant_i32(dc->base.pc_next);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_waiti(cpu_env, pc, tcg_constant_i32(arg[0].imm));
#endif
}
@ -2510,9 +2506,7 @@ static void translate_wsr_ccompare(DisasContext *dc, const OpcodeArg arg[],
uint32_t id = par[0] - CCOMPARE;
assert(id < dc->config->nccompare);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
tcg_gen_mov_i32(cpu_SR[par[0]], arg[0].in);
gen_helper_update_ccompare(cpu_env, tcg_constant_i32(id));
#endif
@ -2522,9 +2516,7 @@ static void translate_wsr_ccount(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_wsr_ccount(cpu_env, arg[0].in);
#endif
}
@ -2711,10 +2703,7 @@ static void translate_xsr_ccount(DisasContext *dc, const OpcodeArg arg[],
#ifndef CONFIG_USER_ONLY
TCGv_i32 tmp = tcg_temp_new_i32();
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_update_ccount(cpu_env);
tcg_gen_mov_i32(tmp, cpu_SR[par[0]]);
gen_helper_wsr_ccount(cpu_env, arg[0].in);

Some files were not shown because too many files have changed in this diff Show more