[qfcc] Create separate instruction init and lookup

v6 vs v6p are more or less as before, with ruamoko added in. qfcc will
now try (and fail, due to the opcode table opnames being wrong) to
create ruamoko progs when given the ruamoko target option.
This commit is contained in:
Bill Currie 2022-01-07 19:56:15 +09:00
parent 14d95f81d1
commit 479d82f380

View file

@ -47,14 +47,17 @@
#include "tools/qfcc/include/statements.h"
#include "tools/qfcc/include/type.h"
static hashtab_t *opcode_type_table;
static hashtab_t *opcode_void_table;
static v6p_opcode_t *opcode_map;
static hashtab_t *v6p_opcode_type_table;
static hashtab_t *v6p_opcode_void_table;
static v6p_opcode_t *v6p_opcode_map;
static hashtab_t *rua_opcode_type_table;
static hashtab_t *rua_opcode_void_table;
#define ROTL(x,n) ((((unsigned)(x))<<(n))|((unsigned)(x))>>(32-n))
static uintptr_t
get_hash (const void *_op, void *_tab)
v6p_get_hash (const void *_op, void *_tab)
{
v6p_opcode_t *op = (v6p_opcode_t *) _op;
uintptr_t hash;
@ -65,7 +68,7 @@ get_hash (const void *_op, void *_tab)
}
static int
compare (const void *_opa, const void *_opb, void *unused)
v6p_compare (const void *_opa, const void *_opb, void *unused)
{
v6p_opcode_t *opa = (v6p_opcode_t *) _opa;
v6p_opcode_t *opb = (v6p_opcode_t *) _opb;
@ -78,11 +81,41 @@ compare (const void *_opa, const void *_opb, void *unused)
}
static const char *
get_key (const void *op, void *unused)
v6p_get_key (const void *op, void *unused)
{
return ((v6p_opcode_t *) op)->name;
}
static uintptr_t
rua_get_hash (const void *_op, void *_tab)
{
opcode_t *op = (opcode_t *) _op;
uintptr_t hash;
hash = ROTL (~op->types[0], 8) + ROTL (~op->types[1], 16)
+ ROTL (~op->types[2], 24);
return hash + Hash_String (op->opname);
}
static int
rua_compare (const void *_opa, const void *_opb, void *unused)
{
opcode_t *opa = (opcode_t *) _opa;
opcode_t *opb = (opcode_t *) _opb;
int cmp;
cmp = (opa->types[0] == opb->types[0])
&& (opa->types[1] == opb->types[1])
&& (opa->types[2] == opb->types[2]);
return cmp && !strcmp (opa->opname, opb->opname);
}
static const char *
rua_get_key (const void *op, void *unused)
{
return ((opcode_t *) op)->opname;
}
static int
check_operand_type (etype_t ot1, etype_t ot2)
{
@ -95,12 +128,16 @@ check_operand_type (etype_t ot1, etype_t ot2)
pr_ushort_t
opcode_get (instruction_t *op)
{
return (v6p_opcode_t *) op - opcode_map;
if (options.code.progsversion < PROG_VERSION) {
return (v6p_opcode_t *) op - v6p_opcode_map;
} else {
return (opcode_t *) op - pr_opcodes;
}
}
instruction_t *
opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
operand_t *op_c)
static v6p_opcode_t *
v6p_opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
operand_t *op_c)
{
v6p_opcode_t search_op = {};
v6p_opcode_t *op;
@ -112,12 +149,12 @@ opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
search_op.type_a = op_a ? low_level_type (op_a->type) : ev_invalid;
search_op.type_b = op_b ? low_level_type (op_b->type) : ev_invalid;
search_op.type_c = op_c ? low_level_type (op_c->type) : ev_invalid;
op = Hash_FindElement (opcode_type_table, &search_op);
op = Hash_FindElement (v6p_opcode_type_table, &search_op);
if (op)
return (instruction_t *) op;
op_list = Hash_FindList (opcode_void_table, name);
return op;
op_list = Hash_FindList (v6p_opcode_void_table, name);
if (!op_list)
return (instruction_t *) op;
return op;
for (i = 0; !op && op_list[i]; i++) {
sop = op_list[i];
if (check_operand_type (sop->type_a, search_op.type_a)
@ -126,36 +163,78 @@ opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
op = sop;
}
free (op_list);
return (instruction_t *) op;
return op;
}
void
opcode_init (void)
static opcode_t *
rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
operand_t *op_c)
{
opcode_t search_op = {};
opcode_t *op;
opcode_t *sop;
void **op_list;
int i;
search_op.opname = name;
search_op.types[0] = op_a ? low_level_type (op_a->type) : ev_invalid;
search_op.types[1] = op_b ? low_level_type (op_b->type) : ev_invalid;
search_op.types[2] = op_c ? low_level_type (op_c->type) : ev_invalid;
op = Hash_FindElement (rua_opcode_type_table, &search_op);
if (op)
return op;
op_list = Hash_FindList (rua_opcode_void_table, name);
if (!op_list)
return op;
for (i = 0; !op && op_list[i]; i++) {
sop = op_list[i];
if (check_operand_type (sop->types[0], search_op.types[0])
&& check_operand_type (sop->types[1], search_op.types[1])
&& check_operand_type (sop->types[2], search_op.types[2]))
op = sop;
}
free (op_list);
return op;
}
instruction_t *
opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
operand_t *op_c)
{
if (options.code.progsversion < PROG_VERSION) {
return (instruction_t *) v6p_opcode_find (name, op_a, op_b, op_c);
} else {
return (instruction_t *) rua_opcode_find (name, op_a, op_b, op_c);
}
}
static void
v6p_opcode_init (void)
{
const v6p_opcode_t *op;
v6p_opcode_t *mop;
if (opcode_type_table) {
Hash_FlushTable (opcode_void_table);
Hash_FlushTable (opcode_type_table);
if (v6p_opcode_type_table) {
Hash_FlushTable (v6p_opcode_void_table);
Hash_FlushTable (v6p_opcode_type_table);
} else {
opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0);
Hash_SetHashCompare (opcode_type_table, get_hash, compare);
opcode_void_table = Hash_NewTable (1021, get_key, 0, 0, 0);
v6p_opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0);
Hash_SetHashCompare (v6p_opcode_type_table, v6p_get_hash, v6p_compare);
v6p_opcode_void_table = Hash_NewTable (1021, v6p_get_key, 0, 0, 0);
}
int num_opcodes = 0;
for (op = pr_v6p_opcodes; op->name; op++) {
num_opcodes++;
}
if (!opcode_map) {
opcode_map = calloc (num_opcodes, sizeof (v6p_opcode_t));
if (!v6p_opcode_map) {
v6p_opcode_map = calloc (num_opcodes, sizeof (v6p_opcode_t));
}
for (int i = 0; i < num_opcodes; i++) {
op = pr_v6p_opcodes + i;
if (op->min_version > options.code.progsversion)
continue;
mop = opcode_map + i;
mop = v6p_opcode_map + i;
*mop = *op;
if (options.code.progsversion == PROG_ID_VERSION) {
// v6 progs have no concept of integer, but the QF engine
@ -169,9 +248,44 @@ opcode_init (void)
if (mop->type_c == ev_integer)
mop->type_c = ev_float;
}
Hash_AddElement (opcode_type_table, mop);
Hash_AddElement (v6p_opcode_type_table, mop);
if (mop->type_a == ev_void || mop->type_b == ev_void
|| mop->type_c == ev_void)
Hash_Add (opcode_void_table, mop);
Hash_Add (v6p_opcode_void_table, mop);
}
}
static void
rua_opcode_init (void)
{
if (rua_opcode_type_table) {
return;
}
rua_opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0);
Hash_SetHashCompare (rua_opcode_type_table, rua_get_hash, rua_compare);
rua_opcode_void_table = Hash_NewTable (1021, rua_get_key, 0, 0, 0);
int num_opcodes = sizeof (pr_opcodes) / sizeof (pr_opcodes[0]);
for (int i = 0; i < num_opcodes; i++) {
const opcode_t *op = pr_opcodes + i;
if (!op->opname) {
continue;
}
Hash_AddElement (rua_opcode_type_table, (opcode_t *) op);
if (op->types[0] == ev_void || op->types[1] == ev_void
|| op->types[2] == ev_void) {
Hash_Add (rua_opcode_void_table, (opcode_t *) op);
}
}
}
void
opcode_init (void)
{
if (options.code.progsversion < PROG_VERSION) {
v6p_opcode_init ();
} else {
rua_opcode_init ();
}
}