ARRAY OF BYTE Parameters

Report any suspected bugs that you find
Locked
gray
Posts: 115
Joined: Tue Feb 12, 2019 2:59 am
Location: Mauritius

ARRAY OF BYTE Parameters

Post by gray » Wed Jan 31, 2024 1:11 pm

The ARM Cortex-M Oberon Programmers Guide states in section 4.1 ARRAY of BYTE:
If the formal parameter is an array of bytes with a fixed size it can accept actual parameters of any type, except POINTER, whose size is the same number of bytes [...]
Example 1:

Code: Select all

  TYPE Word = ARRAY 4 OF BYTE;

  PROCEDURE p0(value: Word);
    VAR x: BYTE;
  BEGIN
    x := value[0]
  END p0;

  PROCEDURE p1;
    VAR i: INTEGER;
  BEGIN
    p0(i)
  END p1;
The same section also says:
The converse situation is also catered for i.e. a procedure with a formal parameter of any type, except POINTER, can accept an actual parameter which is an array of bytes of the same size.
Example 2:

Code: Select all

  TYPE Word = ARRAY 4 OF BYTE;

  PROCEDURE p2(value: INTEGER);
    VAR x: INTEGER;
  BEGIN
    x := value
  END p2;

  PROCEDURE p3;
    VAR w: Word;
  BEGIN
    p2(w)
  END p3;
Looking at the assembly code of example 1:

Code: Select all

  PROCEDURE p0(value: Word);
    VAR x: BYTE;
  BEGIN
.     4     04H  0B501H          push     { r0, lr }
.     6     06H  0B081H          sub      sp,#4
    x := value[0]
  END p0;
.     8     08H  09801H          ldr      r0,[sp,#4]
.    10     0AH  07800H          ldrb     r0,[r0]
.    12     0CH  0A900H          add      r1,sp,#0
.    14     0EH  07008H          strb     r0,[r1]
.    16    010H  0B002H          add      sp,#8
.    18    012H  0BD00H          pop      { pc }

  PROCEDURE p1;
    VAR i: INTEGER;
  BEGIN
.    20    014H  0B500H          push     { lr }
.    22    016H  0B081H          sub      sp,#4
    p0(i)
.    24    018H  04668H          mov      r0,sp
  END p1;
.    26    01AH  0F7FFFFF3H      bl.w     -26 -> 4
.    30    01EH  0E000H          b        0 -> 34
.    32  <LineNo: 14>
.    34    022H  0B001H          add      sp,#4
.    36    024H  0BD00H          pop      { pc }
.    38    026H  046C0H          nop
Everythig is OK. 'p1' passes the address of 'i' to 'p0' (the stack pointer value), and 'p0' reads the value at that address.

Now example 2:

Code: Select all

  PROCEDURE p2(value: INTEGER);
    VAR x: INTEGER;
  BEGIN
.    40    028H  0B501H          push     { r0, lr }
.    42    02AH  0B081H          sub      sp,#4
    x := value
  END p2;
.    44    02CH  09801H          ldr      r0,[sp,#4]
.    46    02EH  09000H          str      r0,[sp]
.    48    030H  0B002H          add      sp,#8
.    50    032H  0BD00H          pop      { pc }

  PROCEDURE p3;
    VAR w: Word;
  BEGIN
.    52    034H  0B500H          push     { lr }
.    54    036H  0B081H          sub      sp,#4
    p2(w)
.    56    038H  04668H          mov      r0,sp
  END p3;
.    58    03AH  0F7FFFFF5H      bl.w     -22 -> 40
.    62    03EH  0E000H          b        0 -> 66
.    64  <LineNo: 26>
.    66    042H  0B001H          add      sp,#4
.    68    044H  0BD00H          pop      { pc }
.    70    046H  046C0H          nop
This does not work. 'p3' passes the address of 'w' to 'p2' (the stack pointer value), but 'p2' of course treats is as value parameter, hence reads the stack pointer value itself.

Either 1) I misunderstand the Guide, or 2) the situation of example 2 does not work for basic types (Astrobe for Cortex-M0 v9.1).

If I do understand the Guide correctly, the assembly code for 'p3' should read in this case with an INTEGER as "target" value parameter:

Code: Select all

  PROCEDURE p3;
    VAR w: Word;
  BEGIN
.    52    034H  0B500H          push     { lr }
.    54    036H  0B081H          sub      sp,#4
    p2(w)
.    56    038H  04668H          mov      r0,[sp]   (* <== here *)
  END p3;
.    58    03AH  0F7FFFFF5H      bl.w     -22 -> 40
.    62    03EH  0E000H          b        0 -> 66
.    64  <LineNo: 26>
.    66    042H  0B001H          add      sp,#4
.    68    044H  0BD00H          pop      { pc }
.    70    046H  046C0H          nop
PS: just to check, if we modify example 2 thusly (p2 with a VAR parameter):

Code: Select all

  PROCEDURE p2(VAR value: INTEGER);
    VAR x: INTEGER;
  BEGIN
    x := value
  END p2;

  PROCEDURE p3;
    VAR w: Word;
  BEGIN
    p2(w)
  END p3;
We get the correct behaviour, unsurprisingly, as now p2 expects an address:

Code: Select all

  PROCEDURE p2(VAR value: INTEGER);
    VAR x: INTEGER;
  BEGIN
.    40    028H  0B501H          push     { r0, lr }
.    42    02AH  0B081H          sub      sp,#4
    x := value
  END p2;
.    44    02CH  09801H          ldr      r0,[sp,#4]
.    46    02EH  06800H          ldr      r0,[r0]
.    48    030H  09000H          str      r0,[sp]
.    50    032H  0B002H          add      sp,#8
.    52    034H  0BD00H          pop      { pc }
.    54    036H  046C0H          nop

  PROCEDURE p3;
    VAR w: Word;
  BEGIN
.    56    038H  0B500H          push     { lr }
.    58    03AH  0B081H          sub      sp,#4
    p2(w)
.    60    03CH  04668H          mov      r0,sp
  END p3;
.    62    03EH  0F7FFFFF3H      bl.w     -26 -> 40
.    66    042H  0E000H          b        0 -> 70
.    68  <LineNo: 26>
.    70    046H  0B001H          add      sp,#4
.    72    048H  0BD00H          pop      { pc }
.    74    04AH  046C0H          nop
It's a workaround that works, but of course 'p3' should "adapt" for 'p2', not the other way around. :)
Last edited by gray on Sat Feb 03, 2024 2:00 am, edited 1 time in total.

cfbsoftware
Site Admin
Posts: 497
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: ARRAY OF BYTE Parameters

Post by cfbsoftware » Fri Feb 02, 2024 8:43 am

Thank you for your report. I can confirm that it is a problem and it will be fixed in the next Cortex-M0 maintenance release.

Locked