!PRIM + PERM file for Motorola 68000 IMP Compiler V2.0 !After compilation -NOCHECK-NOLINE-MAP-LIST, ! the MEX file together with the LIS file are used by PRIMGEN ! to modify the const arrays in the body of the compiler. ! *** The comment { followed by | is used to flag identifiers ! which are to be known to the compiler. ! The case (lower or upper) of the basic identifier is ! preserved -- which is a way of hiding those that should ! not be accessible to the user. ! The form |@ is used to flag a PRIM routine (code here) ! if it does not otherwise need to be known. ! *** NB PRIM routines cannot reference other PRIM routines *** ! *** nor external or system routines *** ! * signal entered by jump with user program PC last thing ! on stack ! Minor point: RTS (rather than signal) usually put at end ! to help interpretation of dis-assembly {| NULL @ {| PROCSTAR @ {| INTTYPE integer {| @ MAXINT {| SHORTTYPE shortinteger {| HALFTYPE halfinteger {| BYTETYPE byteinteger {| MITETYPE miteinteger {| BOOLTYPE BOOLEAN {| CHARTYPE char {| STRINGSTAR string {| STRING1 @ {| STRINGTYPE @ {| ARRSTAR array {| NULLSETTYPE @ {| RECSTAR record {| @ TEXT {| REALTYPE real ! @16_3F00-6 %routine {|} SIGNAL ! @0%integer%fn {|DADDR} addr(%name n) @0%integer%fn {|DSIZEOF}sizeof(%name n) %routine {|} INDEX !Array index. !A0 points at [UB,LB,Size], D0 is index !Check in range; subtract LB; scale by Size. %label hi,ok,bigel,bigx,big %conststring(21) mess="Array bounds exceeded" *cmp (a0)+,d0; *bgt hi; !index > UB -> *sub (a0)+,d0; *bge ok; !index >= LB -> *add -(a0),d0; !restore index hi: *lea mess,a0; *move d0,d2; *move #2,d1; *move #16_76,d0 *jmp signal ! %signal 6,2,d0,"Array bounds exceeded" ok: *tst.w (a0)+; *bne bigel; !element size >= 64k -> *swap d0 *tst.w d0; *bne bigx; !adjusted index >= 64k -> *swap d0 *mulu (a0)+,d0 *rts bigel: !(index can't also be big) *move d1,-(sp) *move d0,d1 *mulu -2(a0),d1 *bra big bigx: *move d1,-(sp) *move d0,d1 *swap d0 *mulu (a0),d1 big: *swap d1 *mulu (a0)+,d0 *add d1,d0 *move (sp)+,d1 %end @0%bytemap {|LENREF} length(%string(*)%name z) @0%bytemap {|SINDEX} charno(%string(*)%name z, %integer n) @16_3F00-12 %routine {|} IMUL @16_3F00-18 %routine {|} IDIV @16_3F00-30 %routine {|} IPOW @16_3F00-36 %routine {|} FNEG @16_3F00-42 %routine {|} FADD @16_3F00-48 %routine {|} FSUB @16_3F00-54 %routine {|} FMUL @16_3F00-60 %routine {|} FDIV @16_3F00-66 %routine {|} FPOW @16_3F00-72 %real%fn {|} float(%integer a) @0 %integer%fn {|DREM} rem(%integer a,b) %routine {|} UNASS !Unassigned test. ! The CMP is done before calling (call sequence does not alter CC) %label ok %conststring mess="Unassigned variable" *bne ok *lea mess,a0; *move #1,d1; *move #16_58,d0 *jmp signal ! %signal 4,2,,"Unassigned variable" ok: %end %routine {|} ADOK !Address test (not NIL or unassigned) ! The CMP is done before calling (call sequence does not alter CC) %label ok %conststring mess="Invalid address" *bgt ok *lea mess,a0; *move #1,d1; *move #16_58,d0 *jmp signal ! %signal 4,2,,"Invalid address" ok: %end %routine {|} STACKOK !Check that stack can be extended by -D4 bytes ! (but do not alter SP) ! ** then reset D4 (byte reg) ** %label ok %conststring mess="Stack space exhausted" *add a7,d4; *cmp d6,d4; *bge ok *clr d4 *lea mess,a0; *move #3,d1; *move #16_55,d0 *jmp signal ok:*clr d4 %end %routine {|} ASIZE !(%integer element size, lower bound, upper bound) !Preliminary to claiming array space !result = EL*(UB-LB+1) %label ok %conststring mess="Array bounds inside out" *sub d2,d1 *ble ok *lea mess,a0; *move #3,d1; *move #16_55,d0 *jmp signal ! %signal 5,3,,"Array bounds inside out" ok:*neg d1 *addq #1,d1 *jmp imul; !=> multiply %end %routine {|} CONCAT !(%string(*)%name s,t,%integer maxlen) !Concatenate S to T %label bad,ok,done %conststring mess="String too big" *move.b (a1),d4; !length(dest) *sub.b d4,d0 *bcs bad *sub.b (a0),d0; !length(source) *bcc ok bad: *lea mess,a0; *move #3,d1; *move #16_51,d0 *jmp signal ! %signal 1,3,,"String too long" ok: *move.b (a0)+,d0 *beq done *add.b d0,(a1) loop: *move.b (a0)+,1(a1,d4) *add.b #1,d4 *sub.b #1,d0 *bne loop done: *move a1,a0 %end %string(1)%fn {|DTOSTRING} tostring(%integer k) !Used only for awkward contexts; others compiled in-line *move.w d0,-(sp) *move #1,d0; *move.b d0,(sp) *move sp,a0 *add #2,sp !%string(1) s ! charno(s,1) = k; length(s) = 1 ! %result = s %end %routine {|} AGET !Claim space for array from stack !D0=size (checked > 0: see ASIZE) !A7:=address of array, A0 also used %label ok,bad,loop1,loop,count %conststring mess="No space for array" *addq #3,d0; *asr #2,d0; *lsl #2,d0; !make multiple of 4 bytes *blt bad; ![safety] *move a7,a0; *sub d0,a0; !new SP (actually 4 less) *cmp d6,a0; *bge ok bad: *move d0,d2 *lea mess,a0; *move #1,d1; *move #16_72,d0 *jmp signal ! %signal 2,1,,"No space for array" ok: *move (a7)+,a0; !return address *lsr #2,d0 *bra count loop1: *swap d0 loop: *move d7,-(a7); !un-assign count: *dbra d0,loop; *swap d0; *dbra d0,loop1 *jmp (a0) %end %routine {|} FOROK !%for loop check !D0=start-inc, D1=inc, D2=final (unchanged) ! Check D2-D0 / D1 is integral and non-neg %label ok1,ok2,no %conststring mess="Invalid %for loop" *move d0,-(sp) *sub d2,d0; *beq ok2; !always ok if D0=D2 (even if D1=0) *move d1,-(sp); *beq no *jsr idiv; ![no error possible(?)] *tst d0; *blt ok1; !going in right direction no: *add #8,sp *lea mess,a0; *move #1,d1; *move #16_55,d0 *jmp signal ! %signal 5,1,,"Invalid for loop" ok1:*tst d1; *bne no; !must hit spot on *move (sp)+,d1 ok2:*move (sp)+,d0 %end %routine {|} CHECK ! Out-of-range error report %conststring mess="Out of range" *lea mess,a0; *move #1,d1; *move #16_56,d0 *jmp signal %end %routine {|} SCOMP ! String comparison ! Performs unassigned check, then compares strings A,B ! [Test for straight =,# compiled in-line when no unass check] ! A0=#A, A1=#B, D7=unassigned-pattern ! CC:= X,V,N:undefined, Z:set iff A=B, C:set iff A *subq #1,d0 *subq #1,d1 *cmp.w d1,d0 *bgt Bshort {length(B) < length(A) -> *sub.w d0,d1 {d1 = length(B)-length(A) >= 0 *cmpm (a1)+,(a0)+ *dbne d0,#-4 *bne done *neg.w d1 done:*movem (sp)+,d0-d1/a0-a1 *rts Bshort:*cmpm (a1)+,(a0)+ *dbne d1,Bshort *bne done Bless:*moveq #1,d1 {A>B *movem (sp)+,d0-d1/a0-a1 *rts Anull:*move.b (a1),d0 *neg.w d0 {B#"" means A @0%record(*) {|DNIL} nil @16_3F00-126 %routine dispose(%name v) @16_3F00-78 %integer%fn round(%real x) @16_3F00-84 %integer%fn trunc(%real x) @16_3F00-90 %real%fn fraction(%real x) @16_3F00-96 %integer%fn int(%real x) @16_3F00-102 %integer%fn intpt(%real x) @16_3F00-108 %real%fn fracpt(%real x) @16_3F00-114 %real%fn sqrt(%real x) @16_3F00-132 %integer%fn nextsymbol @16_3F00-138 %integer%fn readsymbol @16_3F00-138 %routine skipsymbol @16_3F00-144 %routine printsymbol(%integer k) @16_3F00-150 %routine {|DPRINTSTR} printstring(%string(255) z) !!@16_3F00-156 %routine openinput(%integer stream,%string(255)name) !!@16_3F00-162 %routine openoutput(%integer stream,%string(255)name) %external%routine%spec openinput(%integer stream,%string(255)name) %external%routine%spec openoutput(%integer stream,%string(255)name) @16_3F00-168 %routine selectinput(%integer stream) @16_3F00-174 %routine selectoutput(%integer stream) %external%routine%spec setinput(%integer position) %external%routine%spec setoutput(%integer position) %external%routine%spec resetinput %external%routine%spec resetoutput @16_3F00-192 %routine closeinput @16_3F00-198 %routine closeoutput %external%routine%spec prompt(%string(255) s) %routine {|@} newline *move #nl,d0; *jmp printsymbol %end %routine {|@} space *move #' ',d0; *jmp printsymbol %end %system%routine%spec spaces(%integer i) %system%routine%spec newlines(%integer i) %system%volatile%string(255)%fn%spec read %alias "readstring" %system%volatile%real%fn%spec%alias read %alias "readreal" %system%volatile%integer%fn%spec%alias read %system%routine%spec {|DWRITE}write(%integer m, n) %external%volatile%integer%fn%spec cputime %system%routine%spec print(%real x, %integer n,m) %system%routine%spec printfl(%real x, %integer n) @392(a5) %integer instream,outstream @464(a5) %string(255) cliparam %control 16