diff --git a/erlang/apps/sim/src/sim_core.erl b/erlang/apps/sim/src/sim_core.erl index 147f320..1cf35a5 100644 --- a/erlang/apps/sim/src/sim_core.erl +++ b/erlang/apps/sim/src/sim_core.erl @@ -243,6 +243,7 @@ dispatch(Core, Mem, IR, EA) -> 8#211 -> sim_moves:handle_MOVNI(Core, Mem, IR, EA); 8#212 -> sim_moves:handle_MOVNM(Core, Mem, IR, EA); 8#213 -> sim_moves:handle_MOVNS(Core, Mem, IR, EA); + 8#214 -> sim_moves:handle_MOVM(Core, Mem, IR, EA); 8#250 -> sim_moves:handle_EXCH(Core, Mem, IR, EA); _ -> PC = (Core#core.pc_section bsl 18) bor Core#core.pc_offset, diff --git a/erlang/apps/sim/src/sim_moves.erl b/erlang/apps/sim/src/sim_moves.erl index 311f55e..3a8558e 100644 --- a/erlang/apps/sim/src/sim_moves.erl +++ b/erlang/apps/sim/src/sim_moves.erl @@ -29,6 +29,7 @@ , handle_MOVEI/4 , handle_MOVEM/4 , handle_MOVES/4 + , handle_MOVM/4 , handle_MOVN/4 , handle_MOVNI/4 , handle_MOVNM/4 @@ -231,11 +232,42 @@ handle_MOVNS(Core, Mem, AC, EA, Word, Flags) -> fun(Core1, Mem1) -> handle_MOVNS(Core1, Mem1, AC, EA, Word, Flags) end) end. +%% MOVM - Move Magnitude + +-spec handle_MOVM(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_MOVM(Core, Mem, IR, EA) -> + case sim_core:c(Core, Mem, EA) of + {ok, CE} -> + {Magnitude, Flags} = magnitude(CE), + AC = IR band 8#17, + sim_core:next_pc(sim_core:set_ac(sim_core:set_flags(Core, Flags), AC, Magnitude), Mem); + {error, Reason} -> + sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason, + fun(Core1, Mem1) -> handle_MOVM(Core1, Mem1, IR, EA) end) + end. + %% Miscellaneous =============================================================== ea_address(#ea{section = Section, offset = Offset}) -> (Section bsl 18) bor Offset. +magnitude(Word) -> + case Word band (1 bsl 35) of + 0 -> % non-negative + {_Magnitude = Word, _Flags = 0}; + _ -> % negative + case (-Word) band ((1 bsl 36) - 1) of + Word -> % magnitude of -2^35 + Flags = (1 bsl ?PDP10_PF_TRAP_1) bor + (1 bsl ?PDP10_PF_OVERFLOW) bor + (1 bsl ?PDP10_PF_CARRY_1), + {_Magnitude = Word, Flags}; + Negated -> + {_Magnitude = Negated, _Flags = 0} + end + end. + negate(Word) -> case (-Word) band ((1 bsl 36) - 1) of 0 -> % negating 0 diff --git a/erlang/apps/sim/test/sim_moves_tests.erl b/erlang/apps/sim/test/sim_moves_tests.erl index 49675bd..54b73d9 100644 --- a/erlang/apps/sim/test/sim_moves_tests.erl +++ b/erlang/apps/sim/test/sim_moves_tests.erl @@ -55,6 +55,7 @@ -define(OP_MOVNI, 8#211). -define(OP_MOVNM, 8#212). -define(OP_MOVNS, 8#213). +-define(OP_MOVM, 8#214). -define(OP_EXCH, 8#250). %% 2.1.1 Exchange Instruction ================================================== @@ -271,6 +272,47 @@ movns_noac_test() -> , {#ea{section = 1, offset = 0, islocal = false}, 0} % AC0 = 0 ]). +movm_positive_test() -> + Prog = + [ {1, 8#100, ?INSN(?OP_MOVM, 1, 0, 0, 8#150)} % 1,,100/ MOVM 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#150, 8#42} % 1,,150/ 0,,42 + ], + expect(Prog, [], {1, 8#101}, ?DEFAULT_FLAGS, + [ {#ea{section = 1, offset = 1, islocal = false}, 8#42} % AC1 = 42 + ]). + +movm_zero_test() -> + Prog = + [ {1, 8#100, ?INSN(?OP_MOVM, 1, 0, 0, 8#150)} % 1,,100/ MOVM 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#150, 0} % 1,,150/ 0,,0 + ], + expect(Prog, [], {1, 8#101}, ?DEFAULT_FLAGS, + [ {#ea{section = 1, offset = 1, islocal = false}, 0} % AC1 = 0 + ]). + +movm_negative_test() -> + Prog = + [ {1, 8#100, ?INSN(?OP_MOVM, 1, 0, 0, 8#150)} % 1,,100/ MOVM 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#150, (-8#42) band ((1 bsl 36) -1)} % 1,,150/ -42 + ], + expect(Prog, [], {1, 8#101}, ?DEFAULT_FLAGS, + [ {#ea{section = 1, offset = 1, islocal = false}, 8#42} % AC1 = 42 + ]). + +movm_minint_test() -> + Prog = + [ {1, 8#100, ?INSN(?OP_MOVM, 1, 0, 0, 8#150)} % 1,,100/ MOVM 1,150 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + , {1, 8#150, 1 bsl 35} % 1,,150/ 400000,,0 + ], + Flags = ?DEFAULT_FLAGS bor (1 bsl ?PDP10_PF_OVERFLOW) bor (1 bsl ?PDP10_PF_CARRY_1), + expect(Prog, [], {1, 8#101}, Flags, + [ {#ea{section = 1, offset = 1, islocal = false}, 1 bsl 35} % AC1 = 400000,,0 + ]). + %% Common code to run short sequences ========================================== expect(Prog, ACs, ExpectedPC, ExpectedFlags, ExpectedEs) ->