mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-02-22 23:37:55 +00:00
sim: sim_arithmetic: handle CAI{L,E,LE,GE,N,G}, sim_core: handle CAI as no-op and CAIA as skip, add unit tests
This commit is contained in:
@@ -26,6 +26,12 @@
|
||||
|
||||
-export([ handle_AOBJN/4
|
||||
, handle_AOBJP/4
|
||||
, handle_CAIE/4
|
||||
, handle_CAIG/4
|
||||
, handle_CAIGE/4
|
||||
, handle_CAIL/4
|
||||
, handle_CAILE/4
|
||||
, handle_CAIN/4
|
||||
]).
|
||||
|
||||
-include("sim_core.hrl").
|
||||
@@ -72,7 +78,84 @@ handle_AOBJN(Core, Mem, IR, EA) ->
|
||||
_ -> jump(Core1, Mem, EA)
|
||||
end.
|
||||
|
||||
%% 2.6.2 Comparisons, Skips, and Jumps =========================================
|
||||
|
||||
%% CAI - Compare AC Immediate and Skip if Condition Satisfied
|
||||
|
||||
-spec handle_CAIL(#core{}, sim_mem:mem(), IR :: word(), #ea{})
|
||||
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
|
||||
handle_CAIL(Core, Mem, IR, EA) ->
|
||||
AC = IR band 8#17,
|
||||
CA = sim_core:get_ac(Core, AC),
|
||||
skip_if_L(Core, Mem, sext36(CA), EA#ea.offset).
|
||||
|
||||
-spec handle_CAIE(#core{}, sim_mem:mem(), IR :: word(), #ea{})
|
||||
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
|
||||
handle_CAIE(Core, Mem, IR, EA) ->
|
||||
AC = IR band 8#17,
|
||||
CA = sim_core:get_ac(Core, AC),
|
||||
skip_if_E(Core, Mem, CA, EA#ea.offset).
|
||||
|
||||
-spec handle_CAILE(#core{}, sim_mem:mem(), IR :: word(), #ea{})
|
||||
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
|
||||
handle_CAILE(Core, Mem, IR, EA) ->
|
||||
AC = IR band 8#17,
|
||||
CA = sim_core:get_ac(Core, AC),
|
||||
skip_if_LE(Core, Mem, sext36(CA), EA#ea.offset).
|
||||
|
||||
-spec handle_CAIGE(#core{}, sim_mem:mem(), IR :: word(), #ea{})
|
||||
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
|
||||
handle_CAIGE(Core, Mem, IR, EA) ->
|
||||
AC = IR band 8#17,
|
||||
CA = sim_core:get_ac(Core, AC),
|
||||
skip_if_LE(Core, Mem, EA#ea.offset, sext36(CA)). % AC >= 0,E -> 0,E =< AC
|
||||
|
||||
-spec handle_CAIN(#core{}, sim_mem:mem(), IR :: word(), #ea{})
|
||||
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
|
||||
handle_CAIN(Core, Mem, IR, EA) ->
|
||||
AC = IR band 8#17,
|
||||
CA = sim_core:get_ac(Core, AC),
|
||||
skip_if_N(Core, Mem, CA, EA#ea.offset).
|
||||
|
||||
-spec handle_CAIG(#core{}, sim_mem:mem(), IR :: word(), #ea{})
|
||||
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
|
||||
handle_CAIG(Core, Mem, IR, EA) ->
|
||||
AC = IR band 8#17,
|
||||
CA = sim_core:get_ac(Core, AC),
|
||||
skip_if_L(Core, Mem, EA#ea.offset, sext36(CA)). % AC > 0,E -> 0,E < AC
|
||||
|
||||
%% Miscellaneous ===============================================================
|
||||
|
||||
jump(Core, Mem, EA) ->
|
||||
sim_core:run(Core#core{pc_offset = EA#ea.offset}, Mem).
|
||||
|
||||
skip_if_E(Core, Mem, X, Y) ->
|
||||
case X =:= Y of
|
||||
true -> sim_core:skip(Core, Mem);
|
||||
false -> sim_core:next_pc(Core, Mem)
|
||||
end.
|
||||
|
||||
skip_if_L(Core, Mem, X, Y) ->
|
||||
case X < Y of
|
||||
true -> sim_core:skip(Core, Mem);
|
||||
false -> sim_core:next_pc(Core, Mem)
|
||||
end.
|
||||
|
||||
skip_if_LE(Core, Mem, X, Y) ->
|
||||
case X =< Y of
|
||||
true -> sim_core:skip(Core, Mem);
|
||||
false -> sim_core:next_pc(Core, Mem)
|
||||
end.
|
||||
|
||||
skip_if_N(Core, Mem, X, Y) ->
|
||||
case X =/= Y of
|
||||
true -> sim_core:skip(Core, Mem);
|
||||
false -> sim_core:next_pc(Core, Mem)
|
||||
end.
|
||||
|
||||
%% Sign-extend a uint36_t() to the full width of its representation type.
|
||||
-spec sext36(uint36_t()) -> integer().
|
||||
sext36(X) ->
|
||||
UInt36Sbit = 1 bsl (36 - 1),
|
||||
UInt36Max = (1 bsl 36) - 1,
|
||||
((X band UInt36Max) bxor UInt36Sbit) - UInt36Sbit.
|
||||
|
||||
@@ -288,6 +288,14 @@ dispatch(Core, Mem, IR, EA) ->
|
||||
8#261 -> sim_stack:handle_PUSH(Core, Mem, IR, EA);
|
||||
8#262 -> sim_stack:handle_POP(Core, Mem, IR, EA);
|
||||
8#263 -> sim_stack:handle_POPJ(Core, Mem, IR, EA);
|
||||
8#300 -> next_pc(Core, Mem); % CAI = no-op
|
||||
8#301 -> sim_arithmetic:handle_CAIL(Core, Mem, IR, EA);
|
||||
8#302 -> sim_arithmetic:handle_CAIE(Core, Mem, IR, EA);
|
||||
8#303 -> sim_arithmetic:handle_CAILE(Core, Mem, IR, EA);
|
||||
8#304 -> skip(Core, Mem); % CAIA = SKIPA without the memory read
|
||||
8#305 -> sim_arithmetic:handle_CAIGE(Core, Mem, IR, EA);
|
||||
8#306 -> sim_arithmetic:handle_CAIN(Core, Mem, IR, EA);
|
||||
8#307 -> sim_arithmetic:handle_CAIG(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);
|
||||
|
||||
@@ -45,9 +45,19 @@
|
||||
|
||||
-define(INSN_INVALID, ?INSN(0, 0, 0, 0, 0)).
|
||||
|
||||
-define(OP_MOVEI, 8#201).
|
||||
-define(OP_MOVSI, 8#205).
|
||||
-define(OP_MOVNI, 8#211).
|
||||
-define(OP_AOBJP, 8#252).
|
||||
-define(OP_AOBJN, 8#253).
|
||||
-define(OP_CAI, 8#300).
|
||||
-define(OP_CAIL, 8#301).
|
||||
-define(OP_CAIE, 8#302).
|
||||
-define(OP_CAILE, 8#303).
|
||||
-define(OP_CAIA, 8#304).
|
||||
-define(OP_CAIGE, 8#305).
|
||||
-define(OP_CAIN, 8#306).
|
||||
-define(OP_CAIG, 8#307).
|
||||
|
||||
%% 2.6.1 Add One to Both Halves of AC and Jump =================================
|
||||
|
||||
@@ -95,6 +105,135 @@ aobjn_test() ->
|
||||
[{?AC(1), ?COMMA2(0, 1)} % AC1 = 0,,1
|
||||
]).
|
||||
|
||||
%% 2.6.2 Comparisons, Skips, and Jumps =========================================
|
||||
|
||||
%% CAI - Compare AC Immediate and Skip if Condition Satisfied
|
||||
|
||||
cai_test() ->
|
||||
Prog =
|
||||
[ {1, 8#100, ?INSN(?OP_CAI, 0, 0, 0, 0)} % 1,,100/ CAI
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
],
|
||||
expect(Prog, [], {1, 8#101}, ?DEFAULT_FLAGS, []). % no skip
|
||||
|
||||
cail_test() ->
|
||||
Prog1 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVNI, 1, 0, 0, 3)} % 1,,100/ MOVNI 1,3
|
||||
, {1, 8#101, ?INSN(?OP_CAIL, 1, 0, 0, 2)} % 1,,101/ CAIL 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % skip
|
||||
Prog2 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3
|
||||
, {1, 8#101, ?INSN(?OP_CAIL, 1, 0, 0, 2)} % 1,,101/ CAIL 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no skip
|
||||
|
||||
caie_test() ->
|
||||
Prog1 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2
|
||||
, {1, 8#101, ?INSN(?OP_CAIE, 1, 0, 0, 2)} % 1,,101/ CAIE 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % skip
|
||||
Prog2 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3
|
||||
, {1, 8#101, ?INSN(?OP_CAIE, 1, 0, 0, 2)} % 1,,101/ CAIE 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no skip
|
||||
|
||||
caile_test() ->
|
||||
Prog1 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVNI, 1, 0, 0, 3)} % 1,,100/ MOVNI 1,3
|
||||
, {1, 8#101, ?INSN(?OP_CAILE, 1, 0, 0, 2)} % 1,,101/ CAILE 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % skip
|
||||
Prog2 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2
|
||||
, {1, 8#101, ?INSN(?OP_CAILE, 1, 0, 0, 2)} % 1,,101/ CAILE 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog2, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % skip
|
||||
Prog3 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3
|
||||
, {1, 8#101, ?INSN(?OP_CAILE, 1, 0, 0, 2)} % 1,,101/ CAILE 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog3, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no skip
|
||||
|
||||
caia_test() ->
|
||||
Prog =
|
||||
[ {1, 8#100, ?INSN(?OP_CAIA, 0, 0, 0, 0)} % 1,,100/ CAIA
|
||||
, {1, 8#101, ?INSN_INVALID} % 1,,101/ <invalid>
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
],
|
||||
expect(Prog, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % skip
|
||||
|
||||
caige_test() ->
|
||||
Prog1 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3
|
||||
, {1, 8#101, ?INSN(?OP_CAIGE, 1, 0, 0, 2)} % 1,,101/ CAIGE 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % skip
|
||||
Prog2 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2
|
||||
, {1, 8#101, ?INSN(?OP_CAIGE, 1, 0, 0, 2)} % 1,,101/ CAIGE 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog2, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % skip
|
||||
Prog3 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVNI, 1, 0, 0, 3)} % 1,,100/ MOVNI 1,3
|
||||
, {1, 8#101, ?INSN(?OP_CAIGE, 1, 0, 0, 2)} % 1,,101/ CAIGE 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog3, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no skip
|
||||
|
||||
cain_test() ->
|
||||
Prog1 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3
|
||||
, {1, 8#101, ?INSN(?OP_CAIN, 1, 0, 0, 2)} % 1,,101/ CAIN 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % skip
|
||||
Prog2 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 2)} % 1,,100/ MOVEI 1,2
|
||||
, {1, 8#101, ?INSN(?OP_CAIN, 1, 0, 0, 2)} % 1,,101/ CAIN 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no skip
|
||||
|
||||
caig_test() ->
|
||||
Prog1 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVEI, 1, 0, 0, 3)} % 1,,100/ MOVEI 1,3
|
||||
, {1, 8#101, ?INSN(?OP_CAIG, 1, 0, 0, 2)} % 1,,101/ CAIG 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog1, [], {1, 8#103}, ?DEFAULT_FLAGS, []), % skip
|
||||
Prog2 =
|
||||
[ {1, 8#100, ?INSN(?OP_MOVNI, 1, 0, 0, 3)} % 1,,100/ MOVNI 1,3
|
||||
, {1, 8#101, ?INSN(?OP_CAIG, 1, 0, 0, 2)} % 1,,101/ CAIG 1,2
|
||||
, {1, 8#102, ?INSN_INVALID} % 1,,102/ <invalid>
|
||||
, {1, 8#103, ?INSN_INVALID} % 1,,103/ <invalid>
|
||||
],
|
||||
expect(Prog2, [], {1, 8#102}, ?DEFAULT_FLAGS, []). % no skip
|
||||
|
||||
%% Common code to run short sequences ==========================================
|
||||
|
||||
expect(Prog, ACs, ExpectedPC, ExpectedFlags, ExpectedEs) ->
|
||||
|
||||
Reference in New Issue
Block a user