diff --git a/erlang/apps/sim/src/sim_arithmetic.erl b/erlang/apps/sim/src/sim_arithmetic.erl index 37fc5cd..5d3f63e 100644 --- a/erlang/apps/sim/src/sim_arithmetic.erl +++ b/erlang/apps/sim/src/sim_arithmetic.erl @@ -71,6 +71,14 @@ , handle_SKIPL/4 , handle_SKIPLE/4 , handle_SKIPN/4 + , handle_SOJ/4 + , handle_SOJA/4 + , handle_SOJE/4 + , handle_SOJG/4 + , handle_SOJGE/4 + , handle_SOJL/4 + , handle_SOJLE/4 + , handle_SOJN/4 ]). -include("sim_core.hrl"). @@ -656,6 +664,72 @@ handle_AOSG(Core, Mem, IR, EA, Word, Flags) -> fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA, Word, Flags) end) end. +%% SOJ - Subtract One from AC and Jump if Condition Satisfied + +-spec handle_SOJ(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SOJ(Core, Mem, IR, _EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + {Word, Flags} = sub1(CA), + sim_core:next_pc(sim_core:set_flags(sim_core:set_ac(Core, AC, Word), Flags), Mem). + +-spec handle_SOJL(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SOJL(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + {Word, Flags} = sub1(CA), + jump_if_L(sim_core:set_flags(sim_core:set_ac(Core, AC, Word), Flags), Mem, Word, EA). + +-spec handle_SOJE(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SOJE(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + {Word, Flags} = sub1(CA), + jump_if_E(sim_core:set_flags(sim_core:set_ac(Core, AC, Word), Flags), Mem, Word, EA). + +-spec handle_SOJLE(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SOJLE(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + {Word, Flags} = sub1(CA), + jump_if_LE(sim_core:set_flags(sim_core:set_ac(Core, AC, Word), Flags), Mem, Word, EA). + +-spec handle_SOJA(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SOJA(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + {Word, Flags} = sub1(CA), + jump(sim_core:set_flags(sim_core:set_ac(Core, AC, Word), Flags), Mem, EA). + +-spec handle_SOJGE(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SOJGE(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + {Word, Flags} = sub1(CA), + jump_if_GE(sim_core:set_flags(sim_core:set_ac(Core, AC, Word), Flags), Mem, Word, EA). + +-spec handle_SOJN(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SOJN(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + {Word, Flags} = sub1(CA), + jump_if_N(sim_core:set_flags(sim_core:set_ac(Core, AC, Word), Flags), Mem, Word, EA). + +-spec handle_SOJG(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_SOJG(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + {Word, Flags} = sub1(CA), + jump_if_G(sim_core:set_flags(sim_core:set_ac(Core, AC, Word), Flags), Mem, Word, EA). + %% Miscellaneous =============================================================== jump_if_E(Core, Mem, X, EA) -> @@ -735,6 +809,21 @@ add1(Word) -> end, {Add1, Flags}. +sub1(Word) -> + Sub1 = (Word - 1) band ((1 bsl 36) - 1), + Flags = + case Sub1 of + 8#377777777777 -> % -2^35 - 1 + (1 bsl ?PDP10_PF_TRAP_1) bor + (1 bsl ?PDP10_PF_OVERFLOW) bor + (1 bsl ?PDP10_PF_CARRY_0); + 8#777777777777 -> % 0 - 1 + 0; + _ -> % "any other non-zero number" - 1 + (1 bsl ?PDP10_PF_CARRY_0) bor (1 bsl ?PDP10_PF_CARRY_1) + end, + {Sub1, Flags}. + %% Sign-extend a uint36_t() to the full width of its representation type. -spec sext36(uint36_t()) -> integer(). sext36(X) -> diff --git a/erlang/apps/sim/src/sim_core.erl b/erlang/apps/sim/src/sim_core.erl index b20703c..871f8a7 100644 --- a/erlang/apps/sim/src/sim_core.erl +++ b/erlang/apps/sim/src/sim_core.erl @@ -336,6 +336,14 @@ dispatch(Core, Mem, IR, EA) -> 8#355 -> sim_arithmetic:handle_AOSGE(Core, Mem, IR, EA); 8#356 -> sim_arithmetic:handle_AOSN(Core, Mem, IR, EA); 8#357 -> sim_arithmetic:handle_AOSG(Core, Mem, IR, EA); + 8#360 -> sim_arithmetic:handle_SOJ(Core, Mem, IR, EA); + 8#361 -> sim_arithmetic:handle_SOJL(Core, Mem, IR, EA); + 8#362 -> sim_arithmetic:handle_SOJE(Core, Mem, IR, EA); + 8#363 -> sim_arithmetic:handle_SOJLE(Core, Mem, IR, EA); + 8#364 -> sim_arithmetic:handle_SOJA(Core, Mem, IR, EA); + 8#365 -> sim_arithmetic:handle_SOJGE(Core, Mem, IR, EA); + 8#366 -> sim_arithmetic:handle_SOJN(Core, Mem, IR, EA); + 8#367 -> sim_arithmetic:handle_SOJG(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 f97727d..8d69744 100644 --- a/erlang/apps/sim/test/sim_arithmetic_tests.erl +++ b/erlang/apps/sim/test/sim_arithmetic_tests.erl @@ -103,6 +103,14 @@ -define(OP_AOSGE, 8#355). -define(OP_AOSN, 8#356). -define(OP_AOSG, 8#357). +-define(OP_SOJ, 8#360). +-define(OP_SOJL, 8#361). +-define(OP_SOJE, 8#362). +-define(OP_SOJLE, 8#363). +-define(OP_SOJA, 8#364). +-define(OP_SOJGE, 8#365). +-define(OP_SOJN, 8#366). +-define(OP_SOJG, 8#367). %% 2.6.1 Add One to Both Halves of AC and Jump ================================= @@ -1000,6 +1008,151 @@ aosg_test() -> [ {?EA(1, 8#150), ?LOW36(-1)} % C(1,,150) = -1 , {?AC(1), ?LOW36(-1)}]). % AC(1) = -1 +%% SOJ - Subtract One from AC and Jump if Condition Satisfied + +soj_test() -> + Prog = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2 + , {1, 8#101, ?INSN(?OP_SOJ, 1, 0, 0, 0)} % 1,,101/ SOJ 1, + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + ], + expect(Prog, [], {1, 8#102}, ?CARRY_FLAGS, % no jump, carry 0 and 1 + [ {?AC(1), 1}]). % AC(1) = 1 + +sojl_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVNI, 1, 0, 0, 2)} % 1,,100/ MOVNI 1,2 + , {1, 8#101, ?INSN(?OP_SOJL, 1, 0, 0, 8#103)} % 1,,101/ SOJL 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?CARRY_FLAGS, % jump, carry 0 and 1 + [ {?AC(1), ?LOW36(-3)}]), % AC(1) = -3 + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2 + , {1, 8#101, ?INSN(?OP_SOJL, 1, 0, 0, 8#103)} % 1,,101/ SOJL 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#102}, ?CARRY_FLAGS, % no jump, carry 0 and 1 + [ {?AC(1), 1}]). % AC(1) = 1 + +soje_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 1)} % 1,,100/ MOVEI 1,1 + , {1, 8#101, ?INSN(?OP_SOJE, 1, 0, 0, 8#103)} % 1,,101/ SOJE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?CARRY_FLAGS, % jump, carry 0 and 1 + [ {?AC(1), 0}]), % AC(1) = 0 + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2 + , {1, 8#101, ?INSN(?OP_SOJE, 1, 0, 0, 8#103)} % 1,,101/ SOJE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#102}, ?CARRY_FLAGS, % no jump, carry 0 and 1 + [ {?AC(1), 1}]). % AC(1) = 1 + +sojle_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 0)} % 1,,100/ MOVEI 1,0 + , {1, 8#101, ?INSN(?OP_SOJLE, 1, 0, 0, 8#103)} % 1,,101/ SOJLE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, % jump, no carry flags + [ {?AC(1), ?LOW36(-1)}]), % AC(1) = -1 + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 1)} % 1,,100/ MOVEI 1,1 + , {1, 8#101, ?INSN(?OP_SOJLE, 1, 0, 0, 8#103)} % 1,,101/ SOJLE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#103}, ?CARRY_FLAGS, % jump, carry 0 and 1 + [ {?AC(1), 0}]), % AC(1) = 0 + Prog3 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2 + , {1, 8#101, ?INSN(?OP_SOJLE, 1, 0, 0, 8#103)} % 1,,101/ SOJLE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog3, [], {1, 8#102}, ?CARRY_FLAGS, % no jump, carry 0 and 1 + [ {?AC(1), 1}]). % AC(1) = 1 + +soja_test() -> + Prog = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2 + , {1, 8#101, ?INSN(?OP_SOJA, 1, 0, 0, 8#103)} % 1,,101/ SOJA 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog, [], {1, 8#103}, ?CARRY_FLAGS, % jump, carry 0 and 1 + [ {?AC(1), 1}]). % AC(1) = 1 + +sojge_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2 + , {1, 8#101, ?INSN(?OP_SOJGE, 1, 0, 0, 8#103)} % 1,,101/ SOJGE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?CARRY_FLAGS, % jump, carry 0 and 1 + [ {?AC(1), 1}]), % AC(1) = 1 + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 1)} % 1,,100/ MOVEI 1,1 + , {1, 8#101, ?INSN(?OP_SOJGE, 1, 0, 0, 8#103)} % 1,,101/ SOJGE 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#103}, ?CARRY_FLAGS, % jump, carry 0 and 1 + [ {?AC(1), 0}]), % AC(1) = 0 + Prog3 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 0)} % 1,,100/ MOVEI 1,0 + , {1, 8#101, ?INSN(?OP_SOJGE, 1, 0, 0, 8#103)} % 1,,101/ SOJGE 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, no carry flags + [ {?AC(1), ?LOW36(-1)}]). % AC(1) = -1 + +sojn_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2 + , {1, 8#101, ?INSN(?OP_SOJN, 1, 0, 0, 8#103)} % 1,,101/ SOJN 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?CARRY_FLAGS, % jump, carry 0 and 1 + [ {?AC(1), 1}]), % AC(1) = 1 + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 1)} % 1,,100/ MOVEI 1,1 + , {1, 8#101, ?INSN(?OP_SOJN, 1, 0, 0, 8#103)} % 1,,101/ SOJN 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#102}, ?CARRY_FLAGS, % no jump, carry 0 and 1 + [ {?AC(1), 0}]). % AC(1) = 0 + +sojg_test() -> + Prog1 = + [ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2 + , {1, 8#101, ?INSN(?OP_SOJG, 1, 0, 0, 8#103)} % 1,,101/ SOJG 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog1, [], {1, 8#103}, ?CARRY_FLAGS, % jump, carry 0 and 1 + [ {?AC(1), 1}]), % AC(1) = 1 + Prog2 = + [ {1, 8#100, ?INSN(?OP_MOVNI, 1, 0, 0, 2)} % 1,,100/ MOVNI 1,2 + , {1, 8#101, ?INSN(?OP_SOJG, 1, 0, 0, 8#103)} % 1,,101/ SOJG 1,103 + , {1, 8#102, ?INSN_INVALID} % 1,,102/ + , {1, 8#103, ?INSN_INVALID} % 1,,103/ + ], + expect(Prog2, [], {1, 8#102}, ?CARRY_FLAGS, % no jump, carry 0 and 1 + [ {?AC(1), ?LOW36(-3)}]). % AC(1) = -3 + %% Common code to run short sequences ========================================== expect(Prog, ACs, ExpectedPC, ExpectedFlags, ExpectedEs) ->