sim: sim_halfword: new, handle HLL/HLLI/XHLLI/HLLM/HLLS, add unit tests

This commit is contained in:
Mikael Pettersson
2020-07-26 20:54:24 +02:00
parent 515e9ae93b
commit 8fcb2a1ee8
3 changed files with 301 additions and 0 deletions

View File

@@ -317,6 +317,10 @@ dispatch(Core, Mem, IR, EA) ->
8#475 -> sim_boolean:handle_SETO(Core, Mem, IR, EA); % SETOI = SETO
8#476 -> sim_boolean:handle_SETOM(Core, Mem, IR, EA);
8#477 -> sim_boolean:handle_SETOB(Core, Mem, IR, EA);
8#500 -> sim_halfword:handle_HLL(Core, Mem, IR, EA);
8#501 -> sim_halfword:handle_HLLI(Core, Mem, IR, EA); % XHLLI in non-zero sections
8#502 -> sim_halfword:handle_HLLM(Core, Mem, IR, EA);
8#503 -> sim_halfword:handle_HLLS(Core, Mem, IR, EA);
_ ->
PC = (Core#core.pc_section bsl 18) bor Core#core.pc_offset,
{Core, Mem, {error, {?MODULE, {dispatch, PC, IR, EA}}}}

View File

@@ -0,0 +1,115 @@
%%% -*- erlang-indent-level: 2 -*-
%%%
%%% simulator for pdp10-elf
%%% Copyright (C) 2020 Mikael Pettersson
%%%
%%% This file is part of pdp10-tools.
%%%
%%% pdp10-tools is free software: you can redistribute it and/or modify
%%% it under the terms of the GNU General Public License as published by
%%% the Free Software Foundation, either version 3 of the License, or
%%% (at your option) any later version.
%%%
%%% pdp10-tools is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%%% GNU General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License
%%% along with pdp10-tools. If not, see <http://www.gnu.org/licenses/>.
%%%
%%%=============================================================================
%%%
%%% 2.8 Half-Word Data Transmission
-module(sim_halfword).
-export([ handle_HLL/4
, handle_HLLI/4
, handle_HLLM/4
, handle_HLLS/4
]).
-include("sim_core.hrl").
%% 2.8 Half-Word Data Transmission =============================================
%% HLL - Half Word Left to Left
-spec handle_HLL(#core{}, sim_mem:mem(), IR :: word(), #ea{})
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
handle_HLL(Core, Mem, IR, EA) ->
case sim_core:c(Core, Mem, EA) of
{ok, CE} ->
AC = IR band 8#17,
CA = sim_core:get_ac(Core, AC),
Word = set_left(CA, get_left(CE)),
sim_core:next_pc(sim_core:set_ac(Core, AC, Word), Mem);
{error, Reason} ->
sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason,
fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end)
end.
-spec handle_HLLI(#core{}, sim_mem:mem(), IR :: word(), #ea{})
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
handle_HLLI(Core, Mem, IR, #ea{section = Section0, offset = Offset, islocal = IsLocal}) ->
AC = IR band 8#17,
CA = sim_core:get_ac(Core, AC),
%% Behave as XHLLI (2.8.1) in non-zero sections.
Section1 =
if IsLocal, Offset =< 8#17, Section0 > 1 -> 1; % change local AC address to global one
true -> Section0
end,
Word = set_left(CA, Section1),
sim_core:next_pc(sim_core:set_ac(Core, AC, Word), Mem).
-spec handle_HLLM(#core{}, sim_mem:mem(), IR :: word(), #ea{})
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
handle_HLLM(Core, Mem, IR, EA) ->
case sim_core:c(Core, Mem, EA) of
{ok, CE} ->
AC = IR band 8#17,
CA = sim_core:get_ac(Core, AC),
Word = set_left(CE, get_left(CA)),
handle_writeback(Core, Mem, EA, Word);
{error, Reason} ->
sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason,
fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end)
end.
-spec handle_HLLS(#core{}, sim_mem:mem(), IR :: word(), #ea{})
-> {#core{}, sim_mem:mem(), {ok, integer()} | {error, {module(), term()}}}.
handle_HLLS(Core, Mem, IR, EA) ->
%% "If A is zero, HLLS is a no-op; otherwise, it is equivalent to MOVE."
%% This implies that redundant memory accesses should not be performed.
AC = IR band 8#17,
case AC of
0 -> sim_core:next_pc(Core, Mem);
_ ->
case sim_core:c(Core, Mem, EA) of
{ok, CE} ->
sim_core:next_pc(sim_core:set_ac(Core, AC, CE), Mem);
{error, Reason} ->
sim_core:page_fault(Core, Mem, ea_address(EA), read, Reason,
fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, IR, EA) end)
end
end.
%% Miscellaneous ===============================================================
handle_writeback(Core, Mem, EA, Word) ->
case sim_core:cset(Core, Mem, EA, Word) of
{ok, Core1} -> sim_core:next_pc(Core1, Mem);
{error, Reason} ->
sim_core:page_fault(Core, Mem, ea_address(EA), write, Reason,
fun(Core1, Mem1) -> ?FUNCTION_NAME(Core1, Mem1, EA, Word) end)
end.
ea_address(#ea{section = Section, offset = Offset}) ->
(Section bsl 18) bor Offset.
get_left(Word) -> Word bsr 18.
get_right(Word) -> Word band ((1 bsl 18) - 1).
set_left(Word, Left) -> get_right(Word) bor (Left bsl 18).