[qfcc] Map 64-bit load/store/assign instructions

In order to not waste instructions, the Ruamoko ISA does not provide 1
and 2 component 64-bit load/store instructions since they can be
implemented using 2 and 4 component 32-bit instructions (load and store
are independent of the interpretation of the data). This fixes the
double test, and technically the double-alias test, but it fails due to
a problem with the optimizer causing lea to use the wrong reference for
the address. It also breaks the quaternion test due to what seems to be
a type error that may have been lurking for a while, further
investigation is needed there.
This commit is contained in:
Bill Currie 2022-02-02 16:06:15 +09:00
parent 0211b6ec5b
commit 38550922cc
2 changed files with 42 additions and 5 deletions

View file

@ -280,7 +280,7 @@ operand_type (const operand_t *op, const char *name)
} }
static int static int
operand_width (operand_t *op) operand_width (const char *opname, operand_t *op)
{ {
if (!op) { if (!op) {
return 0; return 0;
@ -292,6 +292,14 @@ operand_width (operand_t *op)
if (type == ev_quaternion) { if (type == ev_quaternion) {
return 4; return 4;
} }
// FIXME see FIXME in rua_opcode_find
if ((type == ev_long || type == ev_ulong || type == ev_double)
&& (!strcmp (opname, "load") || !strcmp (opname, "store")
|| !strcmp (opname, "assign"))) {
if (op->width < 3) {
return op->width * 2;
}
}
return op->width; return op->width;
} }
@ -299,6 +307,35 @@ static opcode_t *
rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
operand_t *op_c) operand_t *op_c)
{ {
// FIXME this is a bit of an ugly hack to map 64-bit load and store/assign
// instructions: 1 and 2 component instructions become 2 and 4 components
// using the 32-bit instructions, while 3 and 4 remain unchanged but use
// the 64-bit versions of the instructs (of which there are only 3 and 4
// component versions). That bit of fun can't be helped without wasting a
// lot of instructions, but this mapping scheme leaves a lot to be desired.
const char *opname_a = "";
const char *opname_c = "";
if (!strcmp (name, "load") || !strcmp (name, "store")
|| !strcmp (name, "assign")) {
opname_c = name;
if (!strcmp (name, "assign")) {
opname_a = name;
if (op_c->width > 2) {
name = "assign64";
}
}
if (!strcmp (name, "load")) {
if (op_c->width > 2) {
name = "load64";
}
}
if (!strcmp (name, "store")) {
if (op_c->width > 2) {
name = "store64";
}
}
}
opcode_t search_op = { opcode_t search_op = {
.opname = name, .opname = name,
.types = { .types = {
@ -307,9 +344,9 @@ rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
operand_type (op_c, name), operand_type (op_c, name),
}, },
.widths = { .widths = {
operand_width (op_a), operand_width (opname_a, op_a),
operand_width (op_b), operand_width ("", op_b),
operand_width (op_c), operand_width (opname_c, op_c),
}, },
}; };
opcode_t *op; opcode_t *op;

View file

@ -11,7 +11,7 @@ test_format ()
{ {
int fail = 0; int fail = 0;
type_pun.d = M_PI; type_pun.d = M_PI;
printf ("%g %08x%08x\n", type_pun.d, type_pun.i[1], type_pun.i[0]); printf ("%.17g %08x%08x\n", type_pun.d, type_pun.i[1], type_pun.i[0]);
// this will fail on big-endian systems // this will fail on big-endian systems
fail = type_pun.i[0] != 0x54442d18 || type_pun.i[1] != 0x400921fb; fail = type_pun.i[0] != 0x54442d18 || type_pun.i[1] != 0x400921fb;
return fail; return fail;