# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import copy
import os
main = Environment()
# Use soft links instead of hard links when setting up a build directory.
main.SetOption('duplicate', 'soft-copy')
+class CallType(object):
+ def __init__(self, name):
+ self.name = name
+ self.impl_file = None
+ self.enabled = False
+ self.default = False
+
+ def impl(self, impl, default=False):
+ self.impl_file = impl
+ self.enabled = True
+ self.default = default
+
+call_types = {
+ # Magic instruction.
+ 'inst': CallType('inst'),
+ # Magic address.
+ 'addr': CallType('addr'),
+ # Semihosting extension.
+ 'semi': CallType('semi'),
+}
+
for root, dirs, files in os.walk(abspath(src_dir)):
# Each SConsopts file describes a variant of the m5 utility.
if 'SConsopts' in files:
env = main.Clone()
+ env['CALL_TYPE'] = copy.deepcopy(call_types)
+
# The user may override variant settings by setting environment
# variables of the form ${VARIANT}.${OPTION}. For instance, to set the
# CROSS_COMPILE prefix for variant foo to bar-, the user would set an
# Raw source files.
m5_mmap = 'm5_mmap.c'
-m5op = '${VARIANT}/m5op.S'
m5 = 'm5.c'
jni = 'jni_gem5Op.c'
lua = 'lua_gem5Op.c'
+all_call_types = list(env['CALL_TYPE'].values())
+call_types = list([ ct for ct in all_call_types if ct.enabled ])
+m5ops = list([ '${VARIANT}/%s' % ct.impl_file for ct in call_types ])
+
+default_call_type = list([ ct for ct in call_types if ct.default ])
+assert len(default_call_type) == 1, \
+ 'There should be exactly one default call type for %s, found %d' % \
+ (env['VARIANT'], len(default_call_type))
+default_call_type = default_call_type[0]
+
static_env = env.Clone()
static_env.Append(LINKFLAGS=[ '-no-pie', '-static' ])
+for ct in all_call_types:
+ static_env.Append(CFLAGS='-DENABLE_CT_%s=%d' %
+ (ct.name, 1 if ct.enabled else 0))
+ static_env.Append(CFLAGS='-DDEFAULT_CT_%s=%d' %
+ (ct.name, 1 if ct.default else 0))
+static_env.Append(CFLAGS='-DDEFAULT_CALL_TYPE=%s' % default_call_type.name)
+
#
# The m5 library for use in other C/C++ programs.
#
-libm5 = static_env.StaticLibrary('out/m5', [ m5op, m5_mmap ])
+libm5 = static_env.StaticLibrary('out/m5', [ m5_mmap ] + m5ops)
#
# The m5 stand alone command line utility.
#
-m5_bin = static_env.Program('out/m5', [ m5, m5_mmap, libm5 ])
+ct_support = list([ File('%s_call_type.c' % ct.name) for ct in call_types ])
+m5_bin = static_env.Program('out/m5', ct_support + [ m5, m5_mmap, libm5 ])
# The shared version of the m5 op call sights, used by mutliple targets below.
shared_env = env.Clone()
shared_env.Append(ASFLAGS='-DM5OP_PIC')
-m5op_shared = shared_env.SharedObject(m5op)
+m5op_shared = shared_env.SharedObject(m5ops)
if env['HAVE_JAVA']:
#
OUT=Dir('out'), CWD=Dir('.'))
# Set include paths to the C headers from the JDK which scons found for us.
java_env.Append(CPPPATH='${JAVAINCLUDES}')
- java_env.SharedLibrary('out/gem5OpJni', [ jni, m5op_shared ])
+ java_env.SharedLibrary('out/gem5OpJni', [ jni ] + m5op_shared)
if env['HAVE_LUA51']:
lua_env = shared_env.Clone()
# Extract the include paths needed for lua51 using pkg-config.
lua_env.ParseConfig('pkg-config --cflags lua51')
- lib = lua_env.SharedLibrary('out/gem5OpLua', [ lua, m5op_shared, m5_mmap ])
+ lib = lua_env.SharedLibrary('out/gem5OpLua',
+ [ lua, m5_mmap ] + m5op_shared)
env['VARIANT'] = 'aarch64'
get_variant_opt('CROSS_COMPILE', 'aarch64-linux-gnu-')
+
+env['CALL_TYPE']['inst'].impl('m5op.S', default=True)
+env['CALL_TYPE']['addr'].impl('m5op_addr.S')
#include <gem5/asm/generic/m5ops.h>
-#ifdef M5OP_ADDR
-.macro m5op_func, name, func
- .globl \name
- \name:
- // Load the value of m5_mem into x9...
-#if defined(M5OP_PIC)
- // using the global offset table.
- adrp x9, :got:m5_mem
- ldr x9, [ x9, #:got_lo12:m5_mem ]
- ldr x9, [ x9 ]
-#else
- // normally.
- adrp x9, m5_mem
- ldr x9, [ x9, #:lo12:m5_mem ]
-#endif
- movz x10, #(\func << 8)
- ldr x0, [ x9, x10 ]
- ret
-.endm
-#else
.macro m5op_func, name, func
.globl \name
\name:
.long 0xff000110 | (\func << 16)
ret
.endm
-#endif
.text
#define M5OP(name, func) m5op_func name, func;
--- /dev/null
+/*
+ * Copyright (c) 2010-2013, 2016-2017 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2003-2006 The Regents of The University of Michigan
+ * 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 copyright holders 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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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 <gem5/asm/generic/m5ops.h>
+
+.macro m5op_func, name, func
+ .globl \name
+ \name:
+ // Load the value of m5_mem into x9...
+#if defined(M5OP_PIC)
+ // using the global offset table.
+ adrp x9, :got:m5_mem
+ ldr x9, [ x9, #:got_lo12:m5_mem ]
+ ldr x9, [ x9 ]
+#else
+ // normally.
+ adrp x9, m5_mem
+ ldr x9, [ x9, #:lo12:m5_mem ]
+#endif
+ movz x10, #(\func << 8)
+ ldr x0, [ x9, x10 ]
+ ret
+.endm
+
+.text
+#define M5OP(name, func) m5op_func M5OP_MERGE_TOKENS(name, _addr), func;
+ M5OP_FOREACH
+#undef M5OP
DispatchTable *
addr_call_type_init()
{
+ map_m5_mem();
return &addr_dispatch;
}
env['VARIANT'] = 'arm'
get_variant_opt('CROSS_COMPILE', 'arm-linux-gnueabihf-')
env.Append(CFLAGS='-march=armv7-a')
+
+env['CALL_TYPE']['inst'].impl('m5op.S', default=True)
#include <gem5/asm/generic/m5ops.h>
#include <gem5/m5ops.h>
+#include "call_type.h"
#include "dispatch_table.h"
#include "m5_mmap.h"
char *command = "unspecified";
void usage();
-DispatchTable default_dispatch = {
-#define M5OP(name, func) .name = &name,
-M5OP_FOREACH
-#undef M5OP
-};
-
void
parse_int_args(int argc, char *argv[], uint64_t ints[], int len)
{
void
usage()
{
- int i;
-
- for (i = 0; i < numfuncs; ++i) {
- char *header = i ? "" : "usage:";
- fprintf(stderr, "%-6s %s %s %s\n",
- header, progname, mainfuncs[i].name, mainfuncs[i].usage);
- }
+ fprintf(stderr, "Usage: %s [call type] <command> [arguments]\n", progname);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Call types:\n");
+# if ENABLE_CT_addr
+ fprintf(stderr, " --addr%s\n", DEFAULT_CT_addr ? " (default)" : "");
+ fprintf(stderr, " Use the address based invocation method.\n");
+# if defined(M5OP_ADDR)
+ fprintf(stderr, " The address is %#"PRIx64".\n",
+ (uint64_t)M5OP_ADDR);
+# endif
+# endif
+# if ENABLE_CT_inst
+ fprintf(stderr, " --inst%s\n", DEFAULT_CT_inst ? " (default)" : "");
+ fprintf(stderr, " Use the instruction based invocation method.\n");
+# endif
+# if ENABLE_CT_semi
+ fprintf(stderr, " --semi%s\n", DEFAULT_CT_semi ? " (default)" : "");
+ fprintf(stderr, " Use the semi-hosting based invocation method.\n");
+# endif
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Commands:\n");
+ for (int i = 0; i < numfuncs; ++i)
+ fprintf(stderr, " %s %s\n", mainfuncs[i].name, mainfuncs[i].usage);
fprintf(stderr, "\n");
fprintf(stderr, "All times in nanoseconds!\n");
main(int argc, char *argv[])
{
progname = argv[0];
- if (argc < 2)
- usage(1);
- map_m5_mem();
+ argv++;
+ argc--;
+
+ DispatchTable *dt = NULL;
+
+# if ENABLE_CT_inst
+ if (!dt && inst_call_type_detect(&argc, &argv)) {
+ dt = inst_call_type_init();
+ }
+# endif
+# if ENABLE_CT_addr
+ if (!dt && addr_call_type_detect(&argc, &argv)) {
+ dt = addr_call_type_init();
+ }
+# endif
+# if ENABLE_CT_semi
+ if (!dt && semi_call_type_detect(&argc, &argv)) {
+ dt = semi_call_type_init();
+ }
+# endif
+ if (!dt)
+ dt = default_call_type_init();
+
+ if (!argc)
+ usage(1);
- command = argv[1];
+ command = argv[0];
- argv += 2;
- argc -= 2;
+ argv++;
+ argc--;
int i;
for (i = 0; i < numfuncs; ++i) {
if (strcmp(command, mainfuncs[i].name) != 0)
continue;
- mainfuncs[i].func(&default_dispatch, argc, argv);
+ mainfuncs[i].func(dt, argc, argv);
exit(0);
}
#include "semi_call_type.h"
+#define M5OP(name, func) __typeof__(name) M5OP_MERGE_TOKENS(name, _semi);
+M5OP_FOREACH
+#undef M5OP
+
static DispatchTable semi_dispatch = {
#define M5OP(name, func) .name = &M5OP_MERGE_TOKENS(name, _semi),
M5OP_FOREACH
env['VARIANT'] = 'sparc'
get_variant_opt('CROSS_COMPILE', 'sparc64-linux-gnu-')
env.Append(CFLAGS='-m64')
+
+env['CALL_TYPE']['inst'].impl('m5op.S', default=True)
env['VARIANT'] = 'thumb'
get_variant_opt('CROSS_COMPILE', 'arm-linux-gnueabihf-')
env.Append(CFLAGS=[ '-mthumb', '-march=armv7' ])
+
+env['CALL_TYPE']['inst'].impl('m5op.S', default=True)
env['VARIANT'] = 'x86'
get_variant_opt('CROSS_COMPILE', '')
env.Append(CFLAGS='-DM5OP_ADDR=0xFFFF0000')
-env.Append(ASFLAGS='-DM5OP_ADDR=0xFFFF0000')
+
+env['CALL_TYPE']['inst'].impl('m5op.S')
+env['CALL_TYPE']['addr'].impl('m5op_addr.S', default=True)
#include <gem5/asm/generic/m5ops.h>
-/*
- Note: The ABI for pseudo ops using the M5OP_ADDR is defined in
- src/arch/x86/pseudo_inst_abi.hh. If the ABI is changed below, it's likely
- that the ABI in the arch directory will also need to be updated.
-
- The ABI for the magic instruction-based pseudo ops is not affected by this.
-*/
-
-#if defined(M5OP_ADDR) && defined(M5OP_PIC)
-/* Use the memory mapped m5op interface */
-#define TWO_BYTE_OP(name, number) \
- .globl name; \
- .func name; \
-name: \
- mov m5_mem@gotpcrel(%rip), %r11; \
- mov (%r11), %r11; \
- mov $number, %rax; \
- shl $8, %rax; \
- mov 0(%r11, %rax, 1), %rax; \
- ret; \
- .endfunc;
-
-#elif defined(M5OP_ADDR) && !defined(M5OP_PIC)
-/* Use the memory mapped m5op interface */
-#define TWO_BYTE_OP(name, number) \
- .globl name; \
- .func name; \
-name: \
- mov m5_mem, %r11; \
- mov $number, %rax; \
- shl $8, %rax; \
- mov 0(%r11, %rax, 1), %rax; \
- ret; \
- .endfunc;
-
-#else
-/* Use the magic instruction based m5op interface. This does not work
- * in virtualized environments.
- */
-
-#define TWO_BYTE_OP(name, number) \
- .globl name; \
- .func name; \
-name: \
- .byte 0x0F, 0x04; \
- .word number; \
- ret; \
- .endfunc;
-
-#endif
-
-#define M5OP(name, number) TWO_BYTE_OP(name, number)
+.macro m5op_func, name, func
+ .globl \name
+ .func \name
+\name:
+ .byte 0x0F, 0x04
+ .word \func
+ ret
+ .endfunc
+.endm
+
+.text
+
+#define M5OP(name, func) m5op_func name, func;
M5OP_FOREACH
#undef M5OP
--- /dev/null
+/*
+ * Copyright (c) 2003-2006 The Regents of The University of Michigan
+ * 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 copyright holders 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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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 <gem5/asm/generic/m5ops.h>
+
+/*
+ * Note: The ABI for pseudo ops using the M5OP_ADDR is defined in
+ * src/arch/x86/pseudo_inst_abi.hh. If the ABI is changed below, it's likely
+ * that the ABI in the arch directory will also need to be updated.
+ */
+
+.macro m5op_func, name, func
+ .globl \name
+ .func \name
+\name:
+#if defined(M5OP_PIC)
+ mov m5_mem@gotpcrel(%rip), %r11
+ mov (%r11), %r11
+#else
+ mov m5_mem, %r11
+#endif
+ mov $\func, %rax
+ shl $8, %rax
+ mov 0(%r11, %rax, 1), %rax
+ ret
+ .endfunc
+.endm
+
+.text
+#define M5OP(name, func) m5op_func M5OP_MERGE_TOKENS(name, _addr), func;
+ M5OP_FOREACH
+#undef M5OP