[gamecode] Add 64-bit load/store instructions

Only widths 3 and 4 have been added because widths 1 and 2 can be
implemented by widths 2 and 4 of the 32-bit load/store instructions.
This commit is contained in:
Bill Currie 2022-02-02 14:47:36 +09:00
parent 93840d9892
commit 0211b6ec5b
5 changed files with 266 additions and 1 deletions

View file

@ -9,7 +9,9 @@ bitmap_txt = """
0 0000 0001 adjstk
0 0000 0010 constant
0 1011 nnnn
0 1111 nnnn
0 1111 s0mm load64
0 1111 s1mm store64
0 1111 n000
1 0ooo ttss mathops
1 011r tuss shiftops
@ -211,6 +213,20 @@ jump_formats = {
"jump_widths": [ "0, 0", "1, 1", "1, 0", "1, 1" ]
},
}
load64_formats = {
"opcode": "OP_LOAD64_{op_mode[mm]}_{s+3}",
"mnemonic": "load64",
"opname": "load64",
"format": "{load_fmt[mm]}, %gc",
"widths": "{load_widths[s+2][mm]}, {s+3}",
"types": "{load_types[mm]}, ev_void",
"args": {
"op_mode": address_mode,
"load_fmt": load_fmt,
"load_types": address_types,
"load_widths": address_widths,
},
}
lea_formats = {
"opcode": "OP_LEA_{op_mode[mm]}",
"mnemonic": "lea",
@ -401,6 +417,21 @@ store_formats = {
"store_widths": address_widths,
},
}
store64_formats = {
"opcode": "OP_STORE64_{op_mode[mm]}_{s+3}",
"mnemonic": "{store_op[mm]}64",
"opname": "{store_op[mm]}64",
"format": "%Gc, {store_fmt[mm]}",
"widths": "{store_widths[s+2][mm]}, {s+3}",
"types": "{store_types[mm]}, ev_void",
"args": {
"op_mode": address_mode,
"store_fmt": store_fmt,
"store_op": ["assign", "store", "store", "store"],
"store_types": address_types,
"store_widths": address_widths,
},
}
string_formats = {
"opcode": "OP_{op_str[o*4+oo].upper()}_S",
"mnemonic": "{op_str[o*4+oo]}.s",
@ -509,6 +540,7 @@ group_map = {
"jump": jump_formats,
"lea": lea_formats,
"load": load_formats,
"load64": load64_formats,
"mathops": mathops_formats,
"memset": memset_formats,
"move": move_formats,
@ -520,6 +552,7 @@ group_map = {
"statef": statef_formats,
"stated": stated_formats,
"store": store_formats,
"store64": store64_formats,
"string": string_formats,
"swizzle": swizzle_formats,
"return": return_formats,

View file

@ -2978,6 +2978,32 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
// 0 1110
OP_cmp(LE, <=);
// 0 1111
case OP_LOAD64_B_3:
case OP_LOAD64_C_3:
case OP_LOAD64_D_3:
mm = pr_address_mode (pr, st, (st_op - OP_LOAD64_B_3 + 1));
VectorCopy (&MM(long), &OPC(long));
break;
case OP_STORE64_A_3:
case OP_STORE64_B_3:
case OP_STORE64_C_3:
case OP_STORE64_D_3:
mm = pr_address_mode (pr, st, (st_op - OP_STORE64_A_3));
VectorCopy (&OPC(long), &MM(long));
break;
case OP_LOAD64_B_4:
case OP_LOAD64_C_4:
case OP_LOAD64_D_4:
mm = pr_address_mode (pr, st, (st_op - OP_LOAD64_B_4 + 1));
OPC(lvec4) = MM(lvec4);
break;
case OP_STORE64_A_4:
case OP_STORE64_B_4:
case OP_STORE64_C_4:
case OP_STORE64_D_4:
mm = pr_address_mode (pr, st, (st_op - OP_STORE64_A_4));
MM(lvec4) = OPC(lvec4);
break;
// spare
#define OP_op_1(OP, T, t, op) \

View file

@ -17,12 +17,14 @@ libs_gamecode_tests = \
libs/gamecode/test/test-jump \
libs/gamecode/test/test-lea \
libs/gamecode/test/test-load \
libs/gamecode/test/test-load64 \
libs/gamecode/test/test-long \
libs/gamecode/test/test-mem \
libs/gamecode/test/test-scale \
libs/gamecode/test/test-stack \
libs/gamecode/test/test-state \
libs/gamecode/test/test-store \
libs/gamecode/test/test-store64 \
libs/gamecode/test/test-string \
libs/gamecode/test/test-swizzle \
libs/gamecode/test/test-unsigned \
@ -129,6 +131,11 @@ libs_gamecode_test_test_load_SOURCES= \
libs_gamecode_test_test_load_LDADD= $(test_gamecode_libs)
libs_gamecode_test_test_load_DEPENDENCIES= $(test_gamecode_libs)
libs_gamecode_test_test_load64_SOURCES= \
libs/gamecode/test/test-load64.c
libs_gamecode_test_test_load64_LDADD= $(test_gamecode_libs)
libs_gamecode_test_test_load64_DEPENDENCIES=$(test_gamecode_libs)
libs_gamecode_test_test_long_SOURCES= \
libs/gamecode/test/test-long.c
libs_gamecode_test_test_long_LDADD= $(test_gamecode_libs)
@ -158,6 +165,11 @@ libs_gamecode_test_test_store_SOURCES= \
libs_gamecode_test_test_store_LDADD= $(test_gamecode_libs)
libs_gamecode_test_test_store_DEPENDENCIES= $(test_gamecode_libs)
libs_gamecode_test_test_store64_SOURCES= \
libs/gamecode/test/test-store64.c
libs_gamecode_test_test_store64_LDADD= $(test_gamecode_libs)
libs_gamecode_test_test_store64_DEPENDENCIES= $(test_gamecode_libs)
libs_gamecode_test_test_string_SOURCES= \
libs/gamecode/test/test-string.c
libs_gamecode_test_test_string_LDADD= $(test_gamecode_libs)

View file

@ -0,0 +1,89 @@
#include "head.c"
static pr_int_t test_globals_init[] = {
// pointers
24, 26, 48, 29,
32, -8, -4, 0,
2, 8, 0xdeadbeef, 0xfeedf00d,
0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d,
// destination data
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
// source data
21, 22, 23, 24, 17, 18, 19, 20,
15, 16, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8,
};
static pr_int_t test_globals_expect[] = {
// pointers
24, 26, 48, 29,
32, -8, -4, 0,
2, 8, 0xdeadbeef, 0xfeedf00d,
0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d,
// destination data
/*16*/ 1, 2, 3, 4, 5, 6, 7, 8,
/*24*/ 9, 10, 11, 12, 13, 14, 15, 16,
/*32*/ 17, 18, 19, 20, 21, 22, 23, 24,
// source data
/*40*/ 21, 22, 23, 24, 17, 18, 19, 20,
/*48*/ 15, 16, 9, 10, 11, 12, 13, 14,
/*56*/ 1, 2, 3, 4, 5, 6, 7, 8,
};
static dstatement_t load64_B_statements[] = {
{OP(0, 0, 0, OP_LOAD64_B_4), 7, 9, 16},
{OP(0, 0, 0, OP_LOAD64_B_3), 7, 8, 24},
{OP(0, 0, 0, OP_LOAD_B_2), 7, 7, 30},
{OP(0, 0, 0, OP_LOAD_B_4), 7, 6, 32},
{OP(0, 0, 0, OP_LOAD_B_4), 7, 5, 36},
};
static dstatement_t load64_C_statements[] = {
{OP(0, 0, 0, OP_LOAD64_C_4), 2, 8, 16},
{OP(0, 0, 0, OP_LOAD64_C_3), 2, 2, 24},
{OP(0, 0, 0, OP_LOAD_C_2), 2, 0, 30},
{OP(0, 0, 0, OP_LOAD_C_4), 2, -4, 32},
{OP(0, 0, 0, OP_LOAD_C_4), 2, -8, 36},
};
static dstatement_t load64_D_statements[] = {
{OP(0, 0, 0, OP_LOAD64_D_4), 2, 9, 16},
{OP(0, 0, 0, OP_LOAD64_D_3), 2, 8, 24},
{OP(0, 0, 0, OP_LOAD_D_2), 2, 7, 30},
{OP(0, 0, 0, OP_LOAD_D_4), 2, 6, 32},
{OP(0, 0, 0, OP_LOAD_D_4), 2, 5, 36},
};
test_t tests[] = {
{
.desc = "load64 B",
.num_globals = num_globals (test_globals_init, test_globals_expect),
.num_statements = num_statements (load64_B_statements),
.statements = load64_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 = 48,
},
{
.desc = "load64 C",
.num_globals = num_globals (test_globals_init, test_globals_expect),
.num_statements = num_statements (load64_C_statements),
.statements = load64_C_statements,
.init_globals = test_globals_init,
.expect_globals = test_globals_expect,
},
{
.desc = "load64 D",
.num_globals = num_globals (test_globals_init, test_globals_expect),
.num_statements = num_statements (load64_D_statements),
.statements = load64_D_statements,
.init_globals = test_globals_init,
.expect_globals = test_globals_expect,
},
};
#include "main.c"

View file

@ -0,0 +1,105 @@
#include "head.c"
static pr_int_t test_globals_init[] = {
// pointers
24, 26, 48, 29,
32, -8, -4, 0,
2, 8, 0xdeadbeef, 0xfeedf00d,
0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d,
// source data
/*16*/ 1, 2, 3, 4, 5, 6, 7, 8,
/*24*/ 9, 10, 11, 12, 13, 14, 15, 16,
/*32*/ 17, 18, 19, 20, 21, 22, 23, 24,
// destination data
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
static pr_int_t test_globals_expect[] = {
// pointers
24, 26, 48, 29,
32, -8, -4, 0,
2, 8, 0xdeadbeef, 0xfeedf00d,
0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d,
// source data
/*16*/ 1, 2, 3, 4, 5, 6, 7, 8,
/*24*/ 9, 10, 11, 12, 13, 14, 15, 16,
/*32*/ 17, 18, 19, 20, 21, 22, 23, 24,
// destination data
/*40*/ 21, 22, 23, 24, 17, 18, 19, 20,
/*48*/ 15, 16, 9, 10, 11, 12, 13, 14,
/*56*/ 1, 2, 3, 4, 5, 6, 7, 8,
};
static dstatement_t store64_A_statements[] = {
{OP(0, 0, 0, OP_STORE64_A_4), 56, 0, 16},
{OP(0, 0, 0, OP_STORE64_A_3), 50, 0, 24},
{OP(0, 0, 0, OP_STORE_A_2), 48, 0, 30},
{OP(0, 0, 0, OP_STORE_A_4), 44, 0, 32},
{OP(0, 0, 0, OP_STORE_A_4), 40, 0, 36},
};
static dstatement_t store64_B_statements[] = {
{OP(0, 0, 0, OP_STORE64_B_4), 7, 9, 16},
{OP(0, 0, 0, OP_STORE64_B_3), 7, 8, 24},
{OP(0, 0, 0, OP_STORE_B_2), 7, 7, 30},
{OP(0, 0, 0, OP_STORE_B_4), 7, 6, 32},
{OP(0, 0, 0, OP_STORE_B_4), 7, 5, 36},
};
static dstatement_t store64_C_statements[] = {
{OP(0, 0, 0, OP_STORE64_C_4), 2, 8, 16},
{OP(0, 0, 0, OP_STORE64_C_3), 2, 2, 24},
{OP(0, 0, 0, OP_STORE_C_2), 2, 0, 30},
{OP(0, 0, 0, OP_STORE_C_4), 2, -4, 32},
{OP(0, 0, 0, OP_STORE_C_4), 2, -8, 36},
};
static dstatement_t store64_D_statements[] = {
{OP(0, 0, 0, OP_STORE64_D_4), 2, 9, 16},
{OP(0, 0, 0, OP_STORE64_D_3), 2, 8, 24},
{OP(0, 0, 0, OP_STORE_D_2), 2, 7, 30},
{OP(0, 0, 0, OP_STORE_D_4), 2, 6, 32},
{OP(0, 0, 0, OP_STORE_D_4), 2, 5, 36},
};
test_t tests[] = {
{
.desc = "store64 A",
.num_globals = num_globals (test_globals_init, test_globals_expect),
.num_statements = num_statements (store64_A_statements),
.statements = store64_A_statements,
.init_globals = test_globals_init,
.expect_globals = test_globals_expect,
},
{
.desc = "store64 B",
.num_globals = num_globals (test_globals_init, test_globals_expect),
.num_statements = num_statements (store64_B_statements),
.statements = store64_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 = 48,
},
{
.desc = "store64 C",
.num_globals = num_globals (test_globals_init, test_globals_expect),
.num_statements = num_statements (store64_C_statements),
.statements = store64_C_statements,
.init_globals = test_globals_init,
.expect_globals = test_globals_expect,
},
{
.desc = "store64 D",
.num_globals = num_globals (test_globals_init, test_globals_expect),
.num_statements = num_statements (store64_D_statements),
.statements = store64_D_statements,
.init_globals = test_globals_init,
.expect_globals = test_globals_expect,
},
};
#include "main.c"