mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-01-22 18:42:34 +00:00
sim: sim_shifts: handle ASH/ASHC, add unit tests
This commit is contained in:
parent
edf7257d21
commit
17a9505036
@ -280,8 +280,10 @@ 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#240 -> sim_shifts:handle_ASH(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#244 -> sim_shifts:handle_ASHC(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);
|
||||
|
||||
@ -24,7 +24,9 @@
|
||||
|
||||
-module(sim_shifts).
|
||||
|
||||
-export([ handle_LSH/4
|
||||
-export([ handle_ASH/4
|
||||
, handle_ASHC/4
|
||||
, handle_LSH/4
|
||||
, handle_LSHC/4
|
||||
, handle_ROT/4
|
||||
, handle_ROTC/4
|
||||
@ -76,8 +78,161 @@ handle_ROTC(Core, Mem, IR, EA) ->
|
||||
{Word0, Word1} = rotc(CA0, CA1, EA#ea.offset),
|
||||
set_acs_next_pc(Core, Mem, AC, Word0, Word1).
|
||||
|
||||
%% ASH - Arithmetic Shift
|
||||
|
||||
-spec handle_ASH(#core{}, sim_mem:mem(), IR :: word(), #ea{})
|
||||
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
|
||||
handle_ASH(Core, Mem, IR, EA) ->
|
||||
AC = IR band 8#17,
|
||||
CA = sim_core:get_ac(Core, AC),
|
||||
{Word, Flags} = ash(CA, EA#ea.offset),
|
||||
set_ac_and_flags_next_pc(Core, Mem, AC, Word, Flags).
|
||||
|
||||
%% ASHC - Arithmetic Shift Combined
|
||||
|
||||
-spec handle_ASHC(#core{}, sim_mem:mem(), IR :: word(), #ea{})
|
||||
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
|
||||
handle_ASHC(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, Flags} = ashc(CA0, CA1, EA#ea.offset),
|
||||
set_acs_and_flags_next_pc(Core, Mem, AC, Word0, Word1, Flags).
|
||||
|
||||
%% Miscellaneous ===============================================================
|
||||
|
||||
ash(CA, Offset) ->
|
||||
case Offset band (1 bsl 17) of
|
||||
0 -> % left shift
|
||||
Count = Offset band ((1 bsl 8) - 1),
|
||||
case CA band (1 bsl 35) of
|
||||
0 -> % non-negative
|
||||
{Word, Lost} =
|
||||
if Count >= 35 ->
|
||||
{_Word = 0, _Lost = CA =/= 0};
|
||||
true ->
|
||||
LeftNrBits = Count,
|
||||
RightNrBits = 35 - Count,
|
||||
{_Word = (CA band ((1 bsl RightNrBits) - 1)) bsl LeftNrBits,
|
||||
_Lost = (CA bsr RightNrBits) =/= 0}
|
||||
end,
|
||||
Flags =
|
||||
case Lost of
|
||||
false -> 0;
|
||||
true -> (1 bsl ?PDP10_PF_TRAP_1) bor (1 bsl ?PDP10_PF_OVERFLOW)
|
||||
end,
|
||||
{Word, Flags};
|
||||
_ -> % negative
|
||||
{Word, Lost} =
|
||||
if Count >= 35 ->
|
||||
{_Word = 1 bsl 35,
|
||||
_Lost = CA =/= ((1 bsl 36) - 1)};
|
||||
true ->
|
||||
LeftNrBits = Count,
|
||||
RightNrBits = 35 - Count,
|
||||
{_Word = ((CA band ((1 bsl RightNrBits) - 1)) bsl LeftNrBits) bor (1 bsl 35),
|
||||
_Lost = ((CA bsr RightNrBits) band ((1 bsl LeftNrBits) - 1)) =/= ((1 bsl LeftNrBits) - 1)}
|
||||
end,
|
||||
Flags =
|
||||
case Lost of
|
||||
false -> 0;
|
||||
true -> (1 bsl ?PDP10_PF_TRAP_1) bor (1 bsl ?PDP10_PF_OVERFLOW)
|
||||
end,
|
||||
{Word, Flags}
|
||||
end;
|
||||
_ -> % right shift
|
||||
Count = (-Offset) band ((1 bsl 8) - 1),
|
||||
case CA band (1 bsl 35) of
|
||||
0 -> % non-negative
|
||||
Word =
|
||||
if Count >= 35 -> 0;
|
||||
true -> CA bsr Count
|
||||
end,
|
||||
{Word, _Flags = 0};
|
||||
_ -> % negative
|
||||
Word =
|
||||
if Count >= 35 -> (1 bsl 36) - 1;
|
||||
true -> (((1 bsl Count) - 1) bsl (36 - Count)) bor (CA bsr Count)
|
||||
end,
|
||||
{Word, _Flags = 0}
|
||||
end
|
||||
end.
|
||||
|
||||
ashc(CA0, CA1, Offset) ->
|
||||
case Offset band (1 bsl 17) of
|
||||
0 -> % left shift
|
||||
Count = Offset band ((1 bsl 8) - 1),
|
||||
case CA0 band (1 bsl 35) of
|
||||
0 -> % non-negative
|
||||
{Word0, Word1, Lost} =
|
||||
if Count >= 70 ->
|
||||
{_Word0 = 0, _Word1 = 0, _Lost = CA0 bor (CA1 band ((1 bsl 35) - 1))};
|
||||
Count >= 35 ->
|
||||
Count1 = Count - 35,
|
||||
W0 = (CA1 band ((1 bsl (35 - Count1)) - 1)) bsl Count1,
|
||||
L1 = (CA1 bsr (35 - Count1)) band ((1 bsl Count1) - 1),
|
||||
{_Word0 = W0, _Word1 = 0, _Lost = CA0 bor L1};
|
||||
Count > 0 ->
|
||||
W0 = ((CA0 band ((1 bsl (35 - Count)) - 1)) bsl Count) bor (CA1 bsr (35 - Count)),
|
||||
W1 = (CA1 band ((1 bsl (35 - Count)) - 1)) bsl Count,
|
||||
L0 = CA0 bsr (35 - Count),
|
||||
{_Word0 = W0, _Word1 = W1, _Lost = L0};
|
||||
true ->
|
||||
{_Word0 = CA0, _Word1 = CA1, _Lost = 0}
|
||||
end,
|
||||
Flags =
|
||||
case Lost of
|
||||
0 -> 0;
|
||||
_ -> (1 bsl ?PDP10_PF_TRAP_1) bor (1 bsl ?PDP10_PF_OVERFLOW)
|
||||
end,
|
||||
{Word0, Word1, Flags};
|
||||
_ -> % negative
|
||||
{Word0, Word1, Lost} =
|
||||
if Count >= 70 ->
|
||||
{_Word0 = 1 bsl 35, _Word1 = 1 bsl 35, _Lost = (CA0 bor CA1) band ((1 bsl 35) - 1)};
|
||||
Count >= 35 ->
|
||||
Count1 = Count - 35,
|
||||
W0 = (CA1 band ((1 bsl (35 - Count1)) - 1)) bsl Count1,
|
||||
L1 = (CA1 bsr Count1) band ((1 bsl Count1) - 1),
|
||||
{_Word0 = W0, _Word1 = 1 bsl 35, _Lost = (CA0 band ((1 bsl 35) - 1)) bor L1};
|
||||
true ->
|
||||
W0 = ((CA1 band ((1 bsl (35 - Count)) - 1)) bsl Count) bor (1 bsl 35) bor ((CA1 bsr (35 - Count)) band ((1 bsl Count) - 1)),
|
||||
W1 = ((CA1 band ((1 bsl (35 - Count)) - 1)) bsl Count) bor (1 bsl 35),
|
||||
L0 = (CA0 bsr (35 - Count)) band ((1 bsl Count) - 1),
|
||||
{_Word0 = W0, _Word1 = W1, _Lost = L0}
|
||||
end,
|
||||
Flags =
|
||||
case Lost of
|
||||
0 -> 0;
|
||||
_ -> (1 bsl ?PDP10_PF_TRAP_1) bor (1 bsl ?PDP10_PF_OVERFLOW)
|
||||
end,
|
||||
{Word0, Word1, Flags}
|
||||
end;
|
||||
_ -> % right shift
|
||||
Count = (-Offset) band ((1 bsl 8) - 1),
|
||||
case CA0 band (1 bsl 35) of
|
||||
0 -> % non-negative
|
||||
if Count >= 70 ->
|
||||
{_Word0 = 0, _Word1 = 0, _Flags = 0};
|
||||
Count >= 35 ->
|
||||
Word1 = CA0 bsr (Count - 35),
|
||||
{_Word0 = 0, Word1, _Flags = 0};
|
||||
true ->
|
||||
Word0 = CA0 bsr Count,
|
||||
Word1 = ((CA0 band ((1 bsl Count) - 1)) bsl (35 - Count)) bor (CA1 bsr Count),
|
||||
{Word0, Word1, _Flags = 0}
|
||||
end;
|
||||
_ -> % negative
|
||||
if Count >= 70 ->
|
||||
{_Word0 = (1 bsl 36) - 1, _Word1 = (1 bsl 36) - 1, _Flags = 0};
|
||||
Count >= 35 ->
|
||||
Count1 = Count - 35,
|
||||
W1 = (CA0 bsr Count1) bor (((1 bsl Count1) - 1) bsl (36 - Count1)),
|
||||
{_Word0 = (1 bsl 36) - 1, _Word1 = W1, _Flags = 0}
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
||||
lsh(CA, Offset) ->
|
||||
case Offset band (1 bsl 17) of
|
||||
0 -> % left shift
|
||||
@ -164,3 +319,11 @@ set_acs_next_pc(Core, Mem, AC, Word0, Word1) ->
|
||||
|
||||
set_ac_next_pc(Core, Mem, AC, Word) ->
|
||||
sim_core:next_pc(sim_core:set_ac(Core, AC, Word), Mem).
|
||||
|
||||
set_acs_and_flags_next_pc(Core, Mem, AC, Word0, Word1, Flags) ->
|
||||
set_ac_and_flags_next_pc(sim_core:set_ac(Core, AC, Word0), Mem, (AC + 1) band 8#17, Word1, Flags).
|
||||
|
||||
set_ac_and_flags_next_pc(Core, Mem, AC, Word, Flags) ->
|
||||
Core1 = sim_core:set_ac(Core, AC, Word),
|
||||
Core2 = sim_core:set_flags(Core1, Flags),
|
||||
sim_core:next_pc(Core2, Mem).
|
||||
|
||||
@ -46,8 +46,10 @@
|
||||
|
||||
-define(INSN_INVALID, ?INSN(0, 0, 0, 0, 0)).
|
||||
|
||||
-define(OP_ASH, 8#240).
|
||||
-define(OP_ROT, 8#241).
|
||||
-define(OP_LSH, 8#242).
|
||||
-define(OP_ASHC, 8#244).
|
||||
-define(OP_ROTC, 8#245).
|
||||
-define(OP_LSHC, 8#246).
|
||||
|
||||
@ -175,6 +177,112 @@ rotc_test() ->
|
||||
, {?AC(2), ?COMMA2(8#666777, 8#000111)} % AC2 = 666777000111
|
||||
]).
|
||||
|
||||
%% ASH - Arithmetic Shift
|
||||
|
||||
ash_test() ->
|
||||
ACS1 =
|
||||
[ {1, ?COMMA2(8#000111, 8#222333)} % AC1 = 000111222333
|
||||
],
|
||||
Prog1 =
|
||||
[ {1, 8#100, ?INSN(?OP_ASH, 1, 0, 0, 6)} % 1,,100/ ASH 1,6
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
],
|
||||
expect(Prog1, ACS1, {1, 8#101}, ?DEFAULT_FLAGS,
|
||||
[ {?AC(1), ?COMMA2(8#011122, 8#233300)} % AC1 = 011122233300
|
||||
]),
|
||||
Prog2 =
|
||||
[ {1, 8#100, ?INSN(?OP_ASH, 1, 0, 0, -9)} % 1,,100/ ASH 1,-9
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
],
|
||||
expect(Prog2, ACS1, {1, 8#101}, ?DEFAULT_FLAGS,
|
||||
[ {?AC(1), ?COMMA2(8#000000, 8#111222)} % AC1 = 000000111222
|
||||
]),
|
||||
ACS2 =
|
||||
[ {1, ?COMMA2(8#777555, 8#333111)} % AC1 = 777555333111
|
||||
],
|
||||
Prog3 =
|
||||
[ {1, 8#100, ?INSN(?OP_ASH, 1, 0, 0, 6)} % 1,,100/ ASH 1,6
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
],
|
||||
expect(Prog3, ACS2, {1, 8#101}, ?DEFAULT_FLAGS,
|
||||
[ {?AC(1), ?COMMA2(8#755533, 8#311100)} % AC1 = 755533311100
|
||||
]),
|
||||
Prog4 =
|
||||
[ {1, 8#100, ?INSN(?OP_ASH, 1, 0, 0, -9)} % 1,,100/ ASH 1,-9
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
],
|
||||
expect(Prog4, ACS2, {1, 8#101}, ?DEFAULT_FLAGS,
|
||||
[ {?AC(1), ?COMMA2(8#777777, 8#555333)} % AC1 = 777777555333
|
||||
]).
|
||||
|
||||
%% ASHC - Arithmetic Shift Combined
|
||||
|
||||
ashc_test() ->
|
||||
ACS1 =
|
||||
[ {1, ?COMMA2(8#000111, 8#222333)} % AC1 = 000111222333
|
||||
, {2, ?COMMA2(8#777666, 8#555444)} % AC2 = 777666555444
|
||||
],
|
||||
Prog1 =
|
||||
[ {1, 8#100, ?INSN(?OP_ASHC, 1, 0, 0, 6)} % 1,,100/ ASHC 1,6
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
],
|
||||
expect(Prog1, ACS1, {1, 8#101}, ?DEFAULT_FLAGS,
|
||||
[ {?AC(1), ?COMMA2(8#011122, 8#233377)} % AC1 = 011122233377
|
||||
, {?AC(2), ?COMMA2(8#366655, 8#544400)} % AC2 = 366655544400
|
||||
]),
|
||||
Prog2 =
|
||||
[ {1, 8#100, ?INSN(?OP_ASHC, 1, 0, 0, -9)} % 1,,100/ ASHC 1,-9
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
],
|
||||
expect(Prog2, ACS1, {1, 8#101}, ?DEFAULT_FLAGS,
|
||||
[ {?AC(1), ?COMMA2(8#000000, 8#111222)} % AC1 = 000000111222
|
||||
, {?AC(2), ?COMMA2(8#155777, 8#666555)} % AC2 = 155777666555
|
||||
]),
|
||||
ACS2 =
|
||||
[ {1, ?COMMA2(8#000000, 8#000000)} % AC1 = 0
|
||||
, {2, ?COMMA2(8#000666, 8#555444)} % AC2 = 000666555444
|
||||
],
|
||||
Prog3 =
|
||||
[ {1, 8#100, ?INSN(?OP_ASHC, 1, 0, 0, 35+6)} % 1,,100/ ASHC 1,51
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
],
|
||||
expect(Prog3, ACS2, {1, 8#101}, ?DEFAULT_FLAGS,
|
||||
[ {?AC(1), ?COMMA2(8#066655, 8#544400)} % AC1 = 066655544400
|
||||
, {?AC(2), ?COMMA2(8#000000, 8#000000)} % AC2 = 0
|
||||
]),
|
||||
Prog4 =
|
||||
[ {1, 8#100, ?INSN(?OP_ASHC, 1, 0, 0, -(35+9))} % 1,,100/ ASHC 1,54
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
],
|
||||
expect(Prog4, ACS1, {1, 8#101}, ?DEFAULT_FLAGS,
|
||||
[ {?AC(1), ?COMMA2(8#000000, 8#000000)} % AC1 = 0
|
||||
, {?AC(2), ?COMMA2(8#000000, 8#111222)} % AC2 = 000000111222
|
||||
]),
|
||||
ACS3 =
|
||||
[ {1, 0} % AC1 = 0
|
||||
, {2, 0} % AC2 = 0
|
||||
],
|
||||
Prog5 =
|
||||
[ {1, 8#100, ?INSN(?OP_ASHC, 1, 0, 0, 70+6)} % 1,,100/ ASHC 1,114
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
],
|
||||
expect(Prog5, ACS3, {1, 8#101}, ?DEFAULT_FLAGS,
|
||||
[ {?AC(1), 0} % AC1 = 0
|
||||
, {?AC(2), 0} % AC2 = 0
|
||||
]),
|
||||
ACS4 =
|
||||
[ {1, ?COMMA2(-1, -1)} % AC1 = -1
|
||||
, {2, ?COMMA2(-1, -1)} % AC2 = -1
|
||||
],
|
||||
Prog6 =
|
||||
[ {1, 8#100, ?INSN(?OP_ASHC, 1, 0, 0, -(70+6))} % 1,,100/ ASHC 1,-114
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
],
|
||||
expect(Prog6, ACS4, {1, 8#101}, ?DEFAULT_FLAGS,
|
||||
[ {?AC(1), ?COMMA2(-1, -1)} % AC1 = -1
|
||||
, {?AC(2), ?COMMA2(-1, -1)} % AC2 = -1
|
||||
]).
|
||||
|
||||
%% Common code to run short sequences ==========================================
|
||||
|
||||
expect(Prog, ACs, ExpectedPC, ExpectedFlags, ExpectedEs) ->
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user