From 1f2c56260fb5b0e8fbc76e71919dd4e3273962d2 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Sun, 2 Aug 2020 23:58:55 +0200 Subject: [PATCH] sim: sim_arithmetic: handle JUMP{L,E,LE,A,GE,N,G}, sim_core: handle JUMP as no-op, add unit tests --- erlang/apps/sim/src/sim_arithmetic.erl | 92 ++++++++++++ erlang/apps/sim/src/sim_core.erl | 8 ++ erlang/apps/sim/test/sim_arithmetic_tests.erl | 135 ++++++++++++++++++ 3 files changed, 235 insertions(+) diff --git a/erlang/apps/sim/src/sim_arithmetic.erl b/erlang/apps/sim/src/sim_arithmetic.erl index c36b542..dffa5ac 100644 --- a/erlang/apps/sim/src/sim_arithmetic.erl +++ b/erlang/apps/sim/src/sim_arithmetic.erl @@ -40,6 +40,13 @@ , handle_CAML/4 , handle_CAMLE/4 , handle_CAMN/4 + , handle_JUMPA/4 + , handle_JUMPE/4 + , handle_JUMPG/4 + , handle_JUMPGE/4 + , handle_JUMPL/4 + , handle_JUMPLE/4 + , handle_JUMPN/4 ]). -include("sim_core.hrl"). @@ -234,8 +241,93 @@ handle_CAMG(Core, Mem, IR, EA) -> fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end) end. +%% JUMP - Jump if AC Condition Satisfied + +-spec handle_JUMPL(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_JUMPL(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + jump_if_L(Core, Mem, CA, EA). + +-spec handle_JUMPE(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_JUMPE(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + jump_if_E(Core, Mem, CA, EA). + +-spec handle_JUMPLE(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_JUMPLE(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + jump_if_LE(Core, Mem, CA, EA). + +-spec handle_JUMPA(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_JUMPA(Core, Mem, _IR, EA) -> + jump(Core, Mem, EA). + +-spec handle_JUMPGE(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_JUMPGE(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + jump_if_GE(Core, Mem, CA, EA). + +-spec handle_JUMPN(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_JUMPN(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + jump_if_N(Core, Mem, CA, EA). + +-spec handle_JUMPG(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_JUMPG(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + jump_if_G(Core, Mem, CA, EA). + %% Miscellaneous =============================================================== +jump_if_E(Core, Mem, X, EA) -> + case X =:= 0 of + true -> jump(Core, Mem, EA); + false -> sim_core:next_pc(Core, Mem) + end. + +jump_if_G(Core, Mem, X, EA) -> + case sext36(X) > 0 of + true -> jump(Core, Mem, EA); + false -> sim_core:next_pc(Core, Mem) + end. + +jump_if_GE(Core, Mem, X, EA) -> + case sext36(X) >= 0 of + true -> jump(Core, Mem, EA); + false -> sim_core:next_pc(Core, Mem) + end. + +jump_if_L(Core, Mem, X, EA) -> + case sext36(X) < 0 of + true -> jump(Core, Mem, EA); + false -> sim_core:next_pc(Core, Mem) + end. + +jump_if_LE(Core, Mem, X, EA) -> + case sext36(X) =< 0 of + true -> jump(Core, Mem, EA); + false -> sim_core:next_pc(Core, Mem) + end. + +jump_if_N(Core, Mem, X, EA) -> + case X =/= 0 of + true -> jump(Core, Mem, EA); + false -> sim_core:next_pc(Core, Mem) + end. + jump(Core, Mem, EA) -> sim_core:run(Core#core{pc_offset = EA#ea.offset}, Mem). diff --git a/erlang/apps/sim/src/sim_core.erl b/erlang/apps/sim/src/sim_core.erl index 2d57bbf..0553b6e 100644 --- a/erlang/apps/sim/src/sim_core.erl +++ b/erlang/apps/sim/src/sim_core.erl @@ -304,6 +304,14 @@ dispatch(Core, Mem, IR, EA) -> 8#315 -> sim_arithmetic:handle_CAMGE(Core, Mem, IR, EA); 8#316 -> sim_arithmetic:handle_CAMN(Core, Mem, IR, EA); 8#317 -> sim_arithmetic:handle_CAMG(Core, Mem, IR, EA); + 8#320 -> next_pc(Core, Mem); % JUMP = no-op + 8#321 -> sim_arithmetic:handle_JUMPL(Core, Mem, IR, EA); + 8#322 -> sim_arithmetic:handle_JUMPE(Core, Mem, IR, EA); + 8#323 -> sim_arithmetic:handle_JUMPLE(Core, Mem, IR, EA); + 8#324 -> sim_arithmetic:handle_JUMPA(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#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 4ca24c7..fe28303 100644 --- a/erlang/apps/sim/test/sim_arithmetic_tests.erl +++ b/erlang/apps/sim/test/sim_arithmetic_tests.erl @@ -67,6 +67,14 @@ -define(OP_CAMGE, 8#315). -define(OP_CAMN, 8#316). -define(OP_CAMG, 8#317). +-define(OP_JUMP, 8#320). +-define(OP_JUMPL, 8#321). +-define(OP_JUMPE, 8#322). +-define(OP_JUMPLE, 8#323). +-define(OP_JUMPA, 8#324). +-define(OP_JUMPGE, 8#325). +-define(OP_JUMPN, 8#326). +-define(OP_JUMPG, 8#327). %% 2.6.1 Add One to Both Halves of AC and Jump ================================= @@ -386,6 +394,133 @@ camg_test() -> ], expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no skip +%% JUMP - Jump if AC Condition Satisfied + +jump_test() -> + Prog = + [ {1, 8#100, ?INSN(?OP_JUMP, 0, 0, 0, 0)} % 1,,100/ JUMP + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + ], + expect(Prog, [], {1, 8#101}, ?DEFAULT_FLAGS, []). % no jump + +jumpl_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVNI, 1, 0, 0, 3)} % 1,,100/ MOVNI 1,3 + , {1, 8#101, ?INSN(?OP_JUMPL, 1, 0, 0, 8#103)} % 1,,101/ JUMPL 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % jump + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3 + , {1, 8#101, ?INSN(?OP_JUMPL, 1, 0, 0, 8#103)} % 1,,101/ JUMPL 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no jump + +jumpe_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 0)} % 1,,100/ MOVEI 1,0 + , {1, 8#101, ?INSN(?OP_JUMPE, 1, 0, 0, 8#103)} % 1,,101/ JUMPE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % jump + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3 + , {1, 8#101, ?INSN(?OP_JUMPE, 1, 0, 0, 8#103)} % 1,,101/ JUMPE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no jump + +jumple_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVNI, 1, 0, 0, 3)} % 1,,100/ MOVNI 1,3 + , {1, 8#101, ?INSN(?OP_JUMPLE, 1, 0, 0, 8#103)} % 1,,101/ JUMPLE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % jump + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 0)} % 1,,100/ MOVEI 1,0 + , {1, 8#101, ?INSN(?OP_JUMPLE, 1, 0, 0, 8#103)} % 1,,101/ JUMPLE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % jump + Prog3 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3 + , {1, 8#101, ?INSN(?OP_JUMPLE, 1, 0, 0, 8#103)} % 1,,101/ JUMPLE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog3, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no jump + +jumpa_test() -> + Prog = + [ {1, 8#100, ?INSN(?OP_JUMPA, 0, 0, 0, 8#102)} % 1,,100/ JUMPA 102 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + ], + expect(Prog, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % jump + +jumpge_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3 + , {1, 8#101, ?INSN(?OP_JUMPGE, 1, 0, 0, 8#103)} % 1,,101/ JUMPGE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % jump + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 0)} % 1,,100/ MOVEI 1,0 + , {1, 8#101, ?INSN(?OP_JUMPGE, 1, 0, 0, 8#103)} % 1,,101/ JUMPGE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % jump + Prog3 = + [ {1, 8#100, ?INSN(?OP_MOVNI, 1, 0, 0, 3)} % 1,,100/ MOVNI 1,3 + , {1, 8#101, ?INSN(?OP_JUMPGE, 1, 0, 0, 8#103)} % 1,,101/ JUMPGE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog3, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no jump + +jumpn_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3 + , {1, 8#101, ?INSN(?OP_JUMPN, 1, 0, 0, 8#103)} % 1,,101/ JUMPN 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % jump + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 0)} % 1,,100/ MOVEI 1,0 + , {1, 8#101, ?INSN(?OP_JUMPN, 1, 0, 0, 8#103)} % 1,,101/ JUMPN 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no jump + +jumpg_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3 + , {1, 8#101, ?INSN(?OP_JUMPG, 1, 0, 0, 8#103)} % 1,,101/ JUMPG 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % jump + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVNI, 1, 0, 0, 3)} % 1,,100/ MOVNI 1,3 + , {1, 8#101, ?INSN(?OP_JUMPG, 1, 0, 0, 8#103)} % 1,,101/ JUMPG 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no jump + %% Common code to run short sequences ========================================== expect(Prog, ACs, ExpectedPC, ExpectedFlags, ExpectedEs) ->