#include <perms.h>
// Edinburgh IMP77 Compiler - Version 8.4
//
// 1 !
// 2 ! The hand-generated code below should be producable by PSR's compiler if it:
// 3 ! A) delays stores as late as possible
// 4 !
// 5 ! B) remembers registers over procedure calls
// 6 !
// 7 ! C) has a general algorithm for drop-through conditionally executed
// 8 ! instructions, i.e. if there are no instructions between a conditional
// 9 ! branch and its destination which set the condition codes, and the
// 10 ! sequence is less that a certain length, then all the instructions
// 11 ! within the sequence can be made conditional.
// 12 !
// 13 ! D) does as above, but also allows instructions within the sequence
// 14 ! whose subsequent execution depends on the same condition, e.g.
// 15 !
// 16 ! %if a=b %and c=d %then a=b
// 17 !
// 18 ! CmpS R0,R1 NAIVE STYLE
// 19 ! Bne elsepart
// 20 ! Cmps R2,R3
// 21 ! Bne elsepart
// 22 ! Mov R0,R2
// 23 !
// 24 ! CmpS R0,R1 RULE (C) ABOVE
// 25 ! Bne elsepart
// 26 ! CmpS R2,R3
// 27 ! MovEQ R0,R2
// 28 !
// 29 ! CmpS R0,R1 RULE (D) SPECIAL CASE
// 30 ! CmpSEQ R2,R3
// 31 ! MovEQ R0,R2
// 32 !
// 33 ! E) alters conditions to generate similar condition codes on
// 34 ! condition AND condition AND condition to generate more cases
// 35 ! to which rule (D) can be applied.
// 36 !
// 37 ! F) adjusts constants in < or <= cases to favour above, i.e. turning
// 38 ! CMP R,#const & BLE ... into CMP R,#const-1 & BLT ... etc.
// 39 !
// 40 ! G) changes Newline back from the current implicit printsymbol(10) -
// 41 ! there is no run-time overhead in moving the MOV R0,#10 over to
// 42 ! the procedure body instead of having it in every call where it
// 43 ! takes up space - after all, Peter's code-moving stuff ought to
// 44 ! get %permroutine newline;printsymbol(10);%end correct - it will
// 45 ! place the Mov R0,#10 before the body of %permroutine printsymbol
// 46 ! and generate a suitable entry point for it...
// 47 ! Personally, I would recommend stacking/restoring R0 as well
// 48 ! as it might keep another variable in a register for a bit longer...
// 49 !
// 50 ! I've only suggested optimisations which fit into the style of PSR's
// 51 ! compilers...
// 52 !
// 53
// 54
// 55 %begin
int main(int argc, char **argv) { /*%begin*/
_imp_initialise(argc, argv);
// 56 %integer a,i,b
int A;
int I;
int B;
// 57
// 58 read(a)
_imp_READ(/*?*/ &A);
// 59 ! BL read_fn
// 60
// 61 ! Str R0,a
// 62 read(i)
_imp_READ(/*?*/ &I);
// 63 ! BL read_fn
// 64
// 65 ! Str R0,i
// 66 read(b)
_imp_READ(/*?*/ &B);
// 67 ! BL read_fn
// 68
// 69 %if a <= i <= b %start
{
// Double-sided test on I (Part I)
int tmp;
if (A > (tmp = I)) goto L_0001;
// Double-sided test on I (Part II)
if (tmp > B) goto L_0001;
}
// 70 ! Ldr R1,a
// 71 ! Ldr R2,i
// 72 ! CmpS R1,R2
// 73 ! CmpSLE R2,R0
// 74 i = 22
I = 22;
// 75 ! MovLE R2,#22
// 76 %finish
L_0001:;
// 77
// 78 %if 22 <= i <= b %start
{
// Double-sided test on I (Part I)
int tmp;
if (22 > (tmp = I)) goto L_0002;
// Double-sided test on I (Part II)
if (tmp > B) goto L_0002;
}
// 79 ! CmpS R2,#22-1
// 80 ! CmpSGT R2,R0
// 81 i = 44
I = 44;
// 82 ! MovGT R2,#44
// 83 %finish
L_0002:;
// 84
// 85 %if a <= i <= 77 %start
{
// Double-sided test on I (Part I)
int tmp;
if (A > (tmp = I)) goto L_0003;
// Double-sided test on I (Part II)
if (tmp > 77) goto L_0003;
}
// 86 ! CmpS R1,R2
// 87 ! CmpSLE R2,#77
// 88 i = 99
I = 99;
// 89 ! MovLE R2,#99
// 90 %finish
L_0003:;
// 91
// 92 %if 11 <= i <= 100 %start ;! Peter's special case when both const is good
{
// Double-sided test on I (Part I)
int tmp;
if (11 > (tmp = I)) goto L_0004;
// Double-sided test on I (Part II)
if (tmp > 100) goto L_0004;
}
// 93 ! Sub R2,#11 ;! but usually corrupts a register needed later
// 94 ! CmpS R2,#100-11
// 95 i = 1
I = 1;
// 96 ! MovLS R2,#1
// 97 %finish
L_0004:;
// 98
// 99 ! Str R0,b
// 100 write(a,0)
_imp_WRITE(A, 0);
// 101 ! Mov R0,R1
// 102 ! Mov R1,#0
// 103 ! Bl Write
// 104
// 105 newline
_imp_NEWLINE();
// 106 ! Bl Newline
// 107
// 108 ! Mov R0,R2
// 109 write(i,0)
_imp_WRITE(I, 0);
// 110 ! Bl write
// 111
// 112 newline
_imp_NEWLINE();
// 113 ! Bl newline
// 114
// 115 write(b,0)
_imp_WRITE(B, 0);
// 116 ! Ldr R0,b
// 117 ! Bl write
// 118
// 119 newline
_imp_NEWLINE();
// 120 ! Bl newline
// 121
// 122 %endofprogram
_imp_stop(0);
return 0;
end_0:;
}