mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/xtensa/tags/20180109-xtensa' into staging
target/xtensa updates: - add libisa to the xtensa target; - change xtensa instruction translator to use it; - switch existing xtensa cores to use it; - add support for a number of instructions: salt/saltu, const16, GPIO32 group, debug mode and MMU-related; - add disassembler for Xtensa. # gpg: Signature made Tue 09 Jan 2018 18:11:02 GMT # gpg: using RSA key 0x51F9CC91F83FA044 # gpg: Good signature from "Max Filippov <filippov@cadence.com>" # gpg: aka "Max Filippov <max.filippov@cogentembedded.com>" # gpg: aka "Max Filippov <jcmvbkbc@gmail.com>" # Primary key fingerprint: 2B67 854B 98E5 327D CDEB 17D8 51F9 CC91 F83F A044 * remotes/xtensa/tags/20180109-xtensa: target/xtensa: implement disassembler target/xtensa: implement const16 target/xtensa: implement GPIO32 target/xtensa: implement salt/saltu target/xtensa: add internal/noop SRs and opcodes target/xtensa: drop DisasContext::litbase target/xtensa: tests: fix memctl SR test target/xtensa: use libisa for instruction decoding target/xtensa: switch fsf to libisa target/xtensa: switch dc233c to libisa target/xtensa: switch dc232b to libisa target/xtensa: update import_core.sh script for libisa target/xtensa: extract FPU2000 opcode translators target/xtensa: extract core opcode translators target/xtensa: import libisa source target/xtensa: pass actual frame size to the entry helper Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -259,6 +259,7 @@ S: Maintained
|
||||
F: target/xtensa/
|
||||
F: hw/xtensa/
|
||||
F: tests/tcg/xtensa/
|
||||
F: disas/xtensa.c
|
||||
|
||||
TriCore
|
||||
M: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
|
||||
|
||||
@@ -21,6 +21,7 @@ common-obj-$(CONFIG_S390_DIS) += s390.o
|
||||
common-obj-$(CONFIG_SH4_DIS) += sh4.o
|
||||
common-obj-$(CONFIG_SPARC_DIS) += sparc.o
|
||||
common-obj-$(CONFIG_LM32_DIS) += lm32.o
|
||||
common-obj-$(CONFIG_XTENSA_DIS) += xtensa.o
|
||||
|
||||
# TODO: As long as the TCG interpreter and its generated code depend
|
||||
# on the QEMU target, we cannot compile the disassembler here.
|
||||
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Max Filippov, Open Source and Linux Lab.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Open Source and Linux Lab nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "disas/bfd.h"
|
||||
#include "hw/xtensa/xtensa-isa.h"
|
||||
|
||||
int print_insn_xtensa(bfd_vma memaddr, struct disassemble_info *info)
|
||||
{
|
||||
xtensa_isa isa = info->private_data;
|
||||
xtensa_insnbuf insnbuf = xtensa_insnbuf_alloc(isa);
|
||||
xtensa_insnbuf slotbuf = xtensa_insnbuf_alloc(isa);
|
||||
bfd_byte *buffer = g_malloc(1);
|
||||
int status = info->read_memory_func(memaddr, buffer, 1, info);
|
||||
xtensa_format fmt;
|
||||
unsigned slot, slots;
|
||||
unsigned len;
|
||||
|
||||
if (status) {
|
||||
info->memory_error_func(status, memaddr, info);
|
||||
len = -1;
|
||||
goto out;
|
||||
}
|
||||
len = xtensa_isa_length_from_chars(isa, buffer);
|
||||
if (len == XTENSA_UNDEFINED) {
|
||||
info->fprintf_func(info->stream, ".byte 0x%02x", buffer[0]);
|
||||
len = 1;
|
||||
goto out;
|
||||
}
|
||||
buffer = g_realloc(buffer, len);
|
||||
status = info->read_memory_func(memaddr + 1, buffer + 1, len - 1, info);
|
||||
if (status) {
|
||||
info->fprintf_func(info->stream, ".byte 0x%02x", buffer[0]);
|
||||
info->memory_error_func(status, memaddr + 1, info);
|
||||
len = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
xtensa_insnbuf_from_chars(isa, insnbuf, buffer, len);
|
||||
fmt = xtensa_format_decode(isa, insnbuf);
|
||||
if (fmt == XTENSA_UNDEFINED) {
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
info->fprintf_func(info->stream, "%s 0x%02x",
|
||||
i ? ", " : ".byte ", buffer[i]);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
slots = xtensa_format_num_slots(isa, fmt);
|
||||
|
||||
if (slots > 1) {
|
||||
info->fprintf_func(info->stream, "{ ");
|
||||
}
|
||||
|
||||
for (slot = 0; slot < slots; ++slot) {
|
||||
xtensa_opcode opc;
|
||||
unsigned opnd, vopnd, opnds;
|
||||
|
||||
if (slot) {
|
||||
info->fprintf_func(info->stream, "; ");
|
||||
}
|
||||
xtensa_format_get_slot(isa, fmt, slot, insnbuf, slotbuf);
|
||||
opc = xtensa_opcode_decode(isa, fmt, slot, slotbuf);
|
||||
if (opc == XTENSA_UNDEFINED) {
|
||||
info->fprintf_func(info->stream, "???");
|
||||
continue;
|
||||
}
|
||||
opnds = xtensa_opcode_num_operands(isa, opc);
|
||||
|
||||
info->fprintf_func(info->stream, "%s", xtensa_opcode_name(isa, opc));
|
||||
|
||||
for (opnd = vopnd = 0; opnd < opnds; ++opnd) {
|
||||
if (xtensa_operand_is_visible(isa, opc, opnd)) {
|
||||
uint32_t v = 0xbadc0de;
|
||||
int rc;
|
||||
|
||||
info->fprintf_func(info->stream, vopnd ? ", " : "\t");
|
||||
xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
|
||||
slotbuf, &v);
|
||||
rc = xtensa_operand_decode(isa, opc, opnd, &v);
|
||||
if (rc == XTENSA_UNDEFINED) {
|
||||
info->fprintf_func(info->stream, "???");
|
||||
} else if (xtensa_operand_is_register(isa, opc, opnd)) {
|
||||
xtensa_regfile rf = xtensa_operand_regfile(isa, opc, opnd);
|
||||
|
||||
info->fprintf_func(info->stream, "%s%d",
|
||||
xtensa_regfile_shortname(isa, rf), v);
|
||||
} else if (xtensa_operand_is_PCrelative(isa, opc, opnd)) {
|
||||
xtensa_operand_undo_reloc(isa, opc, opnd, &v, memaddr);
|
||||
info->fprintf_func(info->stream, "0x%x", v);
|
||||
} else {
|
||||
info->fprintf_func(info->stream, "%d", v);
|
||||
}
|
||||
++vopnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (slots > 1) {
|
||||
info->fprintf_func(info->stream, " }");
|
||||
}
|
||||
|
||||
out:
|
||||
g_free(buffer);
|
||||
xtensa_insnbuf_free(isa, insnbuf);
|
||||
xtensa_insnbuf_free(isa, slotbuf);
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -428,6 +428,7 @@ int print_insn_ia64 (bfd_vma, disassemble_info*);
|
||||
int print_insn_lm32 (bfd_vma, disassemble_info*);
|
||||
int print_insn_big_nios2 (bfd_vma, disassemble_info*);
|
||||
int print_insn_little_nios2 (bfd_vma, disassemble_info*);
|
||||
int print_insn_xtensa (bfd_vma, disassemble_info*);
|
||||
|
||||
#if 0
|
||||
/* Fetch the disassembler for a given BFD, if that support is available. */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,5 +3,6 @@ obj-y += core-dc232b.o
|
||||
obj-y += core-dc233c.o
|
||||
obj-y += core-fsf.o
|
||||
obj-$(CONFIG_SOFTMMU) += monitor.o
|
||||
obj-y += xtensa-isa.o
|
||||
obj-y += translate.o op_helper.o helper.o cpu.o
|
||||
obj-y += gdbstub.o
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
#include "core-dc232b/core-isa.h"
|
||||
#include "overlay_tool.h"
|
||||
|
||||
#define xtensa_modules xtensa_modules_dc232b
|
||||
#include "core-dc232b/xtensa-modules.c"
|
||||
|
||||
static XtensaConfig dc232b __attribute__((unused)) = {
|
||||
.name = "dc232b",
|
||||
.gdb_regmap = {
|
||||
@@ -43,6 +46,7 @@ static XtensaConfig dc232b __attribute__((unused)) = {
|
||||
#include "core-dc232b/gdb-config.c"
|
||||
}
|
||||
},
|
||||
.isa_internal = &xtensa_modules,
|
||||
.clock_freq_khz = 10000,
|
||||
DEFAULT_SECTIONS
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,9 @@
|
||||
#include "core-dc233c/core-isa.h"
|
||||
#include "overlay_tool.h"
|
||||
|
||||
#define xtensa_modules xtensa_modules_dc233c
|
||||
#include "core-dc233c/xtensa-modules.c"
|
||||
|
||||
static XtensaConfig dc233c __attribute__((unused)) = {
|
||||
.name = "dc233c",
|
||||
.gdb_regmap = {
|
||||
@@ -44,6 +47,7 @@ static XtensaConfig dc233c __attribute__((unused)) = {
|
||||
#include "core-dc233c/gdb-config.c"
|
||||
}
|
||||
},
|
||||
.isa_internal = &xtensa_modules,
|
||||
.clock_freq_khz = 10000,
|
||||
DEFAULT_SECTIONS
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,11 +29,15 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/host-utils.h"
|
||||
|
||||
#include "core-fsf/core-isa.h"
|
||||
#include "overlay_tool.h"
|
||||
|
||||
#define xtensa_modules xtensa_modules_fsf
|
||||
#include "core-fsf/xtensa-modules.c"
|
||||
|
||||
static XtensaConfig fsf __attribute__((unused)) = {
|
||||
.name = "fsf",
|
||||
.gdb_regmap = {
|
||||
@@ -42,6 +46,7 @@ static XtensaConfig fsf __attribute__((unused)) = {
|
||||
XTREG_END
|
||||
},
|
||||
},
|
||||
.isa_internal = &xtensa_modules,
|
||||
.clock_freq_khz = 10000,
|
||||
DEFAULT_SECTIONS
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -93,6 +93,14 @@ static ObjectClass *xtensa_cpu_class_by_name(const char *cpu_model)
|
||||
return oc;
|
||||
}
|
||||
|
||||
static void xtensa_cpu_disas_set_info(CPUState *cs, disassemble_info *info)
|
||||
{
|
||||
XtensaCPU *cpu = XTENSA_CPU(cs);
|
||||
|
||||
info->private_data = cpu->env.config->isa;
|
||||
info->print_insn = print_insn_xtensa;
|
||||
}
|
||||
|
||||
static void xtensa_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
@@ -164,6 +172,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
|
||||
cc->do_unassigned_access = xtensa_cpu_do_unassigned_access;
|
||||
#endif
|
||||
cc->debug_excp_handler = xtensa_breakpoint_handler;
|
||||
cc->disas_set_info = xtensa_cpu_disas_set_info;
|
||||
cc->tcg_initialize = xtensa_translate_init;
|
||||
dc->vmsd = &vmstate_xtensa_cpu;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "cpu-qom.h"
|
||||
#include "exec/cpu-defs.h"
|
||||
#include "fpu/softfloat.h"
|
||||
#include "xtensa-isa.h"
|
||||
|
||||
#define NB_MMU_MODES 4
|
||||
|
||||
@@ -107,6 +108,7 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
EXPSTATE = 230,
|
||||
THREADPTR = 231,
|
||||
FCR = 232,
|
||||
FSR = 233,
|
||||
@@ -126,6 +128,7 @@ enum {
|
||||
WINDOW_BASE = 72,
|
||||
WINDOW_START = 73,
|
||||
PTEVADDR = 83,
|
||||
MMID = 89,
|
||||
RASID = 90,
|
||||
ITLBCFG = 91,
|
||||
DTLBCFG = 92,
|
||||
@@ -133,6 +136,7 @@ enum {
|
||||
MEMCTL = 97,
|
||||
CACHEATTR = 98,
|
||||
ATOMCTL = 99,
|
||||
DDR = 104,
|
||||
IBREAKA = 128,
|
||||
DBREAKA = 144,
|
||||
DBREAKC = 160,
|
||||
@@ -205,6 +209,8 @@ enum {
|
||||
#define MEMCTL_DSNP 0x2
|
||||
#define MEMCTL_IL0EN 0x1
|
||||
|
||||
#define MAX_INSN_LENGTH 64
|
||||
#define MAX_OPCODE_ARGS 16
|
||||
#define MAX_NAREG 64
|
||||
#define MAX_NINTERRUPT 32
|
||||
#define MAX_NLEVEL 6
|
||||
@@ -330,6 +336,24 @@ typedef struct XtensaMemory {
|
||||
} location[MAX_NMEMORY];
|
||||
} XtensaMemory;
|
||||
|
||||
typedef struct DisasContext DisasContext;
|
||||
typedef void (*XtensaOpcodeOp)(DisasContext *dc, const uint32_t arg[],
|
||||
const uint32_t par[]);
|
||||
|
||||
typedef struct XtensaOpcodeOps {
|
||||
const char *name;
|
||||
XtensaOpcodeOp translate;
|
||||
const uint32_t *par;
|
||||
} XtensaOpcodeOps;
|
||||
|
||||
typedef struct XtensaOpcodeTranslators {
|
||||
unsigned num_opcodes;
|
||||
const XtensaOpcodeOps *opcode;
|
||||
} XtensaOpcodeTranslators;
|
||||
|
||||
extern const XtensaOpcodeTranslators xtensa_core_opcodes;
|
||||
extern const XtensaOpcodeTranslators xtensa_fpu2000_opcodes;
|
||||
|
||||
struct XtensaConfig {
|
||||
const char *name;
|
||||
uint64_t options;
|
||||
@@ -370,6 +394,11 @@ struct XtensaConfig {
|
||||
|
||||
uint32_t configid[2];
|
||||
|
||||
void *isa_internal;
|
||||
xtensa_isa isa;
|
||||
XtensaOpcodeOps **opcode_ops;
|
||||
const XtensaOpcodeTranslators **opcode_translators;
|
||||
|
||||
uint32_t clock_freq_khz;
|
||||
|
||||
xtensa_tlb itlb;
|
||||
@@ -522,6 +551,8 @@ static inline void xtensa_select_static_vectors(CPUXtensaState *env,
|
||||
env->static_vectors = n;
|
||||
}
|
||||
void xtensa_runstall(CPUXtensaState *env, bool runstall);
|
||||
XtensaOpcodeOps *xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t,
|
||||
const char *opcode);
|
||||
|
||||
#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
|
||||
#define XTENSA_OPTION_ALL (~(uint64_t)0)
|
||||
|
||||
@@ -52,10 +52,47 @@ static void xtensa_core_class_init(ObjectClass *oc, void *data)
|
||||
cc->gdb_num_core_regs = config->gdb_regmap.num_regs;
|
||||
}
|
||||
|
||||
static void init_libisa(XtensaConfig *config)
|
||||
{
|
||||
unsigned i, j;
|
||||
unsigned opcodes;
|
||||
|
||||
config->isa = xtensa_isa_init(config->isa_internal, NULL, NULL);
|
||||
assert(xtensa_isa_maxlength(config->isa) <= MAX_INSN_LENGTH);
|
||||
opcodes = xtensa_isa_num_opcodes(config->isa);
|
||||
config->opcode_ops = g_new(XtensaOpcodeOps *, opcodes);
|
||||
|
||||
for (i = 0; i < opcodes; ++i) {
|
||||
const char *opc_name = xtensa_opcode_name(config->isa, i);
|
||||
XtensaOpcodeOps *ops = NULL;
|
||||
|
||||
assert(xtensa_opcode_num_operands(config->isa, i) <= MAX_OPCODE_ARGS);
|
||||
if (!config->opcode_translators) {
|
||||
ops = xtensa_find_opcode_ops(&xtensa_core_opcodes, opc_name);
|
||||
} else {
|
||||
for (j = 0; !ops && config->opcode_translators[j]; ++j) {
|
||||
ops = xtensa_find_opcode_ops(config->opcode_translators[j],
|
||||
opc_name);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (ops == NULL) {
|
||||
fprintf(stderr,
|
||||
"opcode translator not found for %s's opcode '%s'\n",
|
||||
config->name, opc_name);
|
||||
}
|
||||
#endif
|
||||
config->opcode_ops[i] = ops;
|
||||
}
|
||||
}
|
||||
|
||||
void xtensa_finalize_config(XtensaConfig *config)
|
||||
{
|
||||
unsigned i, n = 0;
|
||||
|
||||
if (config->isa_internal) {
|
||||
init_libisa(config);
|
||||
}
|
||||
if (config->gdb_regmap.num_regs) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,17 @@ tar -xf "$OVERLAY" -C "$TARGET" --strip-components=1 \
|
||||
--xform='s/core/core-isa/' config/core.h
|
||||
tar -xf "$OVERLAY" -O gdb/xtensa-config.c | \
|
||||
sed -n '1,/*\//p;/XTREG/,/XTREG_END/p' > "$TARGET"/gdb-config.c
|
||||
#
|
||||
# Fix up known issues in the xtensa-modules.c
|
||||
#
|
||||
tar -xf "$OVERLAY" -O binutils/xtensa-modules.c | \
|
||||
sed -e 's/\(xtensa_opcode_encode_fn.*\[\] =\)/static \1/' \
|
||||
-e '/^int num_bypass_groups()/,/}/d' \
|
||||
-e '/^int num_bypass_group_chunks()/,/}/d' \
|
||||
-e '/^uint32 \*bypass_entry(int i)/,/}/d' \
|
||||
-e '/^#include "ansidecl.h"/d' \
|
||||
-e '/^Slot_[a-zA-Z0-9_]\+_decode (const xtensa_insnbuf insn)/,/^}/s/^ return 0;$/ return XTENSA_UNDEFINED;/' \
|
||||
> "$TARGET"/xtensa-modules.c
|
||||
|
||||
cat <<EOF > "${TARGET}.c"
|
||||
#include "qemu/osdep.h"
|
||||
@@ -35,6 +46,9 @@ cat <<EOF > "${TARGET}.c"
|
||||
#include "core-$NAME/core-isa.h"
|
||||
#include "overlay_tool.h"
|
||||
|
||||
#define xtensa_modules xtensa_modules_$NAME
|
||||
#include "core-$NAME/xtensa-modules.c"
|
||||
|
||||
static XtensaConfig $NAME __attribute__((unused)) = {
|
||||
.name = "$NAME",
|
||||
.gdb_regmap = {
|
||||
@@ -42,6 +56,7 @@ static XtensaConfig $NAME __attribute__((unused)) = {
|
||||
#include "core-$NAME/gdb-config.c"
|
||||
}
|
||||
},
|
||||
.isa_internal = &xtensa_modules,
|
||||
.clock_freq_khz = $FREQ,
|
||||
DEFAULT_SECTIONS
|
||||
};
|
||||
|
||||
@@ -249,7 +249,7 @@ void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
|
||||
if (windowstart & ((1 << callinc) - 1)) {
|
||||
HELPER(window_check)(env, pc, callinc);
|
||||
}
|
||||
env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - (imm << 3);
|
||||
env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm;
|
||||
rotate_window(env, callinc);
|
||||
env->sregs[WINDOW_START] |=
|
||||
windowstart_bit(env->sregs[WINDOW_BASE], env);
|
||||
|
||||
+3702
-2166
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,231 @@
|
||||
/* Internal definitions for the Xtensa ISA library.
|
||||
*
|
||||
* Copyright (c) 2004-2011 Tensilica Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef XTENSA_ISA_INTERNAL_H
|
||||
#define XTENSA_ISA_INTERNAL_H
|
||||
|
||||
#ifndef uint32
|
||||
#define uint32 uint32_t
|
||||
#endif
|
||||
|
||||
/* Flags. */
|
||||
|
||||
#define XTENSA_OPERAND_IS_REGISTER 0x00000001
|
||||
#define XTENSA_OPERAND_IS_PCRELATIVE 0x00000002
|
||||
#define XTENSA_OPERAND_IS_INVISIBLE 0x00000004
|
||||
#define XTENSA_OPERAND_IS_UNKNOWN 0x00000008
|
||||
|
||||
#define XTENSA_OPCODE_IS_BRANCH 0x00000001
|
||||
#define XTENSA_OPCODE_IS_JUMP 0x00000002
|
||||
#define XTENSA_OPCODE_IS_LOOP 0x00000004
|
||||
#define XTENSA_OPCODE_IS_CALL 0x00000008
|
||||
|
||||
#define XTENSA_STATE_IS_EXPORTED 0x00000001
|
||||
#define XTENSA_STATE_IS_SHARED_OR 0x00000002
|
||||
|
||||
#define XTENSA_INTERFACE_HAS_SIDE_EFFECT 0x00000001
|
||||
|
||||
/* Function pointer typedefs */
|
||||
typedef void (*xtensa_format_encode_fn)(xtensa_insnbuf);
|
||||
typedef void (*xtensa_get_slot_fn)(const xtensa_insnbuf, xtensa_insnbuf);
|
||||
typedef void (*xtensa_set_slot_fn)(xtensa_insnbuf, const xtensa_insnbuf);
|
||||
typedef int (*xtensa_opcode_decode_fn)(const xtensa_insnbuf);
|
||||
typedef uint32_t (*xtensa_get_field_fn)(const xtensa_insnbuf);
|
||||
typedef void (*xtensa_set_field_fn)(xtensa_insnbuf, uint32_t);
|
||||
typedef int (*xtensa_immed_decode_fn)(uint32_t *);
|
||||
typedef int (*xtensa_immed_encode_fn)(uint32_t *);
|
||||
typedef int (*xtensa_do_reloc_fn)(uint32_t *, uint32_t);
|
||||
typedef int (*xtensa_undo_reloc_fn)(uint32_t *, uint32_t);
|
||||
typedef void (*xtensa_opcode_encode_fn)(xtensa_insnbuf);
|
||||
typedef int (*xtensa_format_decode_fn)(const xtensa_insnbuf);
|
||||
typedef int (*xtensa_length_decode_fn)(const unsigned char *);
|
||||
|
||||
typedef struct xtensa_format_internal_struct {
|
||||
const char *name; /* Instruction format name. */
|
||||
int length; /* Instruction length in bytes. */
|
||||
xtensa_format_encode_fn encode_fn;
|
||||
int num_slots;
|
||||
int *slot_id; /* Array[num_slots] of slot IDs. */
|
||||
} xtensa_format_internal;
|
||||
|
||||
typedef struct xtensa_slot_internal_struct {
|
||||
const char *name; /* Not necessarily unique. */
|
||||
const char *format;
|
||||
int position;
|
||||
xtensa_get_slot_fn get_fn;
|
||||
xtensa_set_slot_fn set_fn;
|
||||
xtensa_get_field_fn *get_field_fns; /* Array[field_id]. */
|
||||
xtensa_set_field_fn *set_field_fns; /* Array[field_id]. */
|
||||
xtensa_opcode_decode_fn opcode_decode_fn;
|
||||
const char *nop_name;
|
||||
} xtensa_slot_internal;
|
||||
|
||||
typedef struct xtensa_operand_internal_struct {
|
||||
const char *name;
|
||||
int field_id;
|
||||
xtensa_regfile regfile; /* Register file. */
|
||||
int num_regs; /* Usually 1; 2 for reg pairs, etc. */
|
||||
uint32_t flags; /* See XTENSA_OPERAND_* flags. */
|
||||
xtensa_immed_encode_fn encode; /* Encode the operand value. */
|
||||
xtensa_immed_decode_fn decode; /* Decode the value from the field. */
|
||||
xtensa_do_reloc_fn do_reloc; /* Perform a PC-relative reloc. */
|
||||
xtensa_undo_reloc_fn undo_reloc; /* Undo a PC-relative relocation. */
|
||||
} xtensa_operand_internal;
|
||||
|
||||
typedef struct xtensa_arg_internal_struct {
|
||||
union {
|
||||
int operand_id; /* For normal operands. */
|
||||
xtensa_state state; /* For stateOperands. */
|
||||
} u;
|
||||
char inout; /* Direction: 'i', 'o', or 'm'. */
|
||||
} xtensa_arg_internal;
|
||||
|
||||
typedef struct xtensa_iclass_internal_struct {
|
||||
int num_operands; /* Size of "operands" array. */
|
||||
xtensa_arg_internal *operands; /* Array[num_operands]. */
|
||||
|
||||
int num_stateOperands; /* Size of "stateOperands" array. */
|
||||
xtensa_arg_internal *stateOperands; /* Array[num_stateOperands]. */
|
||||
|
||||
int num_interfaceOperands; /* Size of "interfaceOperands". */
|
||||
xtensa_interface *interfaceOperands; /* Array[num_interfaceOperands]. */
|
||||
} xtensa_iclass_internal;
|
||||
|
||||
typedef struct xtensa_opcode_internal_struct {
|
||||
const char *name; /* Opcode mnemonic. */
|
||||
int iclass_id; /* Iclass for this opcode. */
|
||||
uint32_t flags; /* See XTENSA_OPCODE_* flags. */
|
||||
xtensa_opcode_encode_fn *encode_fns; /* Array[slot_id]. */
|
||||
int num_funcUnit_uses; /* Number of funcUnit_use entries. */
|
||||
xtensa_funcUnit_use *funcUnit_uses; /* Array[num_funcUnit_uses]. */
|
||||
} xtensa_opcode_internal;
|
||||
|
||||
typedef struct xtensa_regfile_internal_struct {
|
||||
const char *name; /* Full name of the regfile. */
|
||||
const char *shortname; /* Abbreviated name. */
|
||||
xtensa_regfile parent; /* View parent (or identity). */
|
||||
int num_bits; /* Width of the registers. */
|
||||
int num_entries; /* Number of registers. */
|
||||
} xtensa_regfile_internal;
|
||||
|
||||
typedef struct xtensa_interface_internal_struct {
|
||||
const char *name; /* Interface name. */
|
||||
int num_bits; /* Width of the interface. */
|
||||
uint32_t flags; /* See XTENSA_INTERFACE_* flags. */
|
||||
int class_id; /* Class of related interfaces. */
|
||||
char inout; /* "i" or "o". */
|
||||
} xtensa_interface_internal;
|
||||
|
||||
typedef struct xtensa_funcUnit_internal_struct {
|
||||
const char *name; /* Functional unit name. */
|
||||
int num_copies; /* Number of instances. */
|
||||
} xtensa_funcUnit_internal;
|
||||
|
||||
typedef struct xtensa_state_internal_struct {
|
||||
const char *name; /* State name. */
|
||||
int num_bits; /* Number of state bits. */
|
||||
uint32_t flags; /* See XTENSA_STATE_* flags. */
|
||||
} xtensa_state_internal;
|
||||
|
||||
typedef struct xtensa_sysreg_internal_struct {
|
||||
const char *name; /* Register name. */
|
||||
int number; /* Register number. */
|
||||
int is_user; /* Non-zero if a "user register". */
|
||||
} xtensa_sysreg_internal;
|
||||
|
||||
typedef struct xtensa_lookup_entry_struct {
|
||||
const char *key;
|
||||
union {
|
||||
xtensa_opcode opcode; /* Internal opcode number. */
|
||||
xtensa_sysreg sysreg; /* Internal sysreg number. */
|
||||
xtensa_state state; /* Internal state number. */
|
||||
xtensa_interface intf; /* Internal interface number. */
|
||||
xtensa_funcUnit fun; /* Internal funcUnit number. */
|
||||
} u;
|
||||
} xtensa_lookup_entry;
|
||||
|
||||
typedef struct xtensa_isa_internal_struct {
|
||||
int is_big_endian; /* Endianness. */
|
||||
int insn_size; /* Maximum length in bytes. */
|
||||
int insnbuf_size; /* Number of insnbuf_words. */
|
||||
|
||||
int num_formats;
|
||||
xtensa_format_internal *formats;
|
||||
xtensa_format_decode_fn format_decode_fn;
|
||||
xtensa_length_decode_fn length_decode_fn;
|
||||
|
||||
int num_slots;
|
||||
xtensa_slot_internal *slots;
|
||||
|
||||
int num_fields;
|
||||
|
||||
int num_operands;
|
||||
xtensa_operand_internal *operands;
|
||||
|
||||
int num_iclasses;
|
||||
xtensa_iclass_internal *iclasses;
|
||||
|
||||
int num_opcodes;
|
||||
xtensa_opcode_internal *opcodes;
|
||||
xtensa_lookup_entry *opname_lookup_table;
|
||||
|
||||
int num_regfiles;
|
||||
xtensa_regfile_internal *regfiles;
|
||||
|
||||
int num_states;
|
||||
xtensa_state_internal *states;
|
||||
xtensa_lookup_entry *state_lookup_table;
|
||||
|
||||
int num_sysregs;
|
||||
xtensa_sysreg_internal *sysregs;
|
||||
xtensa_lookup_entry *sysreg_lookup_table;
|
||||
|
||||
/*
|
||||
* The current Xtensa ISA only supports 256 of each kind of sysreg so
|
||||
* we can get away with implementing lookups with tables indexed by
|
||||
* the register numbers. If we ever allow larger sysreg numbers, this
|
||||
* may have to be reimplemented. The first entry in the following
|
||||
* arrays corresponds to "special" registers and the second to "user"
|
||||
* registers.
|
||||
*/
|
||||
int max_sysreg_num[2];
|
||||
xtensa_sysreg *sysreg_table[2];
|
||||
|
||||
int num_interfaces;
|
||||
xtensa_interface_internal *interfaces;
|
||||
xtensa_lookup_entry *interface_lookup_table;
|
||||
|
||||
int num_funcUnits;
|
||||
xtensa_funcUnit_internal *funcUnits;
|
||||
xtensa_lookup_entry *funcUnit_lookup_table;
|
||||
|
||||
int num_stages; /* Number of pipe stages. */
|
||||
} xtensa_isa_internal;
|
||||
|
||||
int xtensa_isa_name_compare(const void *, const void *);
|
||||
|
||||
extern xtensa_isa_status xtisa_errno;
|
||||
extern char xtisa_error_msg[];
|
||||
|
||||
#endif /* !XTENSA_ISA_INTERNAL_H */
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user