Alert: no free registers Question

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

Alert: no free registers Question

Post by gray » Thu May 16, 2024 2:09 am

The following test code is distilled from a real use case. This is with Astrobe for Cortex-M0 v9.2.

Code: Select all

MODULE M;
  VAR v0: INTEGER;

  PROCEDURE p0(i0, i1, i2, i3, i4, i5: INTEGER; i6: INTEGER; b7: BOOLEAN); END p0;
  PROCEDURE p1(i0, i1, i2, i3, i4, i5: INTEGER; b6: BOOLEAN; i7: INTEGER); END p1;

  PROCEDURE p2;
    VAR v1: INTEGER; b1: BOOLEAN;
  BEGIN
    p0(v0, v1, 0, 1, 2, 3, 4, b1);
    p1(v0, v1, 0, 1, 2, 3, b1, 4);
  END p2;
END M.
Compiling gives a 'no free registers' Alert for the call of 'p0'.

The cause of the Alert is evident in the assembly listing:

Code: Select all

    p0(v0, v1, 0, 1, 2, 3, 4, b1);
.    24    018H  0480EH          ldr      r0,[pc,#56] -> 84
.    26    01AH  06800H          ldr      r0,[r0]
.    28    01CH  09900H          ldr      r1,[sp]
.    30    01EH  02200H          movs     r2,#0
.    32    020H  02301H          movs     r3,#1
.    34    022H  02402H          movs     r4,#2
.    36    024H  02503H          movs     r5,#3
.    38    026H  02604H          movs     r6,#4
.    40    028H  0A801H          add      r0,sp,#4   <===
.    42    02AH  07807H          ldrb     r7,[r0]
I think I understand the need for this method of loading a byte-sized argument from the stack: no encoding T2 for 'ldrb', as we have for 'ldr', eg. 'ldr r1,[sp,#4]'. Here we're "unlucky" that the byte-sized parameter is the last one.

Rearranging the parameters as in procedure 'p1' avoids the issue, but I wonder if the compiler could generate this code:

Code: Select all

    p0(v0, v1, 0, 1, 2, 3, 4, b1);
.    24    018H  0480EH          ldr      r0,[pc,#56] -> 84
.    26    01AH  06800H          ldr      r0,[r0]
.    28    01CH  09900H          ldr      r1,[sp]
.    30    01EH  02200H          movs     r2,#0
.    32    020H  02301H          movs     r3,#1
.    34    022H  02402H          movs     r4,#2
.    36    024H  02503H          movs     r5,#3
.    38    026H  02604H          movs     r6,#4
.    40    028H  0AF01H          add      r7,sp,#4
.    42    02AH  0783FH          ldrb     r7,[r7]
I am aware this is an edge case, with eight parameters, and the last one byte-sized. Or even more on the edge, eight byte-sized parameters, where rearranging could not resolve the situation.

PS: the new Alert system is really useful, allowing to inspect the assembly code in cases like this.

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

Re: Alert: no free registers Question

Post by cfbsoftware » Thu May 16, 2024 6:08 am

Rather than trying to allow for this particular case the time could be spent implementing a general scheme to allow more than eight parameters for the Cortex-M0 compiler if there was sufficient demand. However, in general, it is good practice to try to minimise the number of parameters wherever possible. Ways in which this might be done include:

* Refactor the procedure into two or more separate procedures with fewer parameters.
* If some or all of the parameters are related, populate a record or array variable with the values and then pass that to the procedure.

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

Re: Alert: no free registers Question

Post by cfbsoftware » Wed May 22, 2024 9:33 pm

On further investigation we've reclassified this issue as a bug which will be fixed in the next maintenance release.

gray
Posts: 126
Joined: Tue Feb 12, 2019 2:59 am
Location: Mauritius

Re: Alert: no free registers Question

Post by gray » Sun Jun 02, 2024 6:17 am

Consider this test case, distilled from a real use case (Astrobe for Cortex-M0 v9.2):

Code: Select all

MODULE M;
  TYPE
    Cfg0* = RECORD END;
    Cfg1* = RECORD END;

  PROCEDURE make(dev: INTEGER; cfg0: Cfg0; x, y: INTEGER; VAR cfg1: Cfg1); END make;

  PROCEDURE config(dev: INTEGER; cfg0: Cfg0);
    VAR x, y: INTEGER; cfg1: Cfg1;
  BEGIN
    make(dev, cfg0, x, y, cfg1)
  END config;
END M.
Compiling also results in:

Code: Select all

Alert: no free registers

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

Re: Alert: no free registers Question

Post by cfbsoftware » Mon Jun 03, 2024 12:00 am

Workarounds are similar to before but a breakup of the make procedure might be a better long-term solution anyway depending on the details of what it is actually doing. I suspect it actually involves two distinct operations: copying some of the fields and adding some new data. If so it might go something like this:

Code: Select all

MODULE M;
  TYPE
    Cfg0* = RECORD END;
    Cfg1* = RECORD END;

  PROCEDURE CopyData(dev: INTEGER; cfg0: Cfg0; VAR cfg1: Cfg1);
  END CopyData;

  PROCEDURE AddData(dev, x, y: INTEGER; VAR cfg1: Cfg1);
  END AddData;

  PROCEDURE config(dev: INTEGER; cfg0: Cfg0);
    VAR x, y: INTEGER; cfg1: Cfg1;
  BEGIN
    CopyData(dev, cfg0, cfg1);
    AddData(dev, x, y, cfg1)
  END config;

END M.

Post Reply