mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-20 07:50:45 +00:00
[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:
parent
14d95f81d1
commit
479d82f380
1 changed files with 142 additions and 28 deletions
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue