diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 79e1949d9..b9c316a1d 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -11,7 +11,7 @@ bitmap_txt = """ 0 1011 otss udivops 0 1111 s0mm load64 0 1111 s1mm store64 -0 1111 n000 +0 1111 m000 lea2 1 0ooo ttss mathops 1 011r tuss shiftops @@ -46,20 +46,24 @@ address_types = [ "ev_entity, ev_field", "ev_ptr, ev_short", "ev_ptr, ev_int", + "ev_void, ev_short", + "ev_void, ev_int", ] address_widths = [ [ "1, 0", "1, 1", "1, 0", "1, 1", ], [ "2, 0", "1, 1", "1, 0", "1, 1", ], [ "3, 0", "1, 1", "1, 0", "1, 1", ], [ "4, 0", "1, 1", "1, 0", "1, 1", ], - [ "-1, 0", "1, 1", "1, 0", "1, 1", ], + [ "-1, 0", "1, 1", "1, 0", "1, 1", "-1, 0", "-1, 1"], ] -#store, pop and lea +#store, pop, lea store_fmt = [ "%ga", "%Ga.%Gb(%Ea)", "*(%Ga + %sb)", "*(%Ga + %Gb)", + "%ga + %sb", + "%ga + %Gb", ] # load and push load_fmt = [ @@ -267,6 +271,20 @@ lea_formats = { "lea_widths": address_widths[4], }, } +lea2_formats = { + "opcode": "OP_LEA_{op_mode[m]}", + "mnemonic": "lea", + "opname": "lea", + "format": "{lea_fmt[m+4]}, %gc", + "widths": "{lea_widths[m+4]}, 1", + "types": "{lea_types[m+4]}, ev_ptr", + "args": { + "op_mode": "EF", + "lea_fmt": store_fmt, + "lea_types": address_types, + "lea_widths": address_widths[4], + }, +} load_formats = { "opcode": "OP_LOAD_{op_mode[mm]}_{ss+1}", "mnemonic": "load", @@ -579,6 +597,7 @@ group_map = { "hops": hops_formats, "jump": jump_formats, "lea": lea_formats, + "lea2": lea2_formats, "load": load_formats, "load64": load64_formats, "mathops": mathops_formats, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index ee7c100f1..639416c37 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1812,6 +1812,14 @@ 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: + // global access with constant offset (supports -ve offset) + mm_offs = op_a - pr->pr_globals + (short) st->b; + break; + case 5: + // global access with variable offset (supports -ve offset) + mm_offs = op_a - pr->pr_globals + OPB(int); + break; } return pr->pr_globals + mm_offs; } @@ -2346,6 +2354,10 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) // 0 1110 OP_cmp(LE, <=); // 0 1111 + case OP_LEA_E: + mm = pr_address_mode (pr, st, 4); + OPC(ptr) = mm - pr->pr_globals; + break; case OP_LOAD64_B_3: case OP_LOAD64_C_3: case OP_LOAD64_D_3: @@ -2359,6 +2371,10 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) mm = pr_address_mode (pr, st, (st_op - OP_STORE64_A_3)); VectorCopy (&OPC(long), &MM(long)); break; + case OP_LEA_F: + mm = pr_address_mode (pr, st, 5); + OPC(ptr) = mm - pr->pr_globals; + break; case OP_LOAD64_B_4: case OP_LOAD64_C_4: case OP_LOAD64_D_4: @@ -2372,7 +2388,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) mm = pr_address_mode (pr, st, (st_op - OP_STORE64_A_4)); MM(lvec4) = OPC(lvec4); break; - // spare #define OP_op(OP, op) \ OP_op_T (OP, I, int, ivec2, ivec4, op); \ diff --git a/libs/gamecode/test/test-lea.c b/libs/gamecode/test/test-lea.c index 33e148c16..a99702144 100644 --- a/libs/gamecode/test/test-lea.c +++ b/libs/gamecode/test/test-lea.c @@ -13,7 +13,7 @@ static pr_int_t lea_globals_expect[] = { // pointers 24, 26, 28, 29, 32, -4, -2, 0, - 1, 4, 0xdeadbeef, 0xfeedf00d, + 1, 4, 6, 32, 7, 34, 26, 88, }; @@ -23,6 +23,8 @@ static dstatement_t lea_statements[] = { {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_B), 4, 2, 15}, + {OP(0, 0, 0, OP_LEA_E), 4, 2, 10}, + {OP(0, 0, 0, OP_LEA_F), 4, 2, 11}, }; test_t tests[] = {