TITLE "mp5.a - interpreter for a plotter language" ; plots as commanded by DATA, an external string ; this version is an expansion of the code from MP4 ; by Douglas Jones -- Nov 15, 2010 S START USE "hawk.macs" ; macros to make long conditional jumps ; (these might be useful addition to hawk.macs?) MACRO JLTU LABEL BGEU .+6 JUMP LABEL ENDMAC MACRO JGTU LABEL BLEU .+6 JUMP LABEL ENDMAC MACRO JGE LABEL BLT .+6 JUMP LABEL ENDMAC MACRO JNE LABEL BEQ .+6 JUMP LABEL ENDMAC MACRO JLE LABEL BGT .+6 JUMP LABEL ENDMAC ; end of long conditional jump macros USE "monitor.h" EXT UNUSED EXT DATA SUBTITLE "Main Program" ; the program starts here! START: LIL R2,UNUSED ; set up the stack LIL R1,DSPINI JSRS R1,R1 ; initialize the display ; --- begin aplication code LIL R3,DATA ; -- parameter string pointer LIS R4,0 ; -- parameter x coord LIS R5,0 ; -- parameter y coord LIS R6,0 ; -- parameter a accumulator JSR R1,INTERPRETER ; interpreter( data, 0, 0 ) ; --- end aplication code LIL R1,EXIT JSRS R1,R1 ; stop! SUBTITLE "Interpreter for funny strings" ; activation record for INTERPRETER ;RETAD = 0 STRING = 4 ; string pointer XCOORD = 8 ; x coordinate YCOORD = 12 ; y coordinate ACC = 16 ; a accumulator ARSIZE = 20 INTERPRETER: ; expects R3, s string pointer ; expects R4, x coordinate ; expects R5, y coordinate ; expects R6, a accumulator ; returns R3, s updated ; returns R6, a updated ; wipes out R4-8 ; call dspch for each char in string ; calls itself recursively to handle parentheses STORES R1,R2 INTERLP: ; for (;;) { LOADS R7,R3 ; -- get word holding char EXTB R7,R7,R3 ; char = *s ; -- through rest of loop, ; -- R3=s, R4=x, R5=y, R6=a, R7=char CMPI R7," " JLTU INTERQT ; if (char < ' ') break out of loop ADDSI R3,1 ; s++ -- delayed to here so won't skip nulls ; select (char) { CMPI R7,"z" JGTU INTELSE ; -- if (char > 'z') goto else case ADDI R8,R7,-"(" JLTU INTELSE ; -- if (char < '(') goto else case ; -- 83 cases remain LEA R1,INTTABLE ADDSL R8,R1,2 LOADS R1,R8 ; -- R1 = INTTABLE[R7] JUMPS R1 ALIGN 4 ; jump table for case select construct INTTABLE: ; ( ) * + , - . / W INTLPAR,INTRPAR,INTELSE,INTPLUS,INTELSE,INTMINS,INTELSE,INTELSE ; 0 1 2 3 4 5 6 7 W INTDIGI,INTDIGI,INTDIGI,INTDIGI,INTDIGI,INTDIGI,INTDIGI,INTDIGI ; 8 9 : ; < = > ? W INTDIGI,INTDIGI,INTELSE,INTELSE,INTLT ,INTEQ ,INTGT ,INTELSE ; @ A B C D E F G W INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE ; H I J K L M N O W INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE ; P Q R S T U V W W INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE ; X Y Z [ \ ] ^ _ W INTELSE,INTELSE,INTELSE,INTLBRK,INTELSE,INTRBRK,INTELSE,INTELSE ; ` a b c d e f g W INTELSE,INTELSE,INTELSE,INTCLR ,INTDOWN,INTELSE,INTELSE,INTELSE ; h i j k l m n o W INTELSE,INTELSE,INTELSE,INTELSE,INTLEFT,INTELSE,INTELSE,INTELSE ; p q r s t u v w W INTELSE,INTELSE,INTRIGT,INTELSE,INTELSE,INTUP ,INTELSE,INTELSE ; x y z W INTX ,INTY ,INTZERO ; cases for MP5 ; -- R3=s, R4=x, R5=y, R6=a, R7=char INTCLR: ; case "c" LIS R6,0 ; a = 0 JUMP INTESAC ; break INTDIGI: ; cases "0" - "9" SL R6,1 ADDSL R6,R6,2 ; a = a * 10 ADDI R8,R7,-"0" ADD R6,R6,R8 ; a = a + (char - "0") JUMP INTESAC ; break INTX: ; case "x" MOVE R4,R6 ; x = a JUMP INTESAC ; break INTY: ; case "y" MOVE R5,R6 ; y = a JUMP INTESAC ; break INTPLUS: ; case "+" ADD R6,R4,R5 ; a = x+y JUMP INTESAC ; break INTMINS: ; case "-" SUB R6,R4,R5 ; a = x-y JUMP INTESAC ; break INTGT: ; case ">" TESTR R6 JLE INTESAC ADDSI R3,1 ; if (a > 0) s++ JUMP INTESAC ; break INTEQ: ; case "=" TESTR R6 JNE INTESAC ADDSI R3,1 ; if (a = 0) s++ JUMP INTESAC ; break INTLT: ; case "<" TESTR R6 JGE INTESAC ADDSI R3,1 ; if (a < 0) s++ JUMP INTESAC ; break INTLBRK: ; case "[" -- skip forward over ] ; do { LOADS R7,R3 ; -- get word holding char EXTB R7,R7,R3 ; char = *s CMPI R7," " BLTU INTERQT ; if (char < ' ') break outer loop ADDSI R3,1 ; s++ -- delayed past check for null CMPI R7,"]" BNE INTLBRK ; } until (char = "]") JUMP INTESAC ; break INTRBRK: ; case "]" -- skip backware until [ ; do { ADDSI R3,-1 ; s-- LOADS R7,R3 ; -- get word holding char EXTB R7,R7,R3 ; char = *s CMPI R7," " BLTU INTERQT ; if (char < ' ') break outer loop CMPI R7,"[" BNE INTRBRK ; } until (char = "[") ADDSI R3,1 ; s++ -- we wanted to stop sooner! JUMP INTESAC ; break ; cases for MP4 ; -- R3=s, R4=x, R5=y, R6=a, R7=char INTRPAR: ; case ")" BR INTERQT ; break out of loop; INTZERO: ; case "z" LIS R4,0 ; x = 0 LIS R5,0 ; y = 0 JUMP INTESAC ; break INTUP: ; case "u" ADDSI R5,-1 ; y-- JUMP INTESAC ; break INTDOWN: ; case "d" ADDSI R5,1 ; y++ JUMP INTESAC ; break INTLEFT: ; case "l" ADDSI R4,-1 ; x-- JUMP INTESAC ; break INTRIGT: ; case "r" ADDSI R4,1 ; x++ JUMP INTESAC ; break INTLPAR: ; case "(" STORE R4,R2,XCOORD STORE R5,R2,YCOORD ; -- save coords through call ADDI R2,R2,ARSIZE JSR R1,INTERPRETER ; s = interpreter( s, x, y ) ADDI R2,R2,-ARSIZE LOAD R4,R2,XCOORD LOAD R5,R2,YCOORD ; -- restore coords after call JUMP INTESAC ; break INTELSE: ; } else { STORE R3,R2,STRING STORE R4,R2,XCOORD STORE R5,R2,YCOORD STORE R6,R2,ACC ; -- save everything through calls MOVE R8,R7 MOVE R3,R4 ; -- shove params into place MOVE R4,R5 ADDI R2,R2,ARSIZE LIL R1,DSPAT JSRS R1,R1 ; dspat( x,y ) MOVE R3,R8 ; -- recover saved char LIL R1,DSPCH JSRS R1,R1 ; dspch( char ) ADDI R2,R2,-ARSIZE LOAD R3,R2,STRING LOAD R4,R2,XCOORD LOAD R5,R2,YCOORD LOAD R6,R2,ACC ; -- restore everything after calls JUMP INTESAC ; break INTESAC = INTERLP ; } INTERQT: ; } LOADS R1,R2 JUMPS R1 ; return s and a END