aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2019-02-13 17:36:30 -0800
committerMax Filippov <jcmvbkbc@gmail.com>2019-02-28 04:43:22 -0800
commit068e538a54552289a58689f21c99ed3696e59961 (patch)
tree0a8c9a81e678a2f7d026dc635755e0e0a560880b /target
parent89bec9e9117d454d2101f7848475b11677ca99ff (diff)
downloadqemu-068e538a54552289a58689f21c99ed3696e59961.zip
qemu-068e538a54552289a58689f21c99ed3696e59961.tar.gz
qemu-068e538a54552289a58689f21c99ed3696e59961.tar.bz2
target/xtensa: prioritize load/store in FLIX bundles
Load/store opcodes may raise MMU exceptions. Normally exceptions should be checked in priority order before any actual operations, but since MMU exceptions are tightly coupled with actual memory access, there's currently no way to do it. Approximate this behavior by executing all load, then all store, and then all other opcodes in the FLIX bundles. Use opcode dependency mechanism to express ordering. Mark load/store opcodes with XTENSA_OP_{LOAD,STORE} flags. Newer libisa has classifier functions that can tell whether opcode is a load or store, but this information is not available in the existing overlays. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'target')
-rw-r--r--target/xtensa/cpu.h4
-rw-r--r--target/xtensa/translate.c37
2 files changed, 36 insertions, 5 deletions
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index bf021f7..a01a94e 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -390,6 +390,10 @@ enum {
XTENSA_OP_NAME_ARRAY = 0x8000,
XTENSA_OP_CONTROL_FLOW = 0x10000,
+ XTENSA_OP_STORE = 0x20000,
+ XTENSA_OP_LOAD = 0x40000,
+ XTENSA_OP_LOAD_STORE =
+ XTENSA_OP_LOAD | XTENSA_OP_STORE,
};
typedef struct XtensaOpcodeOps {
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 5502b5c..338e6ca 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -986,6 +986,10 @@ static bool op_depends_on(const struct slot_prop *a,
if (a->op_flags & XTENSA_OP_CONTROL_FLOW) {
return true;
}
+ if ((a->op_flags & XTENSA_OP_LOAD_STORE) <
+ (b->op_flags & XTENSA_OP_LOAD_STORE)) {
+ return true;
+ }
while (i < a->n_out && j < b->n_in) {
if (a->out[i].resource < b->in[j].resource) {
++i;
@@ -1017,6 +1021,10 @@ static bool break_dependency(struct slot_prop *a,
if (a->op_flags & XTENSA_OP_CONTROL_FLOW) {
return false;
}
+ if ((a->op_flags & XTENSA_OP_LOAD_STORE) <
+ (b->op_flags & XTENSA_OP_LOAD_STORE)) {
+ return false;
+ }
while (i < a->n_out && j < b->n_in) {
if (a->out[i].resource < b->in[j].resource) {
++i;
@@ -1293,7 +1301,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
if (slots > 1) {
slot_prop[slot].n_in = 0;
slot_prop[slot].n_out = 0;
- slot_prop[slot].op_flags = 0;
+ slot_prop[slot].op_flags = ops->op_flags & XTENSA_OP_LOAD_STORE;
opnds = xtensa_opcode_num_operands(isa, opc);
@@ -3223,40 +3231,47 @@ static const XtensaOpcodeOps core_ops[] = {
.name = "l16si",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TESW, false, false},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l16ui",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUW, false, false},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l32ai",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, true, false},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l32e",
.translate = translate_l32e,
- .op_flags = XTENSA_OP_PRIVILEGED,
+ .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_LOAD,
}, {
.name = (const char * const[]) {
"l32i", "l32i.n", NULL,
},
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, false, false},
- .op_flags = XTENSA_OP_NAME_ARRAY,
+ .op_flags = XTENSA_OP_NAME_ARRAY | XTENSA_OP_LOAD,
}, {
.name = "l32r",
.translate = translate_l32r,
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l8ui",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_UB, false, false},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "lddec",
.translate = translate_mac16,
.par = (const uint32_t[]){MAC16_NONE, 0, -4},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "ldinc",
.translate = translate_mac16,
.par = (const uint32_t[]){MAC16_NONE, 0, 4},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "ldpte",
.op_flags = XTENSA_OP_ILL,
@@ -4214,28 +4229,32 @@ static const XtensaOpcodeOps core_ops[] = {
.name = "s16i",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUW, false, true},
+ .op_flags = XTENSA_OP_STORE,
}, {
.name = "s32c1i",
.translate = translate_s32c1i,
+ .op_flags = XTENSA_OP_LOAD | XTENSA_OP_STORE,
}, {
.name = "s32e",
.translate = translate_s32e,
- .op_flags = XTENSA_OP_PRIVILEGED,
+ .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_STORE,
}, {
.name = (const char * const[]) {
"s32i", "s32i.n", "s32nb", NULL,
},
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, false, true},
- .op_flags = XTENSA_OP_NAME_ARRAY,
+ .op_flags = XTENSA_OP_NAME_ARRAY | XTENSA_OP_STORE,
}, {
.name = "s32ri",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, true, true},
+ .op_flags = XTENSA_OP_STORE,
}, {
.name = "s8i",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_UB, false, true},
+ .op_flags = XTENSA_OP_STORE,
}, {
.name = "salt",
.translate = translate_salt,
@@ -5525,21 +5544,25 @@ static const XtensaOpcodeOps fpu2000_ops[] = {
.name = "lsi",
.translate = translate_ldsti,
.par = (const uint32_t[]){false, false},
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "lsiu",
.translate = translate_ldsti,
.par = (const uint32_t[]){false, true},
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "lsx",
.translate = translate_ldstx,
.par = (const uint32_t[]){false, false},
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "lsxu",
.translate = translate_ldstx,
.par = (const uint32_t[]){false, true},
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "madd.s",
@@ -5619,21 +5642,25 @@ static const XtensaOpcodeOps fpu2000_ops[] = {
.name = "ssi",
.translate = translate_ldsti,
.par = (const uint32_t[]){true, false},
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "ssiu",
.translate = translate_ldsti,
.par = (const uint32_t[]){true, true},
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "ssx",
.translate = translate_ldstx,
.par = (const uint32_t[]){true, false},
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "ssxu",
.translate = translate_ldstx,
.par = (const uint32_t[]){true, true},
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "sub.s",