diff --git a/erlang/apps/sim/src/sim_arithmetic.erl b/erlang/apps/sim/src/sim_arithmetic.erl index dffa5ac..8070cd9 100644 --- a/erlang/apps/sim/src/sim_arithmetic.erl +++ b/erlang/apps/sim/src/sim_arithmetic.erl @@ -47,6 +47,14 @@ , handle_JUMPL/4 , handle_JUMPLE/4 , handle_JUMPN/4 + , handle_SKIP/4 + , handle_SKIPA/4 + , handle_SKIPE/4 + , handle_SKIPG/4 + , handle_SKIPGE/4 + , handle_SKIPL/4 + , handle_SKIPLE/4 + , handle_SKIPN/4 ]). -include("sim_core.hrl"). @@ -290,6 +298,96 @@ handle_JUMPG(Core, Mem, IR, EA) -> CA = sim_core:get_ac(Core, AC), jump_if_G(Core, Mem, CA, EA). +%% SKIP - Skip if Memory Condition Satisfied + +-spec handle_SKIP(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SKIP(Core, Mem, IR, EA) -> + case sim_core:c(Core, Mem, EA) of + {ok, CE} -> + sim_core:next_pc(set_non_zero_ac(Core, IR, CE), Mem); + {error, Reason} -> + sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason, + fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end) + end. + +-spec handle_SKIPL(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SKIPL(Core, Mem, IR, EA) -> + case sim_core:c(Core, Mem, EA) of + {ok, CE} -> + skip_if_L(set_non_zero_ac(Core, IR, CE), Mem, sext36(CE), 0); + {error, Reason} -> + sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason, + fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end) + end. + +-spec handle_SKIPE(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SKIPE(Core, Mem, IR, EA) -> + case sim_core:c(Core, Mem, EA) of + {ok, CE} -> + skip_if_E(set_non_zero_ac(Core, IR, CE), Mem, CE, 0); + {error, Reason} -> + sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason, + fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end) + end. + +-spec handle_SKIPLE(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SKIPLE(Core, Mem, IR, EA) -> + case sim_core:c(Core, Mem, EA) of + {ok, CE} -> + skip_if_LE(set_non_zero_ac(Core, IR, CE), Mem, sext36(CE), 0); + {error, Reason} -> + sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason, + fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end) + end. + +-spec handle_SKIPA(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SKIPA(Core, Mem, IR, EA) -> + case sim_core:c(Core, Mem, EA) of + {ok, CE} -> + sim_core:skip(set_non_zero_ac(Core, IR, CE), Mem); + {error, Reason} -> + sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason, + fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end) + end. + +-spec handle_SKIPGE(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SKIPGE(Core, Mem, IR, EA) -> + case sim_core:c(Core, Mem, EA) of + {ok, CE} -> + skip_if_LE(set_non_zero_ac(Core, IR, CE), Mem, 0, sext36(CE)); % C(E) >= 0 -> 0 =< C(E) + {error, Reason} -> + sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason, + fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end) + end. + +-spec handle_SKIPN(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SKIPN(Core, Mem, IR, EA) -> + case sim_core:c(Core, Mem, EA) of + {ok, CE} -> + skip_if_N(set_non_zero_ac(Core, IR, CE), Mem, CE, 0); + {error, Reason} -> + sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason, + fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end) + end. + +-spec handle_SKIPG(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SKIPG(Core, Mem, IR, EA) -> + case sim_core:c(Core, Mem, EA) of + {ok, CE} -> + skip_if_L(set_non_zero_ac(Core, IR, CE), Mem, 0, sext36(CE)); % C(E) > 0 -> 0 < C(E) + {error, Reason} -> + sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason, + fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end) + end. + %% Miscellaneous =============================================================== jump_if_E(Core, Mem, X, EA) -> @@ -362,5 +460,11 @@ sext36(X) -> UInt36Max = (1 bsl 36) - 1, ((X band UInt36Max) bxor UInt36Sbit) - UInt36Sbit. +set_non_zero_ac(Core, IR, Word) -> + case IR band 8#17 of + 0 -> Core; + AC -> sim_core:set_ac(Core, AC, Word) + end. + ea_address(#ea{section = Section, offset = Offset}) -> (Section bsl 18) bor Offset. diff --git a/erlang/apps/sim/src/sim_core.erl b/erlang/apps/sim/src/sim_core.erl index 0553b6e..e6d1ca2 100644 --- a/erlang/apps/sim/src/sim_core.erl +++ b/erlang/apps/sim/src/sim_core.erl @@ -312,6 +312,14 @@ dispatch(Core, Mem, IR, EA) -> 8#325 -> sim_arithmetic:handle_JUMPGE(Core, Mem, IR, EA); 8#326 -> sim_arithmetic:handle_JUMPN(Core, Mem, IR, EA); 8#327 -> sim_arithmetic:handle_JUMPG(Core, Mem, IR, EA); + 8#330 -> sim_arithmetic:handle_SKIP(Core, Mem, IR, EA); + 8#331 -> sim_arithmetic:handle_SKIPL(Core, Mem, IR, EA); + 8#332 -> sim_arithmetic:handle_SKIPE(Core, Mem, IR, EA); + 8#333 -> sim_arithmetic:handle_SKIPLE(Core, Mem, IR, EA); + 8#334 -> sim_arithmetic:handle_SKIPA(Core, Mem, IR, EA); + 8#335 -> sim_arithmetic:handle_SKIPGE(Core, Mem, IR, EA); + 8#336 -> sim_arithmetic:handle_SKIPN(Core, Mem, IR, EA); + 8#337 -> sim_arithmetic:handle_SKIPG(Core, Mem, IR, EA); 8#400 -> sim_boolean:handle_SETZ(Core, Mem, IR, EA); 8#401 -> sim_boolean:handle_SETZ(Core, Mem, IR, EA); % SETZI = SETZ 8#402 -> sim_boolean:handle_SETZM(Core, Mem, IR, EA); diff --git a/erlang/apps/sim/test/sim_arithmetic_tests.erl b/erlang/apps/sim/test/sim_arithmetic_tests.erl index fe28303..fab7802 100644 --- a/erlang/apps/sim/test/sim_arithmetic_tests.erl +++ b/erlang/apps/sim/test/sim_arithmetic_tests.erl @@ -75,6 +75,14 @@ -define(OP_JUMPGE, 8#325). -define(OP_JUMPN, 8#326). -define(OP_JUMPG, 8#327). +-define(OP_SKIP, 8#330). +-define(OP_SKIPL, 8#331). +-define(OP_SKIPE, 8#332). +-define(OP_SKIPLE, 8#333). +-define(OP_SKIPA, 8#334). +-define(OP_SKIPGE, 8#335). +-define(OP_SKIPN, 8#336). +-define(OP_SKIPG, 8#337). %% 2.6.1 Add One to Both Halves of AC and Jump ================================= @@ -521,6 +529,151 @@ jumpg_test() -> ], expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no jump +%% SKIP - Skip if Memory Condition Satisfied + +skip_test() -> + Prog = + [ {1, 8#100, ?INSN(?OP_MOVEI, 0, 0, 0, 8#42)} % 1,,100/ MOVEI 0,42 + , {1, 8#101, ?INSN(?OP_SKIP, 0, 0, 0, 8#150)} % 1,,101/ SKIP 150 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 2} % 1,,150/ 2 + ], + expect(Prog, [], {1, 8#102}, ?DEFAULT_FLAGS, % no skip + [{?AC(0), 8#42}]). % AC(0) = 42 + +skipl_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_SKIPL, 1, 0, 0, 8#150)} % 1,,100/ SKIPL 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, ?LOW36(-2)} % 1,,150/ -2 + ], + expect(Prog1, [], {1, 8#102}, ?DEFAULT_FLAGS, % skip + [{?AC(1), ?LOW36(-2)}]), % AC1 = -2 + Prog2 = + [ {1, 8#100, ?INSN(?OP_SKIPL, 1, 0, 0, 8#150)} % 1,,100/ SKIPL 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 2} % 1,,150/ 2 + ], + expect(Prog2, [], {1, 8#101}, ?DEFAULT_FLAGS, % no skip + [{?AC(1), 2}]). % AC1 = 2 + +skipe_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_SKIPE, 1, 0, 0, 8#150)} % 1,,100/ SKIPE 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 0} % 1,,150/ 0 + ], + expect(Prog1, [], {1, 8#102}, ?DEFAULT_FLAGS, []), % skip + Prog2 = + [ {1, 8#100, ?INSN(?OP_SKIPE, 1, 0, 0, 8#150)} % 1,,100/ SKIPE 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 2} % 1,,150/ 0,,2 + ], + expect(Prog2, [], {1, 8#101}, ?DEFAULT_FLAGS, % no skip + [{?AC(1), 2}]). % AC1 = 2 + +skiple_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_SKIPLE, 1, 0, 0, 8#150)} % 1,,100/ SKIPLE 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, ?LOW36(-2)} % 1,,150/ -2 + ], + expect(Prog1, [], {1, 8#102}, ?DEFAULT_FLAGS, % + [{?AC(1), ?LOW36(-2)}]), % AC1 = -2 + Prog2 = + [ {1, 8#100, ?INSN(?OP_SKIPLE, 1, 0, 0, 8#150)} % 1,,100/ SKIPLE 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 0} % 1,,150/ 0 + ], + expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, % skip + [{?AC(1), 0}]), % AC1 = 0 + Prog3 = + [ {1, 8#100, ?INSN(?OP_SKIPLE, 1, 0, 0, 8#150)} % 1,,100/ SKIPLE 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 2} % 1,,150/ 2 + ], + expect(Prog3, [], {1, 8#101}, ?DEFAULT_FLAGS, % no skip + [{?AC(1), 2}]). % AC1 = 2 + +skipa_test() -> + Prog = + [ {1, 8#100, ?INSN(?OP_SKIPA, 1, 0, 0, 8#150)} % 1,,100/ SKIPA 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 2} % 1,,150/ 2 + ], + expect(Prog, [], {1, 8#102}, ?DEFAULT_FLAGS, % skip + [{?AC(1), 2}]). % AC1 = 2 + +skipge_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_SKIPGE, 1, 0, 0, 8#150)} % 1,,100/ SKIPGE 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 2} % 1,,150/ 2 + ], + expect(Prog1, [], {1, 8#102}, ?DEFAULT_FLAGS, % skip + [{?AC(1), 2}]), % AC1 = 2 + Prog2 = + [ {1, 8#100, ?INSN(?OP_SKIPGE, 1, 0, 0, 8#150)} % 1,,100/ SKIPGE 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 0} % 1,,150/ 0 + ], + expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, % skip + [{?AC(1), 0}]), % AC1 = 0 + Prog3 = + [ {1, 8#100, ?INSN(?OP_SKIPGE, 1, 0, 0, 8#150)} % 1,,100/ SKIPGE 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, ?LOW36(-2)} % 1,,150/ -2 + ], + expect(Prog3, [], {1, 8#101}, ?DEFAULT_FLAGS, % no skip + [{?AC(1), ?LOW36(-2)}]). % AC1 = -2 + +skipn_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_SKIPN, 1, 0, 0, 8#150)} % 1,,100/ SKIPN 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 2} % 1,,150/ 2 + ], + expect(Prog1, [], {1, 8#102}, ?DEFAULT_FLAGS, % skip + [{?AC(1), 2}]), % AC(1) = 2 + Prog2 = + [ {1, 8#100, ?INSN(?OP_SKIPN, 1, 0, 0, 8#150)} % 1,,100/ SKIPN 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 0} % 1,,150/ 0 + ], + expect(Prog2, [], {1, 8#101}, ?DEFAULT_FLAGS, % no skip + [{?AC(1), 0}]). % AC(1) = 0 + +skipg_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_SKIPG, 1, 0, 0, 8#150)} % 1,,100/ SKIPG 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, 2} % 1,,150/ 2 + ], + expect(Prog1, [], {1, 8#102}, ?DEFAULT_FLAGS, % skip + [{?AC(1), 2}]), % AC(1) = 2 + Prog2 = + [ {1, 8#100, ?INSN(?OP_SKIPG, 1, 0, 0, 8#150)} % 1,,100/ SKIPG 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#150, ?LOW36(-2)} % 1,,150/ -2 + ], + expect(Prog2, [], {1, 8#101}, ?DEFAULT_FLAGS, % no skip + [{?AC(1), ?LOW36(-2)}]). % AC(1) = -2 + %% Common code to run short sequences ========================================== expect(Prog, ACs, ExpectedPC, ExpectedFlags, ExpectedEs) ->