From edf7257d21f87ccbbdbf9b31f667bf07dde94944 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Mon, 17 Aug 2020 00:08:59 +0200 Subject: [PATCH] sim: sim_shifts: handle ROT/ROTC, add unit tests --- erlang/apps/sim/src/sim_core.erl | 2 + erlang/apps/sim/src/sim_shifts.erl | 61 ++++++++++++++++++++++ erlang/apps/sim/test/sim_shifts_tests.erl | 63 +++++++++++++++++++++++ 3 files changed, 126 insertions(+) diff --git a/erlang/apps/sim/src/sim_core.erl b/erlang/apps/sim/src/sim_core.erl index 2bb3a35..e21a028 100644 --- a/erlang/apps/sim/src/sim_core.erl +++ b/erlang/apps/sim/src/sim_core.erl @@ -280,7 +280,9 @@ dispatch(Core, Mem, IR, EA) -> 8#215 -> sim_moves:handle_MOVEI(Core, Mem, IR, EA); % MOVMI = MOVEI 8#216 -> sim_moves:handle_MOVMM(Core, Mem, IR, EA); 8#217 -> sim_moves:handle_MOVMS(Core, Mem, IR, EA); + 8#241 -> sim_shifts:handle_ROT(Core, Mem, IR, EA); 8#242 -> sim_shifts:handle_LSH(Core, Mem, IR, EA); + 8#245 -> sim_shifts:handle_ROTC(Core, Mem, IR, EA); 8#246 -> sim_shifts:handle_LSHC(Core, Mem, IR, EA); 8#250 -> sim_moves:handle_EXCH(Core, Mem, IR, EA); 8#251 -> sim_moves:handle_BLT(Core, Mem, IR, EA); diff --git a/erlang/apps/sim/src/sim_shifts.erl b/erlang/apps/sim/src/sim_shifts.erl index 7eb3c22..2cf05f4 100644 --- a/erlang/apps/sim/src/sim_shifts.erl +++ b/erlang/apps/sim/src/sim_shifts.erl @@ -26,6 +26,8 @@ -export([ handle_LSH/4 , handle_LSHC/4 + , handle_ROT/4 + , handle_ROTC/4 ]). -include("sim_core.hrl"). @@ -53,6 +55,27 @@ handle_LSHC(Core, Mem, IR, EA) -> {Word0, Word1} = lshc(CA0, CA1, EA#ea.offset), set_acs_next_pc(Core, Mem, AC, Word0, Word1). +%% ROT - Rotate + +-spec handle_ROT(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_ROT(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA = sim_core:get_ac(Core, AC), + Word = rot(CA, EA#ea.offset), + set_ac_next_pc(Core, Mem, AC, Word). + +%% ROTC - Rotate Combined + +-spec handle_ROTC(#core{}, sim_mem:mem(), IR :: word(), #ea{}) + -> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}. +handle_ROTC(Core, Mem, IR, EA) -> + AC = IR band 8#17, + CA0 = sim_core:get_ac(Core, AC), + CA1 = sim_core:get_ac(Core, (AC + 1) band 8#17), + {Word0, Word1} = rotc(CA0, CA1, EA#ea.offset), + set_acs_next_pc(Core, Mem, AC, Word0, Word1). + %% Miscellaneous =============================================================== lsh(CA, Offset) -> @@ -98,6 +121,44 @@ lshc(CA0, CA1, Offset) -> end end. +rot(CA, Offset) -> + case Offset band (1 bsl 17) of + 0 -> % rotate left + Count = (Offset band ((1 bsl 8) - 1)) rem 36, + ((CA band ((1 bsl (36 - Count)) - 1)) bsl Count) bor (CA bsr (36 - Count)); + _ -> % rotate right + Count = ((-Offset) band ((1 bsl 8) - 1)) rem 36, + (CA bsr Count) bor ((CA band ((1 bsl Count) - 1)) bsl (36 - Count)) + end. + +rotc(CA0, CA1, Offset) -> + case Offset band (1 bsl 17) of + 0 -> % rotate left + Count = (Offset band ((1 bsl 8) - 1)) rem 72, + if Count >= 36 -> + Count1 = Count - 36, + Word0 = ((CA1 band ((1 bsl (36 - Count1)) - 1)) bsl Count1) bor (CA0 bsr (36 - Count1)), + Word1 = ((CA0 band ((1 bsl (36 - Count1)) - 1)) bsl Count1) bor (CA1 bsr (36 - Count1)), + {Word0, Word1}; + true -> + Word0 = ((CA0 band ((1 bsl (36 - Count)) - 1)) bsl Count) bor (CA1 bsr (36 - Count)), + Word1 = ((CA1 band ((1 bsl (36 - Count)) - 1)) bsl Count) bor (CA0 bsr (36 - Count)), + {Word0, Word1} + end; + _ -> % rotate right + Count = ((-Offset) band ((1 bsl 8) - 1)) rem 72, + if Count >= 36 -> + Count1 = Count - 36, + Word0 = (CA1 bsr Count1) bor ((CA0 band ((1 bsl Count1) - 1)) bsl (36 - Count1)), + Word1 = (CA0 bsr Count1) bor ((CA1 band ((1 bsl Count1) - 1)) bsl (36 - Count1)), + {Word0, Word1}; + true -> + Word0 = (CA0 bsr Count) bor ((CA1 band ((1 bsl Count) - 1)) bsl (36 - Count)), + Word1 = (CA1 bsr Count) bor ((CA0 band ((1 bsl Count) - 1)) bsl (36 - Count)), + {Word0, Word1} + end + end. + set_acs_next_pc(Core, Mem, AC, Word0, Word1) -> set_ac_next_pc(sim_core:set_ac(Core, AC, Word0), Mem, (AC + 1) band 8#17, Word1). diff --git a/erlang/apps/sim/test/sim_shifts_tests.erl b/erlang/apps/sim/test/sim_shifts_tests.erl index b8da560..e3a5727 100644 --- a/erlang/apps/sim/test/sim_shifts_tests.erl +++ b/erlang/apps/sim/test/sim_shifts_tests.erl @@ -46,7 +46,9 @@ -define(INSN_INVALID, ?INSN(0, 0, 0, 0, 0)). +-define(OP_ROT, 8#241). -define(OP_LSH, 8#242). +-define(OP_ROTC, 8#245). -define(OP_LSHC, 8#246). %% 2.5 Shift and Rotate ======================================================== @@ -112,6 +114,67 @@ lshc_test() -> , {?AC(2), ?COMMA2(8#000000, 8#111222)} % AC2 = 000000111222 ]). +%% ROT - Rotate + +rot_test() -> + ACS = + [ {1, ?COMMA2(8#111222, 8#333444)} % AC1 = 111222333444 + ], + Prog1 = + [ {1, 8#100, ?INSN(?OP_ROT, 1, 0, 0, 36+9)} % 1,,100/ ROT 1,55 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + ], + expect(Prog1, ACS, {1, 8#101}, ?DEFAULT_FLAGS, + [ {?AC(1), ?COMMA2(8#222333, 8#444111)} % AC1 = 222333444111 + ]), + Prog2 = + [ {1, 8#100, ?INSN(?OP_ROT, 1, 0, 0, -(36+9))} % 1,,100/ ROT 1,-55 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + ], + expect(Prog2, ACS, {1, 8#101}, ?DEFAULT_FLAGS, + [ {?AC(1), ?COMMA2(8#444111, 8#222333)} % AC1 = 444111222333 + ]). + +%% ROTC - Rotate Combined + +rotc_test() -> + ACS = + [ {1, ?COMMA2(8#000111, 8#222333)} % AC1 = 000111222333 + , {2, ?COMMA2(8#444555, 8#666777)} % AC2 = 444555666777 + ], + Prog1 = + [ {1, 8#100, ?INSN(?OP_ROTC, 1, 0, 0, 18)} % 1,,100/ ROTC 1,22 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + ], + expect(Prog1, ACS, {1, 8#101}, ?DEFAULT_FLAGS, + [ {?AC(1), ?COMMA2(8#222333, 8#444555)} % AC1 = 222333444555 + , {?AC(2), ?COMMA2(8#666777, 8#000111)} % AC2 = 666777000111 + ]), + Prog2 = + [ {1, 8#100, ?INSN(?OP_ROTC, 1, 0, 0, 36+18)} % 1,,100/ ROTC 1,66 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + ], + expect(Prog2, ACS, {1, 8#101}, ?DEFAULT_FLAGS, + [ {?AC(1), ?COMMA2(8#666777, 8#000111)} % AC1 = 666777000111 + , {?AC(2), ?COMMA2(8#222333, 8#444555)} % AC2 = 222333444555 + ]), + Prog3 = + [ {1, 8#100, ?INSN(?OP_ROTC, 1, 0, 0, -18)} % 1,,100/ ROTC 1,-22 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + ], + expect(Prog3, ACS, {1, 8#101}, ?DEFAULT_FLAGS, + [ {?AC(1), ?COMMA2(8#666777, 8#000111)} % AC1 = 666777000111 + , {?AC(2), ?COMMA2(8#222333, 8#444555)} % AC2 = 222333444555 + ]), + Prog4 = + [ {1, 8#100, ?INSN(?OP_ROTC, 1, 0, 0, -(36+18))} % 1,,100/ ROTC 1,-66 + , {1, 8#101, ?INSN_INVALID} % 1,,101/ + ], + expect(Prog4, ACS, {1, 8#101}, ?DEFAULT_FLAGS, + [ {?AC(1), ?COMMA2(8#222333, 8#444555)} % AC1 = 222333444555 + , {?AC(2), ?COMMA2(8#666777, 8#000111)} % AC2 = 666777000111 + ]). + %% Common code to run short sequences ========================================== expect(Prog, ACs, ExpectedPC, ExpectedFlags, ExpectedEs) ->