-module(packkit@internal@bcj).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/packkit/internal/bcj.gleam").
-export([arm64_decode/2, arm_decode/2, ia64_decode/2, riscv_decode/2, sparc_decode/2, armthumb_decode/2, powerpc_decode/2, x86_decode/2]).
-export_type([x86_state/0, arm64_kind/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(false).
-type x86_state() :: {x86_state, integer(), integer()}.
-type arm64_kind() :: arm64_bl | arm64_adrp | arm64_other.
-file("src/packkit/internal/bcj.gleam", 171).
?DOC(false).
-spec test_msb(integer()) -> boolean().
test_msb(Byte) ->
(Byte =:= 0) orelse (Byte =:= 16#FF).
-file("src/packkit/internal/bcj.gleam", 166).
?DOC(false).
-spec is_decodable(integer(), integer()) -> boolean().
is_decodable(Byte, Prev_mask) ->
Mask_top = erlang:'bsr'(Prev_mask, 1),
(test_msb(Byte) andalso (Mask_top =< 4)) andalso (Mask_top /= 3).
-file("src/packkit/internal/bcj.gleam", 175).
?DOC(false).
-spec shift_mask_left(integer(), integer()) -> integer().
shift_mask_left(Mask, By) ->
case By of
0 ->
Mask;
_ ->
shift_mask_left(erlang:'bsl'(erlang:'band'(Mask, 16#77), 1), By - 1)
end.
-file("src/packkit/internal/bcj.gleam", 219).
?DOC(false).
-spec mask_to_bit_number(integer()) -> integer().
mask_to_bit_number(Value) ->
case Value of
0 ->
0;
1 ->
1;
2 ->
2;
3 ->
2;
_ ->
3
end.
-file("src/packkit/internal/bcj.gleam", 285).
?DOC(false).
-spec is_powerpc_branch_link(integer(), integer()) -> boolean().
is_powerpc_branch_link(B0, B3) ->
(erlang:'bsr'(B0, 2) =:= 16#12) andalso (erlang:'band'(B3, 3) =:= 1).
-file("src/packkit/internal/bcj.gleam", 389).
?DOC(false).
-spec is_armthumb_bl(integer(), integer()) -> boolean().
is_armthumb_bl(B1, B3) ->
(erlang:'band'(B1, 16#F8) =:= 16#F0) andalso (erlang:'band'(B3, 16#F8) =:= 16#F8).
-file("src/packkit/internal/bcj.gleam", 490).
?DOC(false).
-spec is_sparc_call(integer(), integer()) -> boolean().
is_sparc_call(B0, B1) ->
((B0 =:= 16#40) andalso (erlang:'band'(B1, 16#C0) =:= 16#00)) orelse ((B0
=:= 16#7F)
andalso (erlang:'band'(B1, 16#C0) =:= 16#C0)).
-file("src/packkit/internal/bcj.gleam", 646).
?DOC(false).
-spec classify_arm64_instr(integer()) -> arm64_kind().
classify_arm64_instr(Instr) ->
case erlang:'bsr'(Instr, 26) of
16#25 ->
arm64_bl;
_ ->
case erlang:'band'(Instr, 16#9F000000) =:= 16#90000000 of
true ->
arm64_adrp;
false ->
arm64_other
end
end.
-file("src/packkit/internal/bcj.gleam", 783).
?DOC(false).
-spec bit_array_to_byte_list(bitstring(), list(integer())) -> list(integer()).
bit_array_to_byte_list(Bytes, Acc) ->
case Bytes of
<<B, Rest/binary>> ->
bit_array_to_byte_list(Rest, [B | Acc]);
_ ->
lists:reverse(Acc)
end.
-file("src/packkit/internal/bcj.gleam", 790).
?DOC(false).
-spec byte_list_to_bit_array(list(integer()), bitstring()) -> bitstring().
byte_list_to_bit_array(Bytes, Acc) ->
case Bytes of
[] ->
Acc;
[B | Rest] ->
byte_list_to_bit_array(Rest, <<Acc/bitstring, B>>)
end.
-file("src/packkit/internal/bcj.gleam", 868).
?DOC(false).
-spec ia64_branch_mask(integer()) -> integer().
ia64_branch_mask(Template) ->
case Template of
16 ->
4;
17 ->
4;
24 ->
4;
25 ->
4;
28 ->
4;
29 ->
4;
18 ->
6;
19 ->
6;
22 ->
7;
23 ->
7;
_ ->
0
end.
-file("src/packkit/internal/bcj.gleam", 931).
?DOC(false).
-spec ia64_rewrite_inst_norm(integer(), integer()) -> integer().
ia64_rewrite_inst_norm(Inst_norm, Dest) ->
Clear_lo20 = erlang:'bsl'(16#FFFFF, 13),
Clear_bit36 = erlang:'bsl'(1, 36),
Clear_mask = erlang:'bnot'(erlang:'bor'(Clear_lo20, Clear_bit36)),
Cleared = erlang:'band'(Inst_norm, Clear_mask),
Dest_lo20 = erlang:'bsl'(erlang:'band'(Dest, 16#FFFFF), 13),
Dest_bit20 = erlang:'bsl'(erlang:'band'(Dest, 16#100000), 16),
erlang:'bor'(Cleared, erlang:'bor'(Dest_lo20, Dest_bit20)).
-file("src/packkit/internal/bcj.gleam", 943).
?DOC(false).
-spec ia64_read_le48(list(integer()), integer(), integer()) -> integer().
ia64_read_le48(Bytes, Index, Acc) ->
case Bytes of
[] ->
Acc;
[B | Rest] ->
Next = Acc + erlang:'bsl'(B, 8 * Index),
ia64_read_le48(Rest, Index + 1, Next)
end.
-file("src/packkit/internal/bcj.gleam", 953).
?DOC(false).
-spec ia64_write_le48(integer(), integer(), list(integer())) -> list(integer()).
ia64_write_le48(Value, Remaining, Acc) ->
case Remaining of
0 ->
lists:reverse(Acc);
_ ->
Byte = erlang:'band'(Value, 16#FF),
ia64_write_le48(erlang:'bsr'(Value, 8), Remaining - 1, [Byte | Acc])
end.
-file("src/packkit/internal/bcj.gleam", 977).
?DOC(false).
-spec list_take_n(list(integer()), integer(), list(integer())) -> list(integer()).
list_take_n(Items, Count, Acc) ->
case {Count, Items} of
{0, _} ->
lists:reverse(Acc);
{_, []} ->
lists:reverse(Acc);
{_, [B | Rest]} ->
list_take_n(Rest, Count - 1, [B | Acc])
end.
-file("src/packkit/internal/bcj.gleam", 966).
?DOC(false).
-spec list_take_range(list(integer()), integer(), integer()) -> list(integer()).
list_take_range(Items, Start, Count) ->
case Start of
0 ->
list_take_n(Items, Count, []);
_ ->
case Items of
[] ->
[];
[_ | Rest] ->
list_take_range(Rest, Start - 1, Count)
end
end.
-file("src/packkit/internal/bcj.gleam", 1003).
?DOC(false).
-spec list_replace_head(list(integer()), list(integer())) -> list(integer()).
list_replace_head(Items, Replacement) ->
case Replacement of
[] ->
Items;
[R | Rest_rep] ->
case Items of
[] ->
[];
[_ | Rest] ->
[R | list_replace_head(Rest, Rest_rep)]
end
end.
-file("src/packkit/internal/bcj.gleam", 985).
?DOC(false).
-spec list_replace_range(list(integer()), integer(), list(integer())) -> list(integer()).
list_replace_range(Items, Start, Replacement) ->
case Start of
0 ->
list_replace_head(Items, Replacement);
_ ->
case Items of
[] ->
[];
[Head | Rest] ->
[Head | list_replace_range(Rest, Start - 1, Replacement)]
end
end.
-file("src/packkit/internal/bcj.gleam", 195).
?DOC(false).
-spec x86_resolve_dest_loop(integer(), integer(), integer(), integer()) -> integer().
x86_resolve_dest_loop(_, Subtract, Prev_mask, Dest) ->
Bit_number = mask_to_bit_number(erlang:'bsr'(Prev_mask, 1)),
Probe_byte = erlang:'band'(erlang:'bsr'(Dest, 24 - (Bit_number * 8)), 16#FF),
case test_msb(Probe_byte) of
false ->
Dest;
true ->
Xor_mask = case Bit_number of
0 ->
16#FFFFFFFF;
N ->
erlang:'band'(
erlang:'bsl'(1, 32 - (N * 8)) - 1,
16#FFFFFFFF
)
end,
New_src = erlang:'bxor'(Dest, Xor_mask),
erlang:'band'((New_src - Subtract) + 16#100000000, 16#FFFFFFFF)
end.
-file("src/packkit/internal/bcj.gleam", 187).
?DOC(false).
-spec x86_resolve_dest(integer(), integer(), integer()) -> integer().
x86_resolve_dest(Src, Subtract, Prev_mask) ->
Dest = erlang:'band'((Src - Subtract) + 16#100000000, 16#FFFFFFFF),
case Prev_mask of
0 ->
Dest;
_ ->
x86_resolve_dest_loop(Src, Subtract, Prev_mask, Dest)
end.
-file("src/packkit/internal/bcj.gleam", 657).
?DOC(false).
-spec arm64_bl_decode(integer(), integer()) -> integer().
arm64_bl_decode(Instr, Pc) ->
Pc_words = erlang:'bsr'(Pc, 2),
Neg_pc = erlang:'band'(16#100000000 - Pc_words, 16#FFFFFFFF),
_pipe = erlang:'bor'(
16#94000000,
erlang:'band'(Instr + Neg_pc, 16#03FFFFFF)
),
erlang:'band'(_pipe, 16#FFFFFFFF).
-file("src/packkit/internal/bcj.gleam", 680).
?DOC(false).
-spec arm64_adrp_apply(integer(), integer(), integer()) -> integer().
arm64_adrp_apply(Instr, Src, Pc) ->
Pc_pages = erlang:'bsr'(Pc, 12),
Neg_pc = erlang:'band'(16#100000000 - Pc_pages, 16#FFFFFFFF),
Dest = erlang:'band'(Src + Neg_pc, 16#FFFFFFFF),
Base = erlang:'band'(Instr, 16#9000001F),
High_immlo = erlang:'bsl'(erlang:'band'(Dest, 3), 29),
Mid_immhi = erlang:'bsl'(erlang:'band'(Dest, 16#0003FFFC), 3),
Sign_replica = erlang:'band'(
16#100000000 - erlang:'band'(Dest, 16#00020000),
16#00E00000
),
_pipe = erlang:'bor'(
erlang:'bor'(Base, High_immlo),
erlang:'bor'(Mid_immhi, Sign_replica)
),
erlang:'band'(_pipe, 16#FFFFFFFF).
-file("src/packkit/internal/bcj.gleam", 665).
?DOC(false).
-spec arm64_adrp_decode(integer(), integer()) -> {ok, integer()} | {error, nil}.
arm64_adrp_decode(Instr, Pc) ->
Src = erlang:'bor'(
erlang:'band'(erlang:'bsr'(Instr, 29), 3),
erlang:'band'(erlang:'bsr'(Instr, 3), 16#001FFFFC)
),
case erlang:'band'(Src + 16#00020000, 16#001C0000) of
0 ->
{ok, arm64_adrp_apply(Instr, Src, Pc)};
_ ->
{error, nil}
end.
-file("src/packkit/internal/bcj.gleam", 699).
?DOC(false).
-spec write_le32(integer()) -> bitstring().
write_le32(Value) ->
Masked = erlang:'band'(Value, 16#FFFFFFFF),
<<(erlang:'band'(Masked, 16#FF)),
(erlang:'band'(erlang:'bsr'(Masked, 8), 16#FF)),
(erlang:'band'(erlang:'bsr'(Masked, 16), 16#FF)),
(erlang:'band'(erlang:'bsr'(Masked, 24), 16#FF))>>.
-file("src/packkit/internal/bcj.gleam", 583).
?DOC(false).
-spec arm64_decode_words(bitstring(), integer(), integer(), bitstring()) -> bitstring().
arm64_decode_words(Bytes, Start_offset, Word_index, Acc) ->
case Bytes of
<<B0, B1, B2, B3, Rest/binary>> ->
Instr = erlang:'bor'(
erlang:'bor'(erlang:'bsl'(B3, 24), erlang:'bsl'(B2, 16)),
erlang:'bor'(erlang:'bsl'(B1, 8), B0)
),
Pc = Start_offset + (Word_index * 4),
case classify_arm64_instr(Instr) of
arm64_bl ->
New_instr = arm64_bl_decode(Instr, Pc),
arm64_decode_words(
Rest,
Start_offset,
Word_index + 1,
gleam_stdlib:bit_array_concat(
[Acc, write_le32(New_instr)]
)
);
arm64_adrp ->
case arm64_adrp_decode(Instr, Pc) of
{ok, New_instr@1} ->
arm64_decode_words(
Rest,
Start_offset,
Word_index + 1,
gleam_stdlib:bit_array_concat(
[Acc, write_le32(New_instr@1)]
)
);
{error, nil} ->
arm64_decode_words(
Rest,
Start_offset,
Word_index + 1,
gleam_stdlib:bit_array_concat(
[Acc, <<B0, B1, B2, B3>>]
)
)
end;
arm64_other ->
arm64_decode_words(
Rest,
Start_offset,
Word_index + 1,
gleam_stdlib:bit_array_concat([Acc, <<B0, B1, B2, B3>>])
)
end;
_ ->
Acc
end.
-file("src/packkit/internal/bcj.gleam", 561).
?DOC(false).
-spec arm64_decode(bitstring(), integer()) -> bitstring().
arm64_decode(Bytes, Start_offset) ->
Total = erlang:byte_size(Bytes),
Aligned = Total - (Total rem 4),
case Aligned of
0 ->
Bytes;
_ ->
case {gleam_stdlib:bit_array_slice(Bytes, 0, Aligned),
gleam_stdlib:bit_array_slice(Bytes, Aligned, Total - Aligned)} of
{{ok, Head}, {ok, Tail}} ->
Body = arm64_decode_words(Head, Start_offset, 0, <<>>),
gleam_stdlib:bit_array_concat([Body, Tail]);
{_, _} ->
Bytes
end
end.
-file("src/packkit/internal/bcj.gleam", 736).
?DOC(false).
-spec arm_decode_words(bitstring(), integer(), integer(), bitstring()) -> bitstring().
arm_decode_words(Bytes, Start_offset, Word_index, Acc) ->
case Bytes of
<<B0, B1, B2, 16#EB, Rest/binary>> ->
Src = erlang:'bor'(
erlang:'bor'(erlang:'bsl'(B2, 16), erlang:'bsl'(B1, 8)),
B0
),
Src_words = erlang:'bsl'(Src, 2),
Abs_byte_target = erlang:'band'(Src_words, 16#FFFFFFFF),
New_target_bytes = erlang:'band'(
(Abs_byte_target - ((Start_offset + (Word_index * 4)) + 8)) + 16#100000000,
16#FFFFFFFF
),
New_src = erlang:'bsr'(New_target_bytes, 2),
New_b0 = erlang:'band'(New_src, 16#FF),
New_b1 = erlang:'band'(erlang:'bsr'(New_src, 8), 16#FF),
New_b2 = erlang:'band'(erlang:'bsr'(New_src, 16), 16#FF),
arm_decode_words(
Rest,
Start_offset,
Word_index + 1,
gleam_stdlib:bit_array_concat(
[Acc, <<New_b0, New_b1, New_b2, 16#EB>>]
)
);
<<B0@1, B1@1, B2@1, B3, Rest@1/binary>> ->
arm_decode_words(
Rest@1,
Start_offset,
Word_index + 1,
gleam_stdlib:bit_array_concat([Acc, <<B0@1, B1@1, B2@1, B3>>])
);
_ ->
Acc
end.
-file("src/packkit/internal/bcj.gleam", 714).
?DOC(false).
-spec arm_decode(bitstring(), integer()) -> bitstring().
arm_decode(Bytes, Start_offset) ->
Total = erlang:byte_size(Bytes),
Aligned = Total - (Total rem 4),
case Aligned of
0 ->
Bytes;
_ ->
case {gleam_stdlib:bit_array_slice(Bytes, 0, Aligned),
gleam_stdlib:bit_array_slice(Bytes, Aligned, Total - Aligned)} of
{{ok, Head}, {ok, Tail}} ->
Body = arm_decode_words(Head, Start_offset, 0, <<>>),
gleam_stdlib:bit_array_concat([Body, Tail]);
{_, _} ->
Bytes
end
end.
-file("src/packkit/internal/bcj.gleam", 893).
?DOC(false).
-spec ia64_process_slot(list(integer()), integer(), integer()) -> list(integer()).
ia64_process_slot(Bytes_list, Bit_pos, Now_pos) ->
Byte_pos = erlang:'bsr'(Bit_pos, 3),
Bit_res = erlang:'band'(Bit_pos, 7),
Six = list_take_range(Bytes_list, Byte_pos, 6),
case erlang:length(Six) =:= 6 of
false ->
Bytes_list;
true ->
Instruction = ia64_read_le48(Six, 0, 0),
Inst_norm = erlang:'bsr'(Instruction, Bit_res),
Major = erlang:'band'(erlang:'bsr'(Inst_norm, 37), 16#F),
Middle = erlang:'band'(erlang:'bsr'(Inst_norm, 9), 16#7),
case (Major =:= 16#5) andalso (Middle =:= 0) of
false ->
Bytes_list;
true ->
Src_lo = erlang:'band'(
erlang:'bsr'(Inst_norm, 13),
16#FFFFF
),
Src_hi_bit = erlang:'band'(erlang:'bsr'(Inst_norm, 36), 1),
Src = erlang:'bsl'(Src_lo + (Src_hi_bit * 16#100000), 4),
Dest_byte = erlang:'band'(
(Src - Now_pos) + 16#100000000,
16#FFFFFFFF
),
Dest = erlang:'bsr'(Dest_byte, 4),
New_inst_norm = ia64_rewrite_inst_norm(Inst_norm, Dest),
Low_mask = erlang:'bsl'(1, Bit_res) - 1,
Preserved = erlang:'band'(Instruction, Low_mask),
New_instruction = Preserved + erlang:'bsl'(
New_inst_norm,
Bit_res
),
New_six = ia64_write_le48(New_instruction, 6, []),
list_replace_range(Bytes_list, Byte_pos, New_six)
end
end.
-file("src/packkit/internal/bcj.gleam", 877).
?DOC(false).
-spec ia64_process_slots(
list(integer()),
integer(),
integer(),
integer(),
integer()
) -> list(integer()).
ia64_process_slots(Bytes_list, Mask, Slot, Bit_pos, Now_pos) ->
gleam@bool:guard(
Slot >= 3,
Bytes_list,
fun() ->
Slot_active = erlang:'band'(erlang:'bsr'(Mask, Slot), 1) =:= 1,
Updated = case Slot_active of
true ->
ia64_process_slot(Bytes_list, Bit_pos, Now_pos);
false ->
Bytes_list
end,
ia64_process_slots(Updated, Mask, Slot + 1, Bit_pos + 41, Now_pos)
end
).
-file("src/packkit/internal/bcj.gleam", 850).
?DOC(false).
-spec ia64_decode_bundle(bitstring(), integer()) -> bitstring().
ia64_decode_bundle(Bundle, Now_pos) ->
case Bundle of
<<B0, _/binary>> ->
Template = erlang:'band'(B0, 16#1F),
Mask = ia64_branch_mask(Template),
case Mask of
0 ->
Bundle;
_ ->
Byte_list = bit_array_to_byte_list(Bundle, []),
Updated = ia64_process_slots(Byte_list, Mask, 0, 5, Now_pos),
byte_list_to_bit_array(Updated, <<>>)
end;
_ ->
Bundle
end.
-file("src/packkit/internal/bcj.gleam", 829).
?DOC(false).
-spec ia64_decode_bundles(bitstring(), integer(), integer(), bitstring()) -> bitstring().
ia64_decode_bundles(Bytes, Start_offset, Bundle_index, Acc) ->
case Bytes of
<<Bundle:16/binary, Rest/binary>> ->
Now_pos = Start_offset + (Bundle_index * 16),
New_bundle = ia64_decode_bundle(Bundle, Now_pos),
ia64_decode_bundles(
Rest,
Start_offset,
Bundle_index + 1,
gleam_stdlib:bit_array_concat([Acc, New_bundle])
);
_ ->
Acc
end.
-file("src/packkit/internal/bcj.gleam", 807).
?DOC(false).
-spec ia64_decode(bitstring(), integer()) -> bitstring().
ia64_decode(Bytes, Start_offset) ->
Total = erlang:byte_size(Bytes),
Aligned = Total - (Total rem 16),
case Aligned of
0 ->
Bytes;
_ ->
case {gleam_stdlib:bit_array_slice(Bytes, 0, Aligned),
gleam_stdlib:bit_array_slice(Bytes, Aligned, Total - Aligned)} of
{{ok, Head}, {ok, Tail}} ->
Body = ia64_decode_bundles(Head, Start_offset, 0, <<>>),
gleam_stdlib:bit_array_concat([Body, Tail]);
{_, _} ->
Bytes
end
end.
-file("src/packkit/internal/bcj.gleam", 1097).
?DOC(false).
-spec riscv_decode_jal(
list(integer()),
integer(),
integer(),
integer(),
integer(),
integer()
) -> {list(integer()), integer()}.
riscv_decode_jal(Bytes_list, Pos, B1, B2, B3, Start_offset) ->
case erlang:'band'(B1, 16#0D) of
0 ->
Pc = Start_offset + Pos,
Addr_a = erlang:'bsl'(erlang:'band'(B1, 16#F0), 13),
Addr_b = erlang:'bsl'(B2, 9),
Addr_c = erlang:'bsl'(B3, 1),
Addr = erlang:'band'(
(((Addr_a + Addr_b) + Addr_c) - Pc) + 16#100000000,
16#FFFFFFFF
),
New_b1 = erlang:'bor'(
erlang:'band'(B1, 16#0F),
erlang:'band'(erlang:'bsr'(Addr, 8), 16#F0)
),
New_b2 = erlang:'bor'(
erlang:'bor'(
erlang:'band'(erlang:'bsr'(Addr, 16), 16#0F),
erlang:'band'(erlang:'bsr'(Addr, 7), 16#10)
),
erlang:'band'(erlang:'bsl'(Addr, 4), 16#E0)
),
New_b3 = erlang:'bor'(
erlang:'band'(erlang:'bsr'(Addr, 4), 16#7F),
erlang:'band'(erlang:'bsr'(Addr, 13), 16#80)
),
Updated = list_replace_range(
Bytes_list,
Pos + 1,
[New_b1, New_b2, New_b3]
),
{Updated, 4};
_ ->
{Bytes_list, 2}
end.
-file("src/packkit/internal/bcj.gleam", 1252).
?DOC(false).
-spec not_auipc_pair(integer(), integer()) -> boolean().
not_auipc_pair(Auipc, Inst2) ->
Shifted = erlang:'band'(erlang:'bsl'(Auipc, 8), 16#FFFFFFFF),
Diff = erlang:'band'((Inst2 - 3) + 16#100000000, 16#FFFFFFFF),
erlang:'band'(erlang:'bxor'(Shifted, Diff), 16#F8003) /= 0.
-file("src/packkit/internal/bcj.gleam", 1260).
?DOC(false).
-spec not_special_auipc(integer(), integer()) -> boolean().
not_special_auipc(Auipc, Inst2_rs1) ->
Diff = erlang:'band'((Auipc - 16#3117) + 16#100000000, 16#FFFFFFFF),
Lhs = erlang:'band'(erlang:'bsl'(Diff, 18), 16#FFFFFFFF),
Rhs = erlang:'band'(Inst2_rs1, 16#1D),
Lhs >= Rhs.
-file("src/packkit/internal/bcj.gleam", 1269).
?DOC(false).
-spec le32_bytes(integer()) -> list(integer()).
le32_bytes(Value) ->
Masked = erlang:'band'(Value, 16#FFFFFFFF),
[erlang:'band'(Masked, 16#FF),
erlang:'band'(erlang:'bsr'(Masked, 8), 16#FF),
erlang:'band'(erlang:'bsr'(Masked, 16), 16#FF),
erlang:'band'(erlang:'bsr'(Masked, 24), 16#FF)].
-file("src/packkit/internal/bcj.gleam", 1188).
?DOC(false).
-spec riscv_decode_pair_apply(list(integer()), integer(), integer(), integer()) -> {list(integer()),
integer()}.
riscv_decode_pair_apply(Bytes_list, Pos, Inst, Inst2) ->
Addr_base = erlang:'band'(Inst, 16#FFFFF000),
Addr = erlang:'band'(Addr_base + erlang:'bsr'(Inst2, 20), 16#FFFFFFFF),
New_inst = erlang:'bor'(
16#17 + erlang:'bsl'(2, 7),
erlang:'band'(erlang:'bsl'(Inst2, 12), 16#FFFFFFFF)
),
New_inst2 = Addr,
Bytes_inst = le32_bytes(New_inst),
Bytes_inst2 = le32_bytes(New_inst2),
Updated = list_replace_range(
Bytes_list,
Pos,
lists:append(Bytes_inst, Bytes_inst2)
),
{Updated, 8}.
-file("src/packkit/internal/bcj.gleam", 1178).
?DOC(false).
-spec riscv_decode_pair(list(integer()), integer(), integer(), integer()) -> {list(integer()),
integer()}.
riscv_decode_pair(Bytes_list, Pos, Inst, Inst2) ->
gleam@bool:guard(
not_auipc_pair(Inst, Inst2),
{Bytes_list, 6},
fun() -> riscv_decode_pair_apply(Bytes_list, Pos, Inst, Inst2) end
).
-file("src/packkit/internal/bcj.gleam", 1210).
?DOC(false).
-spec riscv_decode_special_auipc(
list(integer()),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer()
) -> {list(integer()), integer()}.
riscv_decode_special_auipc(Bytes_list, Pos, Inst, B4, B5, B6, B7, Start_offset) ->
Inst2_rs1 = erlang:'bsr'(Inst, 27),
gleam@bool:guard(
not_special_auipc(Inst, Inst2_rs1),
{Bytes_list, 4},
fun() ->
Addr_be = ((erlang:'bsl'(B4, 24) + erlang:'bsl'(B5, 16)) + erlang:'bsl'(
B6,
8
))
+ B7,
Pc = Start_offset + Pos,
Addr = erlang:'band'((Addr_be - Pc) + 16#100000000, 16#FFFFFFFF),
New_inst2 = erlang:'bor'(
erlang:'bsr'(Inst, 12),
erlang:'band'(erlang:'bsl'(Addr, 20), 16#FFFFFFFF)
),
Auipc_imm = begin
_pipe = erlang:'band'(Addr + 16#800, 16#FFFFFFFF),
erlang:'band'(_pipe, 16#FFFFF000)
end,
New_inst = erlang:'bor'(
erlang:'bor'(16#17, erlang:'bsl'(Inst2_rs1, 7)),
Auipc_imm
),
Bytes_inst = le32_bytes(New_inst),
Bytes_inst2 = le32_bytes(New_inst2),
Updated = list_replace_range(
Bytes_list,
Pos,
lists:append(Bytes_inst, Bytes_inst2)
),
{Updated, 8}
end
).
-file("src/packkit/internal/bcj.gleam", 1139).
?DOC(false).
-spec riscv_decode_auipc(
list(integer()),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer()
) -> {list(integer()), integer()}.
riscv_decode_auipc(
Bytes_list,
Pos,
B0,
B1,
B2,
B3,
B4,
B5,
B6,
B7,
Start_offset
) ->
Inst = ((B0 + erlang:'bsl'(B1, 8)) + erlang:'bsl'(B2, 16)) + erlang:'bsl'(
B3,
24
),
Inst2_le = ((B4 + erlang:'bsl'(B5, 8)) + erlang:'bsl'(B6, 16)) + erlang:'bsl'(
B7,
24
),
case erlang:'band'(Inst, 16#E80) of
0 ->
riscv_decode_special_auipc(
Bytes_list,
Pos,
Inst,
B4,
B5,
B6,
B7,
Start_offset
);
_ ->
riscv_decode_pair(Bytes_list, Pos, Inst, Inst2_le)
end.
-file("src/packkit/internal/bcj.gleam", 1064).
?DOC(false).
-spec riscv_step(list(integer()), integer(), integer()) -> {list(integer()),
integer()}.
riscv_step(Bytes_list, Pos, Start_offset) ->
Slice = list_take_range(Bytes_list, Pos, 8),
case Slice of
[B0, B1, B2, B3, B4, B5, B6, B7] ->
case B0 of
16#EF ->
riscv_decode_jal(Bytes_list, Pos, B1, B2, B3, Start_offset);
_ ->
case erlang:'band'(B0, 16#7F) =:= 16#17 of
true ->
riscv_decode_auipc(
Bytes_list,
Pos,
B0,
B1,
B2,
B3,
B4,
B5,
B6,
B7,
Start_offset
);
false ->
{Bytes_list, 2}
end
end;
_ ->
{Bytes_list, 2}
end.
-file("src/packkit/internal/bcj.gleam", 1053).
?DOC(false).
-spec riscv_decode_loop(list(integer()), integer(), integer(), integer()) -> list(integer()).
riscv_decode_loop(Bytes_list, Pos, Limit, Start_offset) ->
gleam@bool:guard(
Pos > Limit,
Bytes_list,
fun() ->
{Updated, Advance} = riscv_step(Bytes_list, Pos, Start_offset),
riscv_decode_loop(Updated, Pos + Advance, Limit, Start_offset)
end
).
-file("src/packkit/internal/bcj.gleam", 1037).
?DOC(false).
-spec riscv_decode(bitstring(), integer()) -> bitstring().
riscv_decode(Bytes, Start_offset) ->
Aligned_start = erlang:'band'(Start_offset, 16#FFFFFFFF - 1),
Total = erlang:byte_size(Bytes),
case Total < 8 of
true ->
Bytes;
false ->
Byte_list = bit_array_to_byte_list(Bytes, []),
Decoded = riscv_decode_loop(Byte_list, 0, Total - 8, Aligned_start),
byte_list_to_bit_array(Decoded, <<>>)
end.
-file("src/packkit/internal/bcj.gleam", 495).
?DOC(false).
-spec sparc_apply(
integer(),
integer(),
integer(),
integer(),
bitstring(),
integer(),
integer(),
bitstring()
) -> bitstring().
sparc_apply(B0, B1, B2, B3, Rest, Start_offset, Word_index, Acc) ->
Src = begin
_pipe = erlang:'bor'(
erlang:'bor'(erlang:'bsl'(B0, 24), erlang:'bsl'(B1, 16)),
erlang:'bor'(erlang:'bsl'(B2, 8), B3)
),
_pipe@1 = erlang:'bsl'(_pipe, 2),
erlang:'band'(_pipe@1, 16#FFFFFFFF)
end,
Dest = begin
_pipe@2 = erlang:'band'(
(Src - (Start_offset + (Word_index * 4))) + 16#100000000,
16#FFFFFFFF
),
erlang:'bsr'(_pipe@2, 2)
end,
Sign_bit = erlang:'band'(erlang:'bsr'(Dest, 22), 1),
Sign_word = case Sign_bit of
0 ->
0;
_ ->
16#100000000 - 1
end,
Sign_ext = begin
_pipe@3 = erlang:'band'(erlang:'bsl'(Sign_word, 22), 16#3FFFFFFF),
erlang:'band'(_pipe@3, 16#FFFFFFFF)
end,
Combined = erlang:'bor'(
erlang:'bor'(Sign_ext, erlang:'band'(Dest, 16#3FFFFF)),
16#40000000
),
New_b0 = erlang:'band'(erlang:'bsr'(Combined, 24), 16#FF),
New_b1 = erlang:'band'(erlang:'bsr'(Combined, 16), 16#FF),
New_b2 = erlang:'band'(erlang:'bsr'(Combined, 8), 16#FF),
New_b3 = erlang:'band'(Combined, 16#FF),
sparc_decode_words(
Rest,
Start_offset,
Word_index + 1,
gleam_stdlib:bit_array_concat([Acc, <<New_b0, New_b1, New_b2, New_b3>>])
).
-file("src/packkit/internal/bcj.gleam", 468).
?DOC(false).
-spec sparc_decode_words(bitstring(), integer(), integer(), bitstring()) -> bitstring().
sparc_decode_words(Bytes, Start_offset, Word_index, Acc) ->
case Bytes of
<<B0, B1, B2, B3, Rest/binary>> ->
case is_sparc_call(B0, B1) of
true ->
sparc_apply(
B0,
B1,
B2,
B3,
Rest,
Start_offset,
Word_index,
Acc
);
false ->
sparc_decode_words(
Rest,
Start_offset,
Word_index + 1,
gleam_stdlib:bit_array_concat([Acc, <<B0, B1, B2, B3>>])
)
end;
_ ->
Acc
end.
-file("src/packkit/internal/bcj.gleam", 446).
?DOC(false).
-spec sparc_decode(bitstring(), integer()) -> bitstring().
sparc_decode(Bytes, Start_offset) ->
Total = erlang:byte_size(Bytes),
Aligned = Total - (Total rem 4),
case Aligned of
0 ->
Bytes;
_ ->
case {gleam_stdlib:bit_array_slice(Bytes, 0, Aligned),
gleam_stdlib:bit_array_slice(Bytes, Aligned, Total - Aligned)} of
{{ok, Head}, {ok, Tail}} ->
Body = sparc_decode_words(Head, Start_offset, 0, <<>>),
gleam_stdlib:bit_array_concat([Body, Tail]);
{_, _} ->
Bytes
end
end.
-file("src/packkit/internal/bcj.gleam", 393).
?DOC(false).
-spec armthumb_apply(
integer(),
integer(),
integer(),
integer(),
bitstring(),
integer(),
integer(),
integer(),
bitstring()
) -> bitstring().
armthumb_apply(B0, B1, B2, B3, Rest, Start_offset, Pos, Limit, Acc) ->
Src = erlang:'bor'(
erlang:'bor'(
erlang:'bsl'(erlang:'band'(B1, 7), 19),
erlang:'bsl'(B0, 11)
),
erlang:'bor'(erlang:'bsl'(erlang:'band'(B3, 7), 8), B2)
),
Src_bytes = erlang:'bsl'(Src, 1),
Dest = begin
_pipe = erlang:'band'(
(Src_bytes - ((Start_offset + Pos) + 4)) + 16#100000000,
16#FFFFFFFF
),
erlang:'bsr'(_pipe, 1)
end,
New_b1 = erlang:'bor'(16#F0, erlang:'band'(erlang:'bsr'(Dest, 19), 16#07)),
New_b0 = erlang:'band'(erlang:'bsr'(Dest, 11), 16#FF),
New_b3 = erlang:'bor'(16#F8, erlang:'band'(erlang:'bsr'(Dest, 8), 16#07)),
New_b2 = erlang:'band'(Dest, 16#FF),
armthumb_decode_loop(
Rest,
Start_offset,
Pos + 4,
Limit,
gleam_stdlib:bit_array_concat([Acc, <<New_b0, New_b1, New_b2, New_b3>>])
).
-file("src/packkit/internal/bcj.gleam", 348).
?DOC(false).
-spec armthumb_decode_loop(
bitstring(),
integer(),
integer(),
integer(),
bitstring()
) -> bitstring().
armthumb_decode_loop(Remaining, Start_offset, Pos, Limit, Acc) ->
case Pos > Limit of
true ->
gleam_stdlib:bit_array_concat([Acc, Remaining]);
false ->
case Remaining of
<<B0, B1, B2, B3, Rest/binary>> ->
case is_armthumb_bl(B1, B3) of
true ->
armthumb_apply(
B0,
B1,
B2,
B3,
Rest,
Start_offset,
Pos,
Limit,
Acc
);
false ->
armthumb_decode_loop(
gleam_stdlib:bit_array_concat(
[<<B2, B3>>, Rest]
),
Start_offset,
Pos + 2,
Limit,
gleam_stdlib:bit_array_concat([Acc, <<B0, B1>>])
)
end;
_ ->
gleam_stdlib:bit_array_concat([Acc, Remaining])
end
end.
-file("src/packkit/internal/bcj.gleam", 337).
?DOC(false).
-spec armthumb_decode(bitstring(), integer()) -> bitstring().
armthumb_decode(Bytes, Start_offset) ->
Total = erlang:byte_size(Bytes),
case Total < 4 of
true ->
Bytes;
false ->
armthumb_decode_loop(Bytes, Start_offset, 0, Total - 4, <<>>)
end.
-file("src/packkit/internal/bcj.gleam", 289).
?DOC(false).
-spec powerpc_apply(
integer(),
integer(),
integer(),
integer(),
bitstring(),
integer(),
integer(),
bitstring()
) -> bitstring().
powerpc_apply(B0, B1, B2, B3, Rest, Start_offset, Word_index, Acc) ->
Src = erlang:'bor'(
erlang:'bor'(
erlang:'bsl'(erlang:'band'(B0, 3), 24),
erlang:'bsl'(B1, 16)
),
erlang:'bor'(erlang:'bsl'(B2, 8), erlang:'band'(B3, 16#FC))
),
Dest = erlang:'band'(
(Src - (Start_offset + (Word_index * 4))) + 16#100000000,
16#FFFFFFFF
),
New_b0 = erlang:'bor'(16#48, erlang:'band'(erlang:'bsr'(Dest, 24), 16#03)),
New_b1 = erlang:'band'(erlang:'bsr'(Dest, 16), 16#FF),
New_b2 = erlang:'band'(erlang:'bsr'(Dest, 8), 16#FF),
New_b3 = erlang:'bor'(erlang:'band'(B3, 16#03), erlang:'band'(Dest, 16#FC)),
powerpc_decode_words(
Rest,
Start_offset,
Word_index + 1,
gleam_stdlib:bit_array_concat([Acc, <<New_b0, New_b1, New_b2, New_b3>>])
).
-file("src/packkit/internal/bcj.gleam", 257).
?DOC(false).
-spec powerpc_decode_words(bitstring(), integer(), integer(), bitstring()) -> bitstring().
powerpc_decode_words(Bytes, Start_offset, Word_index, Acc) ->
case Bytes of
<<B0, B1, B2, B3, Rest/binary>> ->
case is_powerpc_branch_link(B0, B3) of
false ->
powerpc_decode_words(
Rest,
Start_offset,
Word_index + 1,
gleam_stdlib:bit_array_concat([Acc, <<B0, B1, B2, B3>>])
);
true ->
powerpc_apply(
B0,
B1,
B2,
B3,
Rest,
Start_offset,
Word_index,
Acc
)
end;
_ ->
Acc
end.
-file("src/packkit/internal/bcj.gleam", 235).
?DOC(false).
-spec powerpc_decode(bitstring(), integer()) -> bitstring().
powerpc_decode(Bytes, Start_offset) ->
Total = erlang:byte_size(Bytes),
Aligned = Total - (Total rem 4),
case Aligned of
0 ->
Bytes;
_ ->
case {gleam_stdlib:bit_array_slice(Bytes, 0, Aligned),
gleam_stdlib:bit_array_slice(Bytes, Aligned, Total - Aligned)} of
{{ok, Head}, {ok, Tail}} ->
Body = powerpc_decode_words(Head, Start_offset, 0, <<>>),
gleam_stdlib:bit_array_concat([Body, Tail]);
{_, _} ->
Bytes
end
end.
-file("src/packkit/internal/bcj.gleam", 96).
?DOC(false).
-spec x86_try_decode_call(
list(integer()),
integer(),
integer(),
integer(),
x86_state(),
list(integer())
) -> list(integer()).
x86_try_decode_call(Remaining, Buffer_pos, Limit, Now_pos, State, Acc_reversed) ->
Offset = (Now_pos + Buffer_pos) - erlang:element(2, State),
Prev_pos_after = Now_pos + Buffer_pos,
Prev_mask_after = case Offset > 5 of
true ->
0;
false ->
shift_mask_left(erlang:element(3, State), Offset)
end,
{Opcode, D0, D1, D2, D3, Tail} = case Remaining of
[Op, B0, B1, B2, B3 | Rest] ->
{Op, B0, B1, B2, B3, Rest};
_ ->
{0, 0, 0, 0, 0, []}
end,
case is_decodable(D3, Prev_mask_after) of
false ->
Bumped = case test_msb(D3) of
true ->
erlang:'bor'(erlang:'bor'(Prev_mask_after, 1), 16#10);
false ->
erlang:'bor'(Prev_mask_after, 1)
end,
x86_decode_loop(
[D0, D1, D2, D3 | Tail],
Buffer_pos + 1,
Limit,
Now_pos,
{x86_state, Prev_pos_after, Bumped},
[Opcode | Acc_reversed]
);
true ->
Src = erlang:'bor'(
erlang:'bor'(erlang:'bsl'(D3, 24), erlang:'bsl'(D2, 16)),
erlang:'bor'(erlang:'bsl'(D1, 8), D0)
),
Dest = x86_resolve_dest(
Src,
(Now_pos + Buffer_pos) + 5,
Prev_mask_after
),
New_d3 = case erlang:'band'(erlang:'bsr'(Dest, 24), 1) of
0 ->
0;
_ ->
16#FF
end,
New_d0 = erlang:'band'(Dest, 16#FF),
New_d1 = erlang:'band'(erlang:'bsr'(Dest, 8), 16#FF),
New_d2 = erlang:'band'(erlang:'bsr'(Dest, 16), 16#FF),
x86_decode_loop(
Tail,
Buffer_pos + 5,
Limit,
Now_pos,
{x86_state, Prev_pos_after, 0},
[New_d3, New_d2, New_d1, New_d0, Opcode | Acc_reversed]
)
end.
-file("src/packkit/internal/bcj.gleam", 58).
?DOC(false).
-spec x86_decode_loop(
list(integer()),
integer(),
integer(),
integer(),
x86_state(),
list(integer())
) -> list(integer()).
x86_decode_loop(Remaining, Buffer_pos, Limit, Now_pos, State, Acc_reversed) ->
case Remaining of
[] ->
lists:reverse(Acc_reversed);
[Byte_at_pos | Rest] ->
case Buffer_pos > Limit of
true ->
lists:append(lists:reverse(Acc_reversed), Remaining);
false ->
case Byte_at_pos of
16#E8 ->
x86_try_decode_call(
Remaining,
Buffer_pos,
Limit,
Now_pos,
State,
Acc_reversed
);
16#E9 ->
x86_try_decode_call(
Remaining,
Buffer_pos,
Limit,
Now_pos,
State,
Acc_reversed
);
_ ->
x86_decode_loop(
Rest,
Buffer_pos + 1,
Limit,
Now_pos,
State,
[Byte_at_pos | Acc_reversed]
)
end
end
end.
-file("src/packkit/internal/bcj.gleam", 29).
?DOC(false).
-spec x86_decode(bitstring(), integer()) -> bitstring().
x86_decode(Bytes, Start_offset) ->
Total = erlang:byte_size(Bytes),
case Total < 5 of
true ->
Bytes;
false ->
Byte_list = bit_array_to_byte_list(Bytes, []),
Initial = {x86_state, Start_offset - 5, 0},
Limit = Total - 5,
Decoded = x86_decode_loop(
Byte_list,
0,
Limit,
Start_offset,
Initial,
[]
),
byte_list_to_bit_array(Decoded, <<>>)
end.