[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 0010 mmss push
0 0011 mmss pop 0 0011 mmss pop
0 1ccc ttss compare 0 1ccc ttss compare
0 0000 00nn
0 1011 nnnn 0 1011 nnnn
0 1111 nnnn 0 1111 nnnn
@ -34,11 +35,26 @@ bitmap_txt = """
import copy 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 = [ load_fmt = [
"%Ga.%Gb(%Ea), %gc",
"*%Ga, %gc", "*%Ga, %gc",
"*(%Ga + %sb), %gc", "%Ga.%Gb(%Ea)",
"*(%Ga + %Gb), %gc", "*(%Ga + %sb)",
"*(%Ga + %Gb)",
] ]
branch_fmt = [ branch_fmt = [
"branch %sa (%Oa)", "branch %sa (%Oa)",
@ -175,29 +191,26 @@ lea_formats = {
"opcode": "OP_LEA_{op_mode[mm]}", "opcode": "OP_LEA_{op_mode[mm]}",
"mnemonic": "lea", "mnemonic": "lea",
"opname": "lea", "opname": "lea",
"format": "{lea_fmt[mm]}", "format": "{lea_fmt[mm]}, %gc",
"widths": "0, 0, 1", "widths": "0, 0, 1",
"types": "ev_ptr, ev_ptr, ev_ptr", "types": "{lea_types[mm]}, ev_ptr",
"args": { "args": {
"op_mode": "AECD", "op_mode": address_mode,
"lea_fmt": [ "lea_fmt": store_fmt,
"%ga, %gc", "lea_types": address_types,
"%Ga.%Gb(%Ea), %gc",
"*(%Ga + %sb), %gc",
"*(%Ga + %Gb), %gc",
],
}, },
} }
load_formats = { load_formats = {
"opcode": "OP_LOAD_{op_mode[mm]}_{ss+1}", "opcode": "OP_LOAD_{op_mode[mm]}_{ss+1}",
"mnemonic": "load", "mnemonic": "load",
"opname": "load", "opname": "load",
"format": "{load_fmt[mm]}", "format": "{load_fmt[mm]}, %gc",
"widths": "0, 0, {ss+1}", "widths": "0, 0, {ss+1}",
"types": "ev_void, ev_void, ev_void", "types": "{load_types[mm]}, ev_void",
"args": { "args": {
"op_mode": "EBCD", "op_mode": address_mode,
"load_fmt": load_fmt, "load_fmt": load_fmt,
"load_types": address_types,
}, },
} }
mathops_formats = { mathops_formats = {
@ -242,15 +255,11 @@ push_formats = {
"opname": "push", "opname": "push",
"format": "{push_fmt[mm]}", "format": "{push_fmt[mm]}",
"widths": "{ss+1}, 0, 0", "widths": "{ss+1}, 0, 0",
"types": "ev_void, ev_void, ev_invalid", "types": "{push_types[mm]}, ev_invalid",
"args": { "args": {
"op_mode": "ABCD", "op_mode": address_mode,
"push_fmt": [ "push_fmt": load_fmt,
"%Ga", "push_types": address_types,
"*%Ga",
"*(%Ga + %sb)",
"*(%Ga + %Gb)",
],
}, },
} }
pushregs_formats = { pushregs_formats = {
@ -267,15 +276,11 @@ pop_formats = {
"opname": "pop", "opname": "pop",
"format": "{pop_fmt[mm]}", "format": "{pop_fmt[mm]}",
"widths": "{ss+1}, 0, 0", "widths": "{ss+1}, 0, 0",
"types": "ev_void, ev_void, ev_invalid", "types": "{pop_types[mm]}, ev_invalid",
"args": { "args": {
"op_mode": "ABCD", "op_mode": address_mode,
"pop_fmt": [ "pop_fmt": store_fmt,
"%ga", "pop_types": address_types,
"*%Ga",
"*(%Ga + %sb)",
"*(%Ga + %Gb)",
],
}, },
} }
popregs_formats = { popregs_formats = {
@ -342,24 +347,14 @@ store_formats = {
"opcode": "OP_STORE_{op_mode[mm]}_{ss+1}", "opcode": "OP_STORE_{op_mode[mm]}_{ss+1}",
"mnemonic": "{store_op[mm]}", "mnemonic": "{store_op[mm]}",
"opname": "{store_op[mm]}", "opname": "{store_op[mm]}",
"format": "{store_fmt[mm]}", "format": "%Gc, {store_fmt[mm]}",
"widths": "{ss+1}, 0, {ss+1}", "widths": "{ss+1}, 0, {ss+1}",
"types": "{store_types[mm]}", "types": "{store_types[mm]}, ev_void",
"args": { "args": {
"op_mode": "ABCD", "op_mode": address_mode,
"store_fmt": [ "store_fmt": store_fmt,
"%Gc, %ga",
"%Gc, *%Ga",
"%Gc, *(%Ga + %sb)",
"%Gc, *(%Ga + %Gb)",
],
"store_op": ["assign", "store", "store", "store"], "store_op": ["assign", "store", "store", "store"],
"store_types": [ "store_types": address_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",
],
}, },
} }
string_formats = { 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; mm_offs = op_a - pr->pr_globals;
break; break;
case 1: case 1:
// simple pointer dereference: *a // entity.field (equivalent to OP_LOAD_t_v6p)
mm_offs = OPA(ptr); pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals;
mm_offs = edict_area + OPA(entity) + OPB(field);
break; break;
case 2: case 2:
// constant indexed pointer: *a + b (supports -ve offset) // 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) // variable indexed pointer: *a + *b (supports -ve offset)
mm_offs = OPA(ptr) + OPB(int); mm_offs = OPA(ptr) + OPB(int);
break; 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; 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; pr_opcode_e st_op = st->op & OP_MASK;
switch (st_op) { switch (st_op) {
// 0 0000 // 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_B_1:
case OP_LOAD_C_1: case OP_LOAD_C_1:
case OP_LOAD_D_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); OPC(int) = MM(int);
break; 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_B_2:
case OP_LOAD_C_2: case OP_LOAD_C_2:
case OP_LOAD_D_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); OPC(ivec2) = MM(ivec2);
break; 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_B_3:
case OP_LOAD_C_3: case OP_LOAD_C_3:
case OP_LOAD_D_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)); VectorCopy (&MM(int), &OPC(int));
break; 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_B_4:
case OP_LOAD_C_4: case OP_LOAD_C_4:
case OP_LOAD_D_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); OPC(ivec4) = MM(ivec4);
break; break;
// 0 0001 // 0 0001
@ -3389,15 +3369,12 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
break; break;
// 1 1111 // 1 1111
case OP_LEA_A: case OP_LEA_A:
case OP_LEA_B:
case OP_LEA_C: case OP_LEA_C:
case OP_LEA_D: case OP_LEA_D:
mm = pr_address_mode (pr, st, (st_op - OP_LEA_A)); mm = pr_address_mode (pr, st, (st_op - OP_LEA_A));
op_c->pointer_var = mm - pr->pr_globals; op_c->pointer_var = mm - pr->pr_globals;
break; 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: case OP_QV4MUL_F:
OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4)); OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4));
break; 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_A), 7, 9, 12},
{OP(0, 0, 0, OP_LEA_C), 2, 6, 13}, {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_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[] = { test_t tests[] = {

View file

@ -30,20 +30,12 @@ static pr_int_t test_globals_expect[] = {
1, 2, 3, 4, 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[] = { static dstatement_t load_B_statements[] = {
{OP(0, 0, 0, OP_LOAD_B_4), 4, 0, 12}, {OP(0, 0, 0, OP_LOAD_B_4), 7, 9, 12},
{OP(0, 0, 0, OP_LOAD_B_3), 3, 0, 16}, {OP(0, 0, 0, OP_LOAD_B_3), 7, 8, 16},
{OP(0, 0, 0, OP_LOAD_B_1), 2, 0, 19}, {OP(0, 0, 0, OP_LOAD_B_1), 7, 7, 19},
{OP(0, 0, 0, OP_LOAD_B_2), 1, 0, 20}, {OP(0, 0, 0, OP_LOAD_B_2), 7, 6, 20},
{OP(0, 0, 0, OP_LOAD_B_2), 0, 0, 22}, {OP(0, 0, 0, OP_LOAD_B_2), 7, 5, 22},
}; };
static dstatement_t load_C_statements[] = { static dstatement_t load_C_statements[] = {
@ -63,17 +55,6 @@ static dstatement_t load_D_statements[] = {
}; };
test_t tests[] = { 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", .desc = "load B",
.num_globals = num_globals (test_globals_init, test_globals_expect), .num_globals = num_globals (test_globals_init, test_globals_expect),
@ -81,6 +62,9 @@ test_t tests[] = {
.statements = load_B_statements, .statements = load_B_statements,
.init_globals = test_globals_init, .init_globals = test_globals_init,
.expect_globals = test_globals_expect, .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", .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), 20, 0, 0},
{OP(0, 0, 0, OP_PUSH_A_2), 22, 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), 7, 5, 0},
{OP(0, 0, 0, OP_POP_B_2), 1, 0, 0}, {OP(0, 0, 0, OP_POP_B_2), 7, 6, 0},
{OP(0, 0, 0, OP_POP_B_1), 2, 0, 0}, {OP(0, 0, 0, OP_POP_B_1), 7, 7, 0},
{OP(0, 0, 0, OP_POP_B_3), 3, 0, 0}, {OP(0, 0, 0, OP_POP_B_3), 7, 8, 0},
{OP(0, 0, 0, OP_POP_B_4), 4, 0, 0}, {OP(0, 0, 0, OP_POP_B_4), 7, 9, 0},
}; };
static dstatement_t stack_AC_statements[] = { static dstatement_t stack_AC_statements[] = {
@ -117,11 +117,11 @@ static dstatement_t stack_AD_statements[] = {
}; };
static dstatement_t stack_BA_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), 7, 5, 0},
{OP(0, 0, 0, OP_PUSH_B_2), 1, 0, 0}, {OP(0, 0, 0, OP_PUSH_B_2), 7, 6, 0},
{OP(0, 0, 0, OP_PUSH_B_1), 2, 0, 0}, {OP(0, 0, 0, OP_PUSH_B_1), 7, 7, 0},
{OP(0, 0, 0, OP_PUSH_B_3), 3, 0, 0}, {OP(0, 0, 0, OP_PUSH_B_3), 7, 8, 0},
{OP(0, 0, 0, OP_PUSH_B_4), 4, 0, 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_4), 12, 0, 0},
{OP(0, 0, 0, OP_POP_A_3), 16, 0, 0}, {OP(0, 0, 0, OP_POP_A_3), 16, 0, 0},
@ -176,6 +176,9 @@ test_t tests[] = {
.statements = stack_AB_statements, .statements = stack_AB_statements,
.init_globals = test_globals_init1, .init_globals = test_globals_init1,
.expect_globals = test_globals_expect1, .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", .desc = "stack push A pop C",
@ -203,6 +206,9 @@ test_t tests[] = {
.statements = stack_BA_statements, .statements = stack_BA_statements,
.init_globals = test_globals_init2, .init_globals = test_globals_init2,
.expect_globals = test_globals_expect2, .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", .desc = "stack push C pop A",

View file

@ -39,11 +39,11 @@ static dstatement_t store_A_statements[] = {
}; };
static dstatement_t store_B_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_4), 7, 9, 12},
{OP(0, 0, 0, OP_STORE_B_3), 3, 0, 16}, {OP(0, 0, 0, OP_STORE_B_3), 7, 8, 16},
{OP(0, 0, 0, OP_STORE_B_1), 2, 0, 19}, {OP(0, 0, 0, OP_STORE_B_1), 7, 7, 19},
{OP(0, 0, 0, OP_STORE_B_2), 1, 0, 20}, {OP(0, 0, 0, OP_STORE_B_2), 7, 6, 20},
{OP(0, 0, 0, OP_STORE_B_2), 0, 0, 22}, {OP(0, 0, 0, OP_STORE_B_2), 7, 5, 22},
}; };
static dstatement_t store_C_statements[] = { static dstatement_t store_C_statements[] = {
@ -78,6 +78,9 @@ test_t tests[] = {
.statements = store_B_statements, .statements = store_B_statements,
.init_globals = test_globals_init, .init_globals = test_globals_init,
.expect_globals = test_globals_expect, .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", .desc = "store C",