[gamecode] Change address mode B to entity.field

It turned out that address mode B was redundant as C with 0 offset
(immediate) was the same (except for the underlying C code of course,
but adding st->b is very cheap). This allowed B to be used for
entity.field for all transfer operations. Thus instructions 0-3 are now
free as load E became load B, and other than the specifics of format
codes for statement printing, transfers+lea are unified.
This commit is contained in:
Bill Currie 2022-01-20 14:55:29 +09:00
parent 6ae9daf4b7
commit e20aed5c5a
6 changed files with 82 additions and 117 deletions

View file

@ -4,6 +4,7 @@ bitmap_txt = """
0 0010 mmss push
0 0011 mmss pop
0 1ccc ttss compare
0 0000 00nn
0 1011 nnnn
0 1111 nnnn
@ -34,11 +35,26 @@ bitmap_txt = """
import copy
address_mode = "ABCD"
address_types = [
"ev_void, ev_invalid",
"ev_entity, ev_field",
"ev_ptr, ev_short",
"ev_ptr, ev_int",
]
#store, pop and lea
store_fmt = [
"%ga",
"%Ga.%Gb(%Ea)",
"*(%Ga + %sb)",
"*(%Ga + %Gb)",
]
# load and push
load_fmt = [
"%Ga.%Gb(%Ea), %gc",
"*%Ga, %gc",
"*(%Ga + %sb), %gc",
"*(%Ga + %Gb), %gc",
"%Ga.%Gb(%Ea)",
"*(%Ga + %sb)",
"*(%Ga + %Gb)",
]
branch_fmt = [
"branch %sa (%Oa)",
@ -175,29 +191,26 @@ lea_formats = {
"opcode": "OP_LEA_{op_mode[mm]}",
"mnemonic": "lea",
"opname": "lea",
"format": "{lea_fmt[mm]}",
"format": "{lea_fmt[mm]}, %gc",
"widths": "0, 0, 1",
"types": "ev_ptr, ev_ptr, ev_ptr",
"types": "{lea_types[mm]}, ev_ptr",
"args": {
"op_mode": "AECD",
"lea_fmt": [
"%ga, %gc",
"%Ga.%Gb(%Ea), %gc",
"*(%Ga + %sb), %gc",
"*(%Ga + %Gb), %gc",
],
"op_mode": address_mode,
"lea_fmt": store_fmt,
"lea_types": address_types,
},
}
load_formats = {
"opcode": "OP_LOAD_{op_mode[mm]}_{ss+1}",
"mnemonic": "load",
"opname": "load",
"format": "{load_fmt[mm]}",
"format": "{load_fmt[mm]}, %gc",
"widths": "0, 0, {ss+1}",
"types": "ev_void, ev_void, ev_void",
"types": "{load_types[mm]}, ev_void",
"args": {
"op_mode": "EBCD",
"op_mode": address_mode,
"load_fmt": load_fmt,
"load_types": address_types,
},
}
mathops_formats = {
@ -242,15 +255,11 @@ push_formats = {
"opname": "push",
"format": "{push_fmt[mm]}",
"widths": "{ss+1}, 0, 0",
"types": "ev_void, ev_void, ev_invalid",
"types": "{push_types[mm]}, ev_invalid",
"args": {
"op_mode": "ABCD",
"push_fmt": [
"%Ga",
"*%Ga",
"*(%Ga + %sb)",
"*(%Ga + %Gb)",
],
"op_mode": address_mode,
"push_fmt": load_fmt,
"push_types": address_types,
},
}
pushregs_formats = {
@ -267,15 +276,11 @@ pop_formats = {
"opname": "pop",
"format": "{pop_fmt[mm]}",
"widths": "{ss+1}, 0, 0",
"types": "ev_void, ev_void, ev_invalid",
"types": "{pop_types[mm]}, ev_invalid",
"args": {
"op_mode": "ABCD",
"pop_fmt": [
"%ga",
"*%Ga",
"*(%Ga + %sb)",
"*(%Ga + %Gb)",
],
"op_mode": address_mode,
"pop_fmt": store_fmt,
"pop_types": address_types,
},
}
popregs_formats = {
@ -342,24 +347,14 @@ store_formats = {
"opcode": "OP_STORE_{op_mode[mm]}_{ss+1}",
"mnemonic": "{store_op[mm]}",
"opname": "{store_op[mm]}",
"format": "{store_fmt[mm]}",
"format": "%Gc, {store_fmt[mm]}",
"widths": "{ss+1}, 0, {ss+1}",
"types": "{store_types[mm]}",
"types": "{store_types[mm]}, ev_void",
"args": {
"op_mode": "ABCD",
"store_fmt": [
"%Gc, %ga",
"%Gc, *%Ga",
"%Gc, *(%Ga + %sb)",
"%Gc, *(%Ga + %Gb)",
],
"op_mode": address_mode,
"store_fmt": store_fmt,
"store_op": ["assign", "store", "store", "store"],
"store_types": [
"ev_void, ev_invalid, ev_void",
"ev_ptr, ev_invalid, ev_void",
"ev_ptr, ev_short, ev_void",
"ev_ptr, ev_int, ev_void",
],
"store_types": address_types,
},
}
string_formats = {

View file

@ -1759,8 +1759,9 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind)
mm_offs = op_a - pr->pr_globals;
break;
case 1:
// simple pointer dereference: *a
mm_offs = OPA(ptr);
// entity.field (equivalent to OP_LOAD_t_v6p)
pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals;
mm_offs = edict_area + OPA(entity) + OPB(field);
break;
case 2:
// constant indexed pointer: *a + b (supports -ve offset)
@ -1770,11 +1771,6 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind)
// variable indexed pointer: *a + *b (supports -ve offset)
mm_offs = OPA(ptr) + OPB(int);
break;
case 4:
// entity.field (equivalent to OP_LOAD_t_v6p)
pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals;
mm_offs = edict_area + OPA(entity) + OPB(field);
break;
}
return pr->pr_globals + mm_offs;
}
@ -2767,44 +2763,28 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
pr_opcode_e st_op = st->op & OP_MASK;
switch (st_op) {
// 0 0000
case OP_LOAD_E_1:
mm = pr_address_mode (pr, st, 4);
OPC(int) = MM(int);
break;
case OP_LOAD_B_1:
case OP_LOAD_C_1:
case OP_LOAD_D_1:
mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_1) >> 2);
mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_1 + 4) >> 2);
OPC(int) = MM(int);
break;
case OP_LOAD_E_2:
mm = pr_address_mode (pr, st, 4);
OPC(ivec2) = MM(ivec2);
break;
case OP_LOAD_B_2:
case OP_LOAD_C_2:
case OP_LOAD_D_2:
mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_2) >> 2);
mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_2 + 4) >> 2);
OPC(ivec2) = MM(ivec2);
break;
case OP_LOAD_E_3:
mm = pr_address_mode (pr, st, 4);
VectorCopy (&MM(int), &OPC(int));
break;
case OP_LOAD_B_3:
case OP_LOAD_C_3:
case OP_LOAD_D_3:
mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_3) >> 2);
mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_3 + 4) >> 2);
VectorCopy (&MM(int), &OPC(int));
break;
case OP_LOAD_E_4:
mm = pr_address_mode (pr, st, 4);
OPC(ivec4) = MM(ivec4);
break;
case OP_LOAD_B_4:
case OP_LOAD_C_4:
case OP_LOAD_D_4:
mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_4) >> 2);
mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_4 + 4) >> 2);
OPC(ivec4) = MM(ivec4);
break;
// 0 0001
@ -3389,15 +3369,12 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
break;
// 1 1111
case OP_LEA_A:
case OP_LEA_B:
case OP_LEA_C:
case OP_LEA_D:
mm = pr_address_mode (pr, st, (st_op - OP_LEA_A));
op_c->pointer_var = mm - pr->pr_globals;
break;
case OP_LEA_E:
mm = pr_address_mode (pr, st, 4);
op_c->pointer_var = mm - pr->pr_globals;
break;
case OP_QV4MUL_F:
OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4));
break;

View file

@ -22,7 +22,7 @@ static dstatement_t lea_statements[] = {
{OP(0, 0, 0, OP_LEA_A), 7, 9, 12},
{OP(0, 0, 0, OP_LEA_C), 2, 6, 13},
{OP(0, 0, 0, OP_LEA_D), 2, 6, 14},
{OP(0, 0, 0, OP_LEA_E), 4, 2, 15},
{OP(0, 0, 0, OP_LEA_B), 4, 2, 15},
};
test_t tests[] = {

View file

@ -30,20 +30,12 @@ static pr_int_t test_globals_expect[] = {
1, 2, 3, 4,
};
static dstatement_t load_E_statements[] = {
{OP(0, 0, 0, OP_LOAD_E_4), 7, 9, 12},
{OP(0, 0, 0, OP_LOAD_E_3), 7, 8, 16},
{OP(0, 0, 0, OP_LOAD_E_1), 7, 7, 19},
{OP(0, 0, 0, OP_LOAD_E_2), 7, 6, 20},
{OP(0, 0, 0, OP_LOAD_E_2), 7, 5, 22},
};
static dstatement_t load_B_statements[] = {
{OP(0, 0, 0, OP_LOAD_B_4), 4, 0, 12},
{OP(0, 0, 0, OP_LOAD_B_3), 3, 0, 16},
{OP(0, 0, 0, OP_LOAD_B_1), 2, 0, 19},
{OP(0, 0, 0, OP_LOAD_B_2), 1, 0, 20},
{OP(0, 0, 0, OP_LOAD_B_2), 0, 0, 22},
{OP(0, 0, 0, OP_LOAD_B_4), 7, 9, 12},
{OP(0, 0, 0, OP_LOAD_B_3), 7, 8, 16},
{OP(0, 0, 0, OP_LOAD_B_1), 7, 7, 19},
{OP(0, 0, 0, OP_LOAD_B_2), 7, 6, 20},
{OP(0, 0, 0, OP_LOAD_B_2), 7, 5, 22},
};
static dstatement_t load_C_statements[] = {
@ -63,17 +55,6 @@ static dstatement_t load_D_statements[] = {
};
test_t tests[] = {
{
.desc = "load E",
.num_globals = num_globals (test_globals_init, test_globals_expect),
.num_statements = num_statements (load_E_statements),
.statements = load_E_statements,
.init_globals = test_globals_init,
.expect_globals = test_globals_expect,
// FIXME negative field offsets are not official but work because all
// offset calculations are done in 32-bit and thus wrap anyway
.edict_area = 28,
},
{
.desc = "load B",
.num_globals = num_globals (test_globals_init, test_globals_expect),
@ -81,6 +62,9 @@ test_t tests[] = {
.statements = load_B_statements,
.init_globals = test_globals_init,
.expect_globals = test_globals_expect,
// FIXME negative field offsets are not official but work because all
// offset calculations are done in 32-bit and thus wrap anyway
.edict_area = 28,
},
{
.desc = "load C",

View file

@ -81,11 +81,11 @@ static dstatement_t stack_AB_statements[] = {
{OP(0, 0, 0, OP_PUSH_A_2), 20, 0, 0},
{OP(0, 0, 0, OP_PUSH_A_2), 22, 0, 0},
{OP(0, 0, 0, OP_POP_B_2), 0, 0, 0},
{OP(0, 0, 0, OP_POP_B_2), 1, 0, 0},
{OP(0, 0, 0, OP_POP_B_1), 2, 0, 0},
{OP(0, 0, 0, OP_POP_B_3), 3, 0, 0},
{OP(0, 0, 0, OP_POP_B_4), 4, 0, 0},
{OP(0, 0, 0, OP_POP_B_2), 7, 5, 0},
{OP(0, 0, 0, OP_POP_B_2), 7, 6, 0},
{OP(0, 0, 0, OP_POP_B_1), 7, 7, 0},
{OP(0, 0, 0, OP_POP_B_3), 7, 8, 0},
{OP(0, 0, 0, OP_POP_B_4), 7, 9, 0},
};
static dstatement_t stack_AC_statements[] = {
@ -117,11 +117,11 @@ static dstatement_t stack_AD_statements[] = {
};
static dstatement_t stack_BA_statements[] = {
{OP(0, 0, 0, OP_PUSH_B_2), 0, 0, 0},
{OP(0, 0, 0, OP_PUSH_B_2), 1, 0, 0},
{OP(0, 0, 0, OP_PUSH_B_1), 2, 0, 0},
{OP(0, 0, 0, OP_PUSH_B_3), 3, 0, 0},
{OP(0, 0, 0, OP_PUSH_B_4), 4, 0, 0},
{OP(0, 0, 0, OP_PUSH_B_2), 7, 5, 0},
{OP(0, 0, 0, OP_PUSH_B_2), 7, 6, 0},
{OP(0, 0, 0, OP_PUSH_B_1), 7, 7, 0},
{OP(0, 0, 0, OP_PUSH_B_3), 7, 8, 0},
{OP(0, 0, 0, OP_PUSH_B_4), 7, 9, 0},
{OP(0, 0, 0, OP_POP_A_4), 12, 0, 0},
{OP(0, 0, 0, OP_POP_A_3), 16, 0, 0},
@ -176,6 +176,9 @@ test_t tests[] = {
.statements = stack_AB_statements,
.init_globals = test_globals_init1,
.expect_globals = test_globals_expect1,
// FIXME negative field offsets are not official but work because all
// offset calculations are done in 32-bit and thus wrap anyway
.edict_area = 28,
},
{
.desc = "stack push A pop C",
@ -203,6 +206,9 @@ test_t tests[] = {
.statements = stack_BA_statements,
.init_globals = test_globals_init2,
.expect_globals = test_globals_expect2,
// FIXME negative field offsets are not official but work because all
// offset calculations are done in 32-bit and thus wrap anyway
.edict_area = 28,
},
{
.desc = "stack push C pop A",

View file

@ -39,11 +39,11 @@ static dstatement_t store_A_statements[] = {
};
static dstatement_t store_B_statements[] = {
{OP(0, 0, 0, OP_STORE_B_4), 4, 0, 12},
{OP(0, 0, 0, OP_STORE_B_3), 3, 0, 16},
{OP(0, 0, 0, OP_STORE_B_1), 2, 0, 19},
{OP(0, 0, 0, OP_STORE_B_2), 1, 0, 20},
{OP(0, 0, 0, OP_STORE_B_2), 0, 0, 22},
{OP(0, 0, 0, OP_STORE_B_4), 7, 9, 12},
{OP(0, 0, 0, OP_STORE_B_3), 7, 8, 16},
{OP(0, 0, 0, OP_STORE_B_1), 7, 7, 19},
{OP(0, 0, 0, OP_STORE_B_2), 7, 6, 20},
{OP(0, 0, 0, OP_STORE_B_2), 7, 5, 22},
};
static dstatement_t store_C_statements[] = {
@ -78,6 +78,9 @@ test_t tests[] = {
.statements = store_B_statements,
.init_globals = test_globals_init,
.expect_globals = test_globals_expect,
// FIXME negative field offsets are not official but work because all
// offset calculations are done in 32-bit and thus wrap anyway
.edict_area = 28,
},
{
.desc = "store C",