sasm: bugfix for LBRANCH/LCBRANCH size changes

- The LBRANCH and LCBRANCH directives
  create different instruction sequences
  depending on the jump distance.
  So the code size can shrink during the first pass
  when the jump distance can be determined (when the
  label that is the jump destination is parsed).
  In the long form, LOADREL/JUMP is used, which might
  or might not need 2 bytes of padding. With this bugfix,
  the padding is always added, either before or after
  the LOADREL indirect operand, so that the code
  size does not change depending on the padding
  required. Otherwise the code might shrink further
  on the second pass because a LBRANCH/LCBRANCH
  instruction no longer needs padding due to an
  earlier code size change.
This commit is contained in:
slederer 2025-04-07 00:25:32 +02:00
parent 3c32dff0a7
commit 3526060a19
2 changed files with 22 additions and 8 deletions

View file

@ -1616,7 +1616,7 @@ MEM_FREE_XT:
; Since the return stack is no longer valid afterwards, directly
; jumps to _MAIN instead of using RET.
; parameters: [ _MAIN entry point, start of heap address ]
; parameters: [ start of heap address ]
_MEM_INIT:
; initialize anchor chunk with start of heap address
; and heap size - header size

View file

@ -1515,8 +1515,6 @@ begin
end;
if dref^.symboldata.value <> value then
(* writeln('////// label changed value ', keyword, ' ',
dref^.symboldata.value, ' -> ', value); *)
dref^.symboldata.value := value;
end;
end;
@ -1872,9 +1870,9 @@ begin
if (pc and 3) = 0 then (* no padding *)
begin
pad := false;
(* total size 8 bytes *)
(* total size 10 bytes *)
offset := 4; (* offset for LOADREL *)
shrinkage := 6; (* difference to short form size *)
shrinkage := 8; (* difference to short form size *)
end
else
begin
@ -1892,9 +1890,17 @@ begin
encodeInstruction('JUMP', 0, encoded);
emitInstructionWord(encoded);
(* Padding is always done, so the length of the sequence does
not change depending on the position. The pad is either
placed before the address to align it on a word address,
or after, if it is already aligned. *)
if pad then
emitInstructionWord(0);
emitWord(value);
if not pad then
emitInstructionWord(0);
end
else
begin
@ -1937,9 +1943,9 @@ begin
if (pc and 3) = 2 then (* no padding *)
begin
pad := false;
(* total size 10 bytes *)
(* total size 12 bytes *)
offset := 4; (* offset for LOADREL *)
shrinkage := 8; (* difference to short form size *)
shrinkage := 10; (* difference to short form size *)
end
else
begin
@ -1967,9 +1973,17 @@ begin
encodeInstruction('JUMP', 0, encoded);
emitInstructionWord(encoded);
(* Padding is always done, so the length of the sequence does
not change depending on the position. The pad is either
placed before the address to align it on a word address,
or after, if it is already aligned. *)
if pad then
emitInstructionWord(0);
emitWord(value);
if not pad then
emitInstructionWord(0);
end
else
begin