!
! The hand-generated code below should be producable by PSR's compiler if it:
! A) delays stores as late as possible
!
! B) remembers registers over procedure calls
!
! C) has a general algorithm for drop-through conditionally executed
!    instructions, i.e. if there are no instructions between a conditional 
!    branch and its destination which set the condition codes, and the
!    sequence is less that a certain length, then all the instructions
!    within the sequence can be made conditional.
!
! D) does as above, but also allows instructions within the sequence
!    whose subsequent execution depends on the same condition, e.g.
!
!    %if a=b %and c=d %then a=b
!
!    CmpS   R0,R1            NAIVE STYLE
!    Bne    elsepart
!    Cmps   R2,R3
!    Bne    elsepart
!    Mov    R0,R2
!
!    CmpS   R0,R1            RULE (C) ABOVE
!    Bne    elsepart
!    CmpS   R2,R3
!    MovEQ  R0,R2
!
!    CmpS   R0,R1            RULE (D) SPECIAL CASE
!    CmpSEQ R2,R3
!    MovEQ  R0,R2
!
! E) alters conditions to generate similar condition codes on
!    condition AND condition AND condition to generate more cases
!    to which rule (D) can be applied.
!
! F) adjusts constants in < or <= cases to favour above, i.e. turning
!    CMP R,#const & BLE ... into CMP R,#const-1 & BLT ... etc.
!
! G) changes Newline back from the current implicit printsymbol(10) -
!    there is no run-time overhead in moving the MOV R0,#10 over to
!    the procedure body instead of having it in every call where it
!    takes up space - after all, Peter's code-moving stuff ought to
!    get %permroutine newline;printsymbol(10);%end correct - it will
!    place the Mov R0,#10 before the body of %permroutine printsymbol
!    and generate a suitable entry point for it...
!       Personally, I would recommend stacking/restoring R0 as well
!    as it might keep another variable in a register for a bit longer...
!
! I've only suggested optimisations which fit into the style of PSR's
! compilers...
!


%begin
%integer a,i,b

  read(a)
! BL     read_fn

! Str    R0,a
  read(i)
! BL     read_fn

! Str    R0,i
  read(b)
! BL     read_fn

  %if a <= i <= b %start
! Ldr R1,a
! Ldr R2,i
! CmpS   R1,R2
! CmpSLE R2,R0
    i = 22
! MovLE  R2,#22
  %finish

  %if 22 <= i <= b %start
! CmpS   R2,#22-1
! CmpSGT R2,R0
    i = 44
! MovGT  R2,#44
  %finish

  %if a <= i <= 77 %start
! CmpS   R1,R2
! CmpSLE R2,#77
    i = 99
! MovLE  R2,#99
  %finish

  %if 11 <= i <= 100 %start     ;! Peter's special case when both const is good
! Sub   R2,#11                  ;! but usually corrupts a register needed later
! CmpS  R2,#100-11
    i = 1
! MovLS R2,#1
  %finish

! Str   R0,b
  write(a,0)
! Mov   R0,R1
! Mov   R1,#0
! Bl    Write

  newline
! Bl    Newline

! Mov   R0,R2
  write(i,0)
! Bl    write

  newline
! Bl    newline

  write(b,0)
! Ldr   R0,b
! Bl    write

  newline
! Bl    newline

%endofprogram
