mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-13 18:48:08 +00:00
experimental x86 support for compcov in QEMU
This commit is contained in:
@ -133,6 +133,7 @@ patch -p1 <../patches/cpu-exec.diff || exit 1
|
|||||||
patch -p1 <../patches/syscall.diff || exit 1
|
patch -p1 <../patches/syscall.diff || exit 1
|
||||||
patch -p1 <../patches/translate-all.diff || exit 1
|
patch -p1 <../patches/translate-all.diff || exit 1
|
||||||
patch -p1 <../patches/tcg.diff || exit 1
|
patch -p1 <../patches/tcg.diff || exit 1
|
||||||
|
patch -p1 <../patches/i386-translate.diff || exit 1
|
||||||
|
|
||||||
echo "[+] Patching done."
|
echo "[+] Patching done."
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
TCG instrumentation and block chaining support by Andrea Biondo
|
TCG instrumentation and block chaining support by Andrea Biondo
|
||||||
<andrea.biondo965@gmail.com>
|
<andrea.biondo965@gmail.com>
|
||||||
QEMU 3.1.0 port and thread-safety by Andrea Fioraldi
|
|
||||||
|
QEMU 3.1.0 port, TCG thread-safety and CompareCoverage by Andrea Fioraldi
|
||||||
<andreafioraldi@gmail.com>
|
<andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
|
||||||
@ -65,6 +66,8 @@ abi_ulong afl_entry_point, /* ELF entry point (_start) */
|
|||||||
afl_start_code, /* .text start pointer */
|
afl_start_code, /* .text start pointer */
|
||||||
afl_end_code; /* .text end pointer */
|
afl_end_code; /* .text end pointer */
|
||||||
|
|
||||||
|
u8 afl_enable_compcov;
|
||||||
|
|
||||||
/* Set in the child process in forkserver mode: */
|
/* Set in the child process in forkserver mode: */
|
||||||
|
|
||||||
static int forkserver_installed = 0;
|
static int forkserver_installed = 0;
|
||||||
@ -156,6 +159,12 @@ static void afl_setup(void) {
|
|||||||
afl_end_code = (abi_ulong)-1;
|
afl_end_code = (abi_ulong)-1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getenv("AFL_QEMU_COMPCOV")) {
|
||||||
|
|
||||||
|
fprintf(stderr, "EEe\n");
|
||||||
|
afl_enable_compcov = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* pthread_atfork() seems somewhat broken in util/rcu.c, and I'm
|
/* pthread_atfork() seems somewhat broken in util/rcu.c, and I'm
|
||||||
not entirely sure what is the cause. This disables that
|
not entirely sure what is the cause. This disables that
|
||||||
|
125
qemu_mode/patches/afl-qemu-cpu-translate-inl.h
Normal file
125
qemu_mode/patches/afl-qemu-cpu-translate-inl.h
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
american fuzzy lop - high-performance binary-only instrumentation
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
|
||||||
|
Written by Andrew Griffiths <agriffiths@google.com> and
|
||||||
|
Michal Zalewski <lcamtuf@google.com>
|
||||||
|
|
||||||
|
Idea & design very much by Andrew Griffiths.
|
||||||
|
|
||||||
|
TCG instrumentation and block chaining support by Andrea Biondo
|
||||||
|
<andrea.biondo965@gmail.com>
|
||||||
|
|
||||||
|
QEMU 3.1.0 port, TCG thread-safety and CompareCoverage by Andrea Fioraldi
|
||||||
|
<andreafioraldi@gmail.com>
|
||||||
|
|
||||||
|
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at:
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
This code is a shim patched into the separately-distributed source
|
||||||
|
code of QEMU 3.1.0. It leverages the built-in QEMU tracing functionality
|
||||||
|
to implement AFL-style instrumentation and to take care of the remaining
|
||||||
|
parts of the AFL fork server logic.
|
||||||
|
|
||||||
|
The resulting QEMU binary is essentially a standalone instrumentation
|
||||||
|
tool; for an example of how to leverage it for other purposes, you can
|
||||||
|
have a look at afl-showmap.c.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../config.h"
|
||||||
|
#include "tcg.h"
|
||||||
|
#include "tcg-op.h"
|
||||||
|
|
||||||
|
/* Declared in afl-qemu-cpu-inl.h */
|
||||||
|
extern unsigned char *afl_area_ptr;
|
||||||
|
extern unsigned int afl_inst_rms;
|
||||||
|
extern abi_ulong afl_start_code, afl_end_code;
|
||||||
|
extern u8 afl_enable_compcov;
|
||||||
|
|
||||||
|
void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc,
|
||||||
|
TCGv_i64 arg1, TCGv_i64 arg2);
|
||||||
|
|
||||||
|
static void afl_compcov_log_16(target_ulong cur_loc, target_ulong arg1,
|
||||||
|
target_ulong arg2) {
|
||||||
|
|
||||||
|
if ((arg1 & 0xff) == (arg2 & 0xff)) {
|
||||||
|
afl_area_ptr[cur_loc]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void afl_compcov_log_32(target_ulong cur_loc, target_ulong arg1,
|
||||||
|
target_ulong arg2) {
|
||||||
|
|
||||||
|
if ((arg1 & 0xff) == (arg2 & 0xff)) {
|
||||||
|
afl_area_ptr[cur_loc]++;
|
||||||
|
if ((arg1 & 0xffff) == (arg2 & 0xffff)) {
|
||||||
|
afl_area_ptr[cur_loc +1]++;
|
||||||
|
if ((arg1 & 0xffffff) == (arg2 & 0xffffff)) {
|
||||||
|
afl_area_ptr[cur_loc +2]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void afl_compcov_log_64(target_ulong cur_loc, target_ulong arg1,
|
||||||
|
target_ulong arg2) {
|
||||||
|
|
||||||
|
if ((arg1 & 0xff) == (arg2 & 0xff)) {
|
||||||
|
afl_area_ptr[cur_loc]++;
|
||||||
|
if ((arg1 & 0xffff) == (arg2 & 0xffff)) {
|
||||||
|
afl_area_ptr[cur_loc +1]++;
|
||||||
|
if ((arg1 & 0xffffff) == (arg2 & 0xffffff)) {
|
||||||
|
afl_area_ptr[cur_loc +2]++;
|
||||||
|
if ((arg1 & 0xffffffff) == (arg2 & 0xffffffff)) {
|
||||||
|
afl_area_ptr[cur_loc +3]++;
|
||||||
|
if ((arg1 & 0xffffffff) == (arg2 & 0xffffffffff)) {
|
||||||
|
afl_area_ptr[cur_loc +4]++;
|
||||||
|
if ((arg1 & 0xffffffff) == (arg2 & 0xffffffffffff)) {
|
||||||
|
afl_area_ptr[cur_loc +5]++;
|
||||||
|
if ((arg1 & 0xffffffff) == (arg2 & 0xffffffffffffff)) {
|
||||||
|
afl_area_ptr[cur_loc +6]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void afl_gen_compcov(target_ulong cur_loc, TCGv_i64 arg1, TCGv_i64 arg2,
|
||||||
|
TCGMemOp ot) {
|
||||||
|
|
||||||
|
void *func;
|
||||||
|
|
||||||
|
if (!afl_enable_compcov || cur_loc > afl_end_code || cur_loc < afl_start_code)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (ot) {
|
||||||
|
case MO_64:
|
||||||
|
func = &afl_compcov_log_64;
|
||||||
|
break;
|
||||||
|
case MO_32:
|
||||||
|
func = &afl_compcov_log_32;
|
||||||
|
break;
|
||||||
|
case MO_16:
|
||||||
|
func = &afl_compcov_log_16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
|
||||||
|
cur_loc &= MAP_SIZE - 1;
|
||||||
|
|
||||||
|
if (cur_loc >= afl_inst_rms) return;
|
||||||
|
|
||||||
|
tcg_gen_afl_compcov_log_call(func, cur_loc, arg1, arg2);
|
||||||
|
}
|
@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
TCG instrumentation and block chaining support by Andrea Biondo
|
TCG instrumentation and block chaining support by Andrea Biondo
|
||||||
<andrea.biondo965@gmail.com>
|
<andrea.biondo965@gmail.com>
|
||||||
QEMU 3.1.0 port and thread-safety by Andrea Fioraldi
|
|
||||||
|
QEMU 3.1.0 port, TCG thread-safety and CompareCoverage by Andrea Fioraldi
|
||||||
<andreafioraldi@gmail.com>
|
<andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
|
||||||
@ -42,10 +43,10 @@ void tcg_gen_afl_maybe_log_call(target_ulong cur_loc)
|
|||||||
unsigned sizemask, flags;
|
unsigned sizemask, flags;
|
||||||
TCGOp *op;
|
TCGOp *op;
|
||||||
|
|
||||||
TCGTemp *arg = tcgv_ptr_temp( tcg_const_tl(cur_loc) );
|
TCGTemp *arg = tcgv_i64_temp( tcg_const_tl(cur_loc) );
|
||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
sizemask = dh_sizemask(void, 0) | dh_sizemask(ptr, 1);
|
sizemask = dh_sizemask(void, 0) | dh_sizemask(i64, 1);
|
||||||
|
|
||||||
#if defined(__sparc__) && !defined(__arch64__) \
|
#if defined(__sparc__) && !defined(__arch64__) \
|
||||||
&& !defined(CONFIG_TCG_INTERPRETER)
|
&& !defined(CONFIG_TCG_INTERPRETER)
|
||||||
@ -151,7 +152,7 @@ void tcg_gen_afl_maybe_log_call(target_ulong cur_loc)
|
|||||||
/* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
|
/* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
|
||||||
Note that describing these as TCGv_i64 eliminates an unnecessary
|
Note that describing these as TCGv_i64 eliminates an unnecessary
|
||||||
zero-extension that tcg_gen_concat_i32_i64 would create. */
|
zero-extension that tcg_gen_concat_i32_i64 would create. */
|
||||||
tcg_gen_concat32_i64(temp_tcgv_i64(ret), retl, reth);
|
tcg_gen_concat32_i64(temp_tcgv_i64(NULL), retl, reth);
|
||||||
tcg_temp_free_i64(retl);
|
tcg_temp_free_i64(retl);
|
||||||
tcg_temp_free_i64(reth);
|
tcg_temp_free_i64(reth);
|
||||||
}
|
}
|
||||||
@ -163,3 +164,143 @@ void tcg_gen_afl_maybe_log_call(target_ulong cur_loc)
|
|||||||
#endif /* TCG_TARGET_EXTEND_ARGS */
|
#endif /* TCG_TARGET_EXTEND_ARGS */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc, TCGv_i64 arg1, TCGv_i64 arg2)
|
||||||
|
{
|
||||||
|
int i, real_args, nb_rets, pi;
|
||||||
|
unsigned sizemask, flags;
|
||||||
|
TCGOp *op;
|
||||||
|
|
||||||
|
const int nargs = 3;
|
||||||
|
TCGTemp *args[3] = { tcgv_i64_temp( tcg_const_tl(cur_loc) ),
|
||||||
|
tcgv_i64_temp(arg1),
|
||||||
|
tcgv_i64_temp(arg2) };
|
||||||
|
|
||||||
|
flags = 0;
|
||||||
|
sizemask = dh_sizemask(void, 0) | dh_sizemask(i64, 1) |
|
||||||
|
dh_sizemask(i64, 2) | dh_sizemask(i64, 3);
|
||||||
|
|
||||||
|
#if defined(__sparc__) && !defined(__arch64__) \
|
||||||
|
&& !defined(CONFIG_TCG_INTERPRETER)
|
||||||
|
/* We have 64-bit values in one register, but need to pass as two
|
||||||
|
separate parameters. Split them. */
|
||||||
|
int orig_sizemask = sizemask;
|
||||||
|
int orig_nargs = nargs;
|
||||||
|
TCGv_i64 retl, reth;
|
||||||
|
TCGTemp *split_args[MAX_OPC_PARAM];
|
||||||
|
|
||||||
|
retl = NULL;
|
||||||
|
reth = NULL;
|
||||||
|
if (sizemask != 0) {
|
||||||
|
for (i = real_args = 0; i < nargs; ++i) {
|
||||||
|
int is_64bit = sizemask & (1 << (i+1)*2);
|
||||||
|
if (is_64bit) {
|
||||||
|
TCGv_i64 orig = temp_tcgv_i64(args[i]);
|
||||||
|
TCGv_i32 h = tcg_temp_new_i32();
|
||||||
|
TCGv_i32 l = tcg_temp_new_i32();
|
||||||
|
tcg_gen_extr_i64_i32(l, h, orig);
|
||||||
|
split_args[real_args++] = tcgv_i32_temp(h);
|
||||||
|
split_args[real_args++] = tcgv_i32_temp(l);
|
||||||
|
} else {
|
||||||
|
split_args[real_args++] = args[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nargs = real_args;
|
||||||
|
args = split_args;
|
||||||
|
sizemask = 0;
|
||||||
|
}
|
||||||
|
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
|
||||||
|
for (i = 0; i < nargs; ++i) {
|
||||||
|
int is_64bit = sizemask & (1 << (i+1)*2);
|
||||||
|
int is_signed = sizemask & (2 << (i+1)*2);
|
||||||
|
if (!is_64bit) {
|
||||||
|
TCGv_i64 temp = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 orig = temp_tcgv_i64(args[i]);
|
||||||
|
if (is_signed) {
|
||||||
|
tcg_gen_ext32s_i64(temp, orig);
|
||||||
|
} else {
|
||||||
|
tcg_gen_ext32u_i64(temp, orig);
|
||||||
|
}
|
||||||
|
args[i] = tcgv_i64_temp(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* TCG_TARGET_EXTEND_ARGS */
|
||||||
|
|
||||||
|
op = tcg_emit_op(INDEX_op_call);
|
||||||
|
|
||||||
|
pi = 0;
|
||||||
|
nb_rets = 0;
|
||||||
|
TCGOP_CALLO(op) = nb_rets;
|
||||||
|
|
||||||
|
real_args = 0;
|
||||||
|
for (i = 0; i < nargs; i++) {
|
||||||
|
int is_64bit = sizemask & (1 << (i+1)*2);
|
||||||
|
if (TCG_TARGET_REG_BITS < 64 && is_64bit) {
|
||||||
|
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
|
||||||
|
/* some targets want aligned 64 bit args */
|
||||||
|
if (real_args & 1) {
|
||||||
|
op->args[pi++] = TCG_CALL_DUMMY_ARG;
|
||||||
|
real_args++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* If stack grows up, then we will be placing successive
|
||||||
|
arguments at lower addresses, which means we need to
|
||||||
|
reverse the order compared to how we would normally
|
||||||
|
treat either big or little-endian. For those arguments
|
||||||
|
that will wind up in registers, this still works for
|
||||||
|
HPPA (the only current STACK_GROWSUP target) since the
|
||||||
|
argument registers are *also* allocated in decreasing
|
||||||
|
order. If another such target is added, this logic may
|
||||||
|
have to get more complicated to differentiate between
|
||||||
|
stack arguments and register arguments. */
|
||||||
|
#if defined(HOST_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
|
||||||
|
op->args[pi++] = temp_arg(args[i] + 1);
|
||||||
|
op->args[pi++] = temp_arg(args[i]);
|
||||||
|
#else
|
||||||
|
op->args[pi++] = temp_arg(args[i]);
|
||||||
|
op->args[pi++] = temp_arg(args[i] + 1);
|
||||||
|
#endif
|
||||||
|
real_args += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
op->args[pi++] = temp_arg(args[i]);
|
||||||
|
real_args++;
|
||||||
|
}
|
||||||
|
op->args[pi++] = (uintptr_t)func;
|
||||||
|
op->args[pi++] = flags;
|
||||||
|
TCGOP_CALLI(op) = real_args;
|
||||||
|
|
||||||
|
/* Make sure the fields didn't overflow. */
|
||||||
|
tcg_debug_assert(TCGOP_CALLI(op) == real_args);
|
||||||
|
tcg_debug_assert(pi <= ARRAY_SIZE(op->args));
|
||||||
|
|
||||||
|
#if defined(__sparc__) && !defined(__arch64__) \
|
||||||
|
&& !defined(CONFIG_TCG_INTERPRETER)
|
||||||
|
/* Free all of the parts we allocated above. */
|
||||||
|
for (i = real_args = 0; i < orig_nargs; ++i) {
|
||||||
|
int is_64bit = orig_sizemask & (1 << (i+1)*2);
|
||||||
|
if (is_64bit) {
|
||||||
|
tcg_temp_free_internal(args[real_args++]);
|
||||||
|
tcg_temp_free_internal(args[real_args++]);
|
||||||
|
} else {
|
||||||
|
real_args++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (orig_sizemask & 1) {
|
||||||
|
/* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
|
||||||
|
Note that describing these as TCGv_i64 eliminates an unnecessary
|
||||||
|
zero-extension that tcg_gen_concat_i32_i64 would create. */
|
||||||
|
tcg_gen_concat32_i64(temp_tcgv_i64(NULL), retl, reth);
|
||||||
|
tcg_temp_free_i64(retl);
|
||||||
|
tcg_temp_free_i64(reth);
|
||||||
|
}
|
||||||
|
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
|
||||||
|
for (i = 0; i < nargs; ++i) {
|
||||||
|
int is_64bit = sizemask & (1 << (i+1)*2);
|
||||||
|
if (!is_64bit) {
|
||||||
|
tcg_temp_free_internal(args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* TCG_TARGET_EXTEND_ARGS */
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
TCG instrumentation and block chaining support by Andrea Biondo
|
TCG instrumentation and block chaining support by Andrea Biondo
|
||||||
<andrea.biondo965@gmail.com>
|
<andrea.biondo965@gmail.com>
|
||||||
QEMU 3.1.0 port and thread-safety by Andrea Fioraldi
|
|
||||||
|
QEMU 3.1.0 port, TCG thread-safety and CompareCoverage by Andrea Fioraldi
|
||||||
<andreafioraldi@gmail.com>
|
<andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
|
||||||
@ -41,12 +42,12 @@ extern abi_ulong afl_start_code, afl_end_code;
|
|||||||
|
|
||||||
void tcg_gen_afl_maybe_log_call(target_ulong cur_loc);
|
void tcg_gen_afl_maybe_log_call(target_ulong cur_loc);
|
||||||
|
|
||||||
void afl_maybe_log(void* cur_loc) {
|
void afl_maybe_log(target_ulong cur_loc) {
|
||||||
|
|
||||||
static __thread abi_ulong prev_loc;
|
static __thread abi_ulong prev_loc;
|
||||||
|
|
||||||
afl_area_ptr[(abi_ulong)cur_loc ^ prev_loc]++;
|
afl_area_ptr[cur_loc ^ prev_loc]++;
|
||||||
prev_loc = (abi_ulong)cur_loc >> 1;
|
prev_loc = cur_loc >> 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ static void afl_gen_trace(target_ulong cur_loc) {
|
|||||||
if (cur_loc > afl_end_code || cur_loc < afl_start_code /*|| !afl_area_ptr*/) // not needed because of static dummy buffer
|
if (cur_loc > afl_end_code || cur_loc < afl_start_code /*|| !afl_area_ptr*/) // not needed because of static dummy buffer
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Looks like QEMU always maps to fixed locations, so ASAN is not a
|
/* Looks like QEMU always maps to fixed locations, so ASLR is not a
|
||||||
concern. Phew. But instruction addresses may be aligned. Let's mangle
|
concern. Phew. But instruction addresses may be aligned. Let's mangle
|
||||||
the value to get something quasi-uniform. */
|
the value to get something quasi-uniform. */
|
||||||
|
|
||||||
|
33
qemu_mode/patches/i386-translate.diff
Normal file
33
qemu_mode/patches/i386-translate.diff
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
diff --git a/target/i386/translate.c b/target/i386/translate.c
|
||||||
|
index 0dd5fbe4..b95d341e 100644
|
||||||
|
--- a/target/i386/translate.c
|
||||||
|
+++ b/target/i386/translate.c
|
||||||
|
@@ -32,6 +32,8 @@
|
||||||
|
#include "trace-tcg.h"
|
||||||
|
#include "exec/log.h"
|
||||||
|
|
||||||
|
+#include "../patches/afl-qemu-cpu-translate-inl.h"
|
||||||
|
+
|
||||||
|
#define PREFIX_REPZ 0x01
|
||||||
|
#define PREFIX_REPNZ 0x02
|
||||||
|
#define PREFIX_LOCK 0x04
|
||||||
|
@@ -1343,9 +1345,11 @@ static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
|
||||||
|
tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0,
|
||||||
|
s1->mem_index, ot | MO_LE);
|
||||||
|
tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1);
|
||||||
|
+ afl_gen_compcov(s1->pc, s1->cc_srcT, s1->T1, ot);
|
||||||
|
} else {
|
||||||
|
tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
|
||||||
|
tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
|
||||||
|
+ afl_gen_compcov(s1->pc, s1->T0, s1->T1, ot);
|
||||||
|
gen_op_st_rm_T0_A0(s1, ot, d);
|
||||||
|
}
|
||||||
|
gen_op_update2_cc(s1);
|
||||||
|
@@ -1389,6 +1393,7 @@ static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
|
||||||
|
tcg_gen_mov_tl(cpu_cc_src, s1->T1);
|
||||||
|
tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
|
||||||
|
tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1);
|
||||||
|
+ afl_gen_compcov(s1->pc, s1->T0, s1->T1, ot);
|
||||||
|
set_cc_op(s1, CC_OP_SUBB + ot);
|
||||||
|
break;
|
||||||
|
}
|
Reference in New Issue
Block a user