24.8.2.2. m5ops instructions interface
Let’s study how the gem5 m5 executable uses them:
-
include/gem5/asm/generic/m5ops.h
: defines the magic constants that represent the instructions -
util/m5/m5op_arm_A64.S
: use the magic constants that represent the instructions using C preprocessor magic -
util/m5/m5.c
: the actual executable. Gets linked tom5op_arm_A64.S
which defines a function for each m5op.
We notice that there are two different implementations for each arch:
-
magic instructions, which don’t exist in the corresponding arch
-
magic memory addresses on a given page: m5ops magic addresses
Then, in aarch64 magic instructions for example, the lines:
.macro m5op_func, name, func, subfunc .globl \name \name: .long 0xff000110 | (\func << 16) | (\subfunc << 12) ret
define a simple function function for each m5op. Here we see that:
-
0xff000110
is a base mask for the magic non-existing instruction -
\func
and\subfunc
are OR-applied on top of the base mask, and define m5op this is.Those values will loop over the magic constants defined in
m5ops.h
with the deferred preprocessor idiom.For example,
exit
is0x21
due to:#define M5OP_EXIT 0x21
Finally, m5.c
calls the defined functions as in:
m5_exit(ints[0]);
Therefore, the runtime "argument" that gets passed to the instruction, e.g. the delay in ticks until the exit for m5 exit
, gets passed directly through the aarch64 calling convention.
Keep in mind that for all archs, m5.c
does the calls with 64-bit integers:
uint64_t ints[2] = {0,0}; parse_int_args(argc, argv, ints, argc); m5_fail(ints[1], ints[0]);
Therefore, for example:
-
aarch64 uses
x0
for the first argument andx1
for the second, since each is 64 bits log already -
arm uses
r0
andr1
for the first argument, andr2
andr3
for the second, since each register is only 32 bits long
That convention specifies that x0
to x7
contain the function arguments, so x0
contains the first argument, and x1
the second.
In our m5ops
example, we just hardcode everything in the assembly one-liners we are producing.
We ignore the \subfunc
since it is always 0 on the ops that interest us.