@@ -317,7 +317,7 @@ flush(#state{stream_module = StreamModule, stream = Stream0} = State) ->
317317% %-----------------------------------------------------------------------------
318318-spec debugger (state ()) -> state ().
319319debugger (# state {stream_module = StreamModule , stream = Stream0 } = State ) ->
320- Stream1 = StreamModule :append (Stream0 , jit_riscv32_asm :bkpt ( 0 )),
320+ Stream1 = StreamModule :append (Stream0 , jit_riscv32_asm :c_ebreak ( )),
321321 State # state {stream = Stream1 }.
322322
323323% %-----------------------------------------------------------------------------
@@ -416,12 +416,7 @@ jump_table0(
416416 % Create jump table entry: AUIPC + JALR (8 bytes total)
417417 % This will be patched later in update_branches/2
418418 Offset = StreamModule :offset (Stream0 ),
419- % Placeholder: Load PC + upper20 bits
420- I1 = jit_riscv32_asm :auipc (a3 , 0 ),
421- % Placeholder: Jump to a3 + lower12 bits
422- I2 = jit_riscv32_asm :jalr (zero , a3 , 0 ),
423-
424- JumpEntry = <<I1 /binary , I2 /binary >>,
419+ JumpEntry = <<16#FFFFFFFF :32 , 16#FFFFFFFF :32 >>,
425420 Stream1 = StreamModule :append (Stream0 , JumpEntry ),
426421
427422 % Record both AUIPC and JALR offsets for patching
@@ -451,30 +446,49 @@ update_branches(
451446 Rel = LabelOffset - Offset ,
452447 NewInstr =
453448 case Type of
454- {adr , Reg } when Rel rem 4 =:= 0 -> pc_relative_address (Reg , Rel );
455- {adr , Reg } when Rel rem 4 =:= 2 -> pc_relative_address (Reg , Rel + 2 );
456- {far_branch , Size , TempReg } ->
449+ {adr , Reg } when Rel rem 4 =:= 0 ->
450+ % Generate pc_relative_address and pad to 8 bytes with NOP
451+ I = pc_relative_address (Reg , Rel ),
452+ case byte_size (I ) of
453+ 4 -> <<I /binary , (jit_riscv32_asm :nop ())/binary >>;
454+ 6 -> <<I /binary , (jit_riscv32_asm :c_nop ())/binary >>;
455+ 8 -> I
456+ end ;
457+ {adr , Reg } when Rel rem 4 =:= 2 ; Rel rem 4 =:= - 2 ->
458+ % Handle 2-byte aligned offsets and pad to 8 bytes
459+ % Handle both positive and negative offsets (Erlang rem can be negative)
460+ I = pc_relative_address (Reg , Rel ),
461+ case byte_size (I ) of
462+ 4 -> <<I /binary , (jit_riscv32_asm :nop ())/binary >>;
463+ 6 -> <<I /binary , (jit_riscv32_asm :c_nop ())/binary >>;
464+ 8 -> I
465+ end ;
466+ {far_branch , TempReg } ->
457467 % Check if branch can now be optimized to near branch
458468 if
459469 Rel >= - 1048576 andalso Rel =< 1048574 andalso (Rel rem 2 ) =:= 0 ->
460470 % RISC-V jal has ±1MB range
461471 % Optimize to near branch: jal + nops to fill original size
462472 DirectBranch = jit_riscv32_asm :jal (zero , Rel ),
463- % Fill remaining bytes with NOPs (RISC-V instructions are 4 bytes)
464- NopCount = ( Size - 4 ) div 4 ,
465- Nops = <<
466- << (jit_riscv32_asm :nop ())/binary >>
467- || _ <- lists : seq ( 1 , NopCount )
468- >>,
469- << DirectBranch / binary , Nops / binary >> ;
473+ case byte_size ( DirectBranch ) of
474+ 2 ->
475+ << DirectBranch / binary , ( jit_riscv32_asm : c_nop ())/ binary ,
476+ (jit_riscv32_asm :nop ())/binary >>;
477+ 4 ->
478+ << DirectBranch / binary , ( jit_riscv32_asm : nop ())/ binary >>
479+ end ;
470480 true ->
471481 % Keep far branch sequence: auipc + jalr (PC-relative, 8 bytes)
472482 % Split the relative offset into upper 20 bits and lower 12 bits
473483 Hi20 = (Rel + 16#800 ) bsr 12 ,
474484 Lo12 = Rel - (Hi20 bsl 12 ),
475485 I1 = jit_riscv32_asm :auipc (TempReg , Hi20 ),
476486 I2 = jit_riscv32_asm :jalr (zero , TempReg , Lo12 ),
477- <<I1 /binary , I2 /binary >>
487+ Entry = <<I1 /binary , I2 /binary >>,
488+ case byte_size (Entry ) of
489+ 6 -> <<Entry /binary , (jit_riscv32_asm :c_nop ())/binary >>;
490+ 8 -> Entry
491+ end
478492 end ;
479493 jump_table_auipc_jalr ->
480494 % Calculate PC-relative offset from AUIPC instruction to target
@@ -498,7 +512,12 @@ update_branches(
498512 % Encode AUIPC and JALR with computed offsets
499513 I1 = jit_riscv32_asm :auipc (a3 , Upper20 ),
500514 I2 = jit_riscv32_asm :jalr (zero , a3 , Lower12Signed ),
501- <<I1 /binary , I2 /binary >>
515+ % Map to 8 bytes
516+ JumpTableEntry = <<I1 /binary , I2 /binary >>,
517+ case byte_size (JumpTableEntry ) of
518+ 6 -> <<JumpTableEntry /binary , (jit_riscv32_asm :c_nop ())/binary >>;
519+ 8 -> JumpTableEntry
520+ end
502521 end ,
503522 Stream1 = StreamModule :replace (Stream0 , Offset , NewInstr ),
504523 update_branches (State # state {stream = Stream1 , branches = BranchesT }).
@@ -783,13 +802,10 @@ branch_to_label_code(
783802 % RISC-V: Far branch sequence using PC-relative auipc + jalr (8 bytes)
784803
785804 % Placeholder: auipc TempReg, 0
786- I1 = jit_riscv32_asm :auipc (TempReg , 0 ),
787805 % Placeholder: jalr zero, TempReg, 0
788- I2 = jit_riscv32_asm :jalr (zero , TempReg , 0 ),
789- CodeBlock = <<I1 /binary , I2 /binary >>,
790- SequenceSize = byte_size (CodeBlock ),
806+ CodeBlock = <<16#FFFFFFFF :32 , 16#FFFFFFFF :32 >>,
791807 % Add relocation entry
792- Reloc = {Label , Offset , {far_branch , SequenceSize , TempReg }},
808+ Reloc = {Label , Offset , {far_branch , TempReg }},
793809 State1 = State0 # state {branches = [Reloc | Branches ]},
794810 {State1 , CodeBlock };
795811branch_to_label_code (
@@ -799,13 +815,10 @@ branch_to_label_code(
799815 % Far branch sequence using PC-relative auipc + jalr (8 bytes)
800816
801817 % Placeholder: auipc t6, 0
802- I1 = jit_riscv32_asm :auipc (t6 , 0 ),
803818 % Placeholder: jalr zero, t6, 0
804- I2 = jit_riscv32_asm :jalr (zero , t6 , 0 ),
805- CodeBlock = <<I1 /binary , I2 /binary >>,
806- SequenceSize = byte_size (CodeBlock ),
819+ CodeBlock = <<16#FFFFFFFF :32 , 16#FFFFFFFF :32 >>,
807820 % Add relocation entry
808- Reloc = {Label , Offset , {far_branch , SequenceSize , t6 }},
821+ Reloc = {Label , Offset , {far_branch , t6 }},
809822 State1 = State0 # state {branches = [Reloc | Branches ]},
810823 {State1 , CodeBlock };
811824branch_to_label_code (# state {available_regs = []}, _Offset , _Label , _LabelLookup ) ->
@@ -2356,8 +2369,9 @@ set_continuation_to_label(
23562369 % resolved to point directly to the label's actual address (not the jump table entry)
23572370 Offset = StreamModule :offset (Stream0 ),
23582371 % Emit placeholder for pc_relative_address (auipc + addi)
2372+ % Reserve 8 bytes (2 x 32-bit instructions) with all-1s placeholder for flash programming
23592373 % The relocation will replace these with the correct offset
2360- I1 = pc_relative_address ( Temp , 4 ) ,
2374+ I1 = << 16#FFFFFFFF : 32 / little , 16#FFFFFFFF : 32 / little >> ,
23612375 Reloc = {Label , Offset , {adr , Temp }},
23622376 % Store continuation (jit_state is in a1)
23632377 I2 = jit_riscv32_asm :sw (? JITSTATE_REG , Temp , ? JITSTATE_CONTINUATION_OFFSET ),
@@ -2379,7 +2393,8 @@ set_continuation_to_offset(
23792393) ->
23802394 OffsetRef = make_ref (),
23812395 Offset = StreamModule :offset (Stream0 ),
2382- I1 = pc_relative_address (Temp , 4 ),
2396+ % Reserve 8 bytes with all-1s placeholder for flash programming
2397+ I1 = <<16#FFFFFFFF :32 /little , 16#FFFFFFFF :32 /little >>,
23832398 Reloc = {OffsetRef , Offset , {adr , Temp }},
23842399 % Store continuation (jit_state is in a1)
23852400 I2 = jit_riscv32_asm :sw (? JITSTATE_REG , Temp , ? JITSTATE_CONTINUATION_OFFSET ),
@@ -2659,8 +2674,11 @@ decrement_reductions_and_maybe_schedule_next(
26592674 NewI5 =
26602675 case pc_relative_address (Temp , NewI5Offset ) of
26612676 I when byte_size (I ) =:= 4 ->
2662- % Only auipc, pad with NOP
2677+ % Only auipc, pad with NOP (4 bytes)
26632678 <<I /binary , (jit_riscv32_asm :nop ())/binary >>;
2679+ I when byte_size (I ) =:= 6 ->
2680+ % auipc + c.addi, pad with c.nop (2 bytes)
2681+ <<I /binary , (jit_riscv32_asm :c_nop ())/binary >>;
26642682 I when byte_size (I ) =:= 8 ->
26652683 % auipc + addi, no padding needed
26662684 I
@@ -2798,10 +2816,11 @@ rewrite_cp_offset(
27982816 CPValue = NewOffset bsl 2 ,
27992817 NewMoveInstr = jit_riscv32_asm :li (TempReg , CPValue ),
28002818 % We reserved 8 bytes (2 instructions) for the CP value
2801- % If li generates only 4 bytes, pad with a NOP to maintain alignment
2819+ % Pad with NOP if needed to maintain alignment
28022820 PaddedInstr =
28032821 case byte_size (NewMoveInstr ) of
28042822 4 -> <<NewMoveInstr /binary , (jit_riscv32_asm :nop ())/binary >>;
2823+ 6 -> <<NewMoveInstr /binary , (jit_riscv32_asm :c_nop ())/binary >>;
28052824 8 -> NewMoveInstr
28062825 end ,
28072826 Stream1 = StreamModule :replace (Stream0 , RewriteOffset , PaddedInstr ),
@@ -2841,13 +2860,22 @@ return_labels_and_lines(
28412860 || {Label , LabelOffset } <- Labels , is_integer (Label )
28422861 ]),
28432862
2844- I1 = pc_relative_address (a0 , 12 ),
28452863 I2 = jit_riscv32_asm :ret (),
2864+ % Assume total size is 10 bytes (8-byte I1 + 2-byte c.ret)
2865+ % If actual is 8 bytes (6-byte I1 + 2-byte c.ret), we'll pad with 2 bytes
2866+ I1 = pc_relative_address (a0 , 10 ),
2867+ Prologue = <<I1 /binary , I2 /binary >>,
2868+ ProloguePadded =
2869+ case byte_size (Prologue ) of
2870+ 10 -> Prologue ;
2871+ % 2-byte padding
2872+ 8 -> <<Prologue /binary , 16#FFFF :16 >>
2873+ end ,
28462874 LabelsTable = <<<<Label :16 , Offset :32 >> || {Label , Offset } <- SortedLabels >>,
28472875 LinesTable = <<<<Line :16 , Offset :32 >> || {Line , Offset } <- SortedLines >>,
28482876 Stream1 = StreamModule :append (
28492877 Stream0 ,
2850- <<I1 / binary , I2 /binary , (length (SortedLabels )):16 , LabelsTable /binary ,
2878+ <<ProloguePadded /binary , (length (SortedLabels )):16 , LabelsTable /binary ,
28512879 (length (SortedLines )):16 , LinesTable /binary >>
28522880 ),
28532881 State # state {stream = Stream1 }.
@@ -3005,7 +3033,7 @@ args_regs(Args) ->
30053033 ).
30063034
30073035% %-----------------------------------------------------------------------------
3008- % % @doc Add a label at the current offset. Eventually align it with a nop.
3036+ % % @doc Add a label at the current offset.
30093037% % @end
30103038% % @param State current backend state
30113039% % @param Label the label number or reference
@@ -3014,15 +3042,7 @@ args_regs(Args) ->
30143042- spec add_label (state (), integer () | reference ()) -> state ().
30153043add_label (# state {stream_module = StreamModule , stream = Stream0 } = State0 , Label ) ->
30163044 Offset0 = StreamModule :offset (Stream0 ),
3017- {State1 , Offset1 } =
3018- if
3019- Offset0 rem 4 =:= 0 ->
3020- {State0 , Offset0 };
3021- true ->
3022- Stream1 = StreamModule :append (Stream0 , jit_riscv32_asm :nop ()),
3023- {State0 # state {stream = Stream1 }, Offset0 + 2 }
3024- end ,
3025- add_label (State1 , Label , Offset1 ).
3045+ add_label (State0 , Label , Offset0 ).
30263046
30273047% %-----------------------------------------------------------------------------
30283048% % @doc Add a label at a specific offset
0 commit comments