mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
[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:
parent
0211b6ec5b
commit
38550922cc
2 changed files with 42 additions and 5 deletions
|
@ -280,7 +280,7 @@ operand_type (const operand_t *op, const char *name)
|
|||
}
|
||||
|
||||
static int
|
||||
operand_width (operand_t *op)
|
||||
operand_width (const char *opname, operand_t *op)
|
||||
{
|
||||
if (!op) {
|
||||
return 0;
|
||||
|
@ -292,6 +292,14 @@ operand_width (operand_t *op)
|
|||
if (type == ev_quaternion) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -299,6 +307,35 @@ static opcode_t *
|
|||
rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
|
||||
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 = {
|
||||
.opname = name,
|
||||
.types = {
|
||||
|
@ -307,9 +344,9 @@ rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
|
|||
operand_type (op_c, name),
|
||||
},
|
||||
.widths = {
|
||||
operand_width (op_a),
|
||||
operand_width (op_b),
|
||||
operand_width (op_c),
|
||||
operand_width (opname_a, op_a),
|
||||
operand_width ("", op_b),
|
||||
operand_width (opname_c, op_c),
|
||||
},
|
||||
};
|
||||
opcode_t *op;
|
||||
|
|
|
@ -11,7 +11,7 @@ test_format ()
|
|||
{
|
||||
int fail = 0;
|
||||
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
|
||||
fail = type_pun.i[0] != 0x54442d18 || type_pun.i[1] != 0x400921fb;
|
||||
return fail;
|
||||
|
|
Loading…
Reference in a new issue