******************************************************************************** ******************************************************************************** ** ** Interpreter for the SECDH-2 machine ** ******************************************************************************** ******************************************************************************** ******************************************************************************** * * Here, we define the opcodes for the abstract machine. * Since we want to use them as offsets into an opcode table, they have to be * aligned to long, i.e., they have to be a multiple of 4. * The last entry should be LAST_OP which is used to determine the size of the * opcode table only. * PUSH_S EQU $00000000 PUSH_ES EQU $00000004 MKFRAME EQU $00000008 FREE EQU $0000000c BRC EQU $00000010 CALL EQU $00000014 RET EQU $00000018 AP EQU $0000001c PLUS EQU $00000020 MINUS EQU $00000024 MULT EQU $00000028 EQ EQU $0000002c GT EQU $00000030 ARGS EQU $00000034 LINK EQU $00000038 CREATE_CLOS EQU $0000003c DONE EQU $00000040 LAST_OP EQU $00000044 ******************************************************************************** ORG $0 DC.L $8000 Stack pointer value after a reset DC.L START Program counter value after a reset ******************************************************************************** * * Here, we do reserve some space for the opcode table * OP_TAB DS.L LAST_OP ******************************************************************************** * * Here, we do reserve memory space for the stacks S, E, and D. * The labels x_STACK_T point to the current top positions: * STACK_REG DS.L 100 S_STACK_T DS.L 100 E_STACK_T DS.L 100 D_STACK_T DS.L 1 ******************************************************************************** * * In the following part of the memory we do keep our programs, i.e., the * portion of the heap denoted by C * P_FAC DC.L ARGS,1,MKFRAME,1,PUSH_ES,0,0,PUSH_S,0,EQ,BRC,P_T,P_F,FREE,1,RET P_T DC.L PUSH_S,1,RET P_F DC.L PUSH_S,1,PUSH_ES,0,0,MINUS,LINK,0,CALL,P_FAC,PUSH_ES,0,0,MULT,RET P_FAC_PRG DC.L PUSH_S,4,LINK,-1,CALL,P_FAC,DONE ******************************************************************************** * * Here, we do reserve a heap area for storing the closures: * HEAP_START DS.L 1000 HEAP_STOP DS.L 1 ******************************************************************************** ******************************************************************************** * * Here, the implementation of the SEMCD-H2 interpreter starts: * ******************************************************************************** * * First, we do define some string constants: * START_STR DC.B 'starting secdh-2 interpreter...',0 DONE_STR DC.B 'finished',0,0 RES_STR DC.B 'the result is: ',0 ******************************************************************************** * * Now, the main program: * START: JSR INIT_OP_TAB initialize opcode table JSR INIT_IO initialize DUART JSR CLEAR_SCREEN MOVE.L #START_STR,-(SP) JSR PUT_STR MOVE.L #P_FAC_PRG,-(SP) push program pointer on stack JSR EXEC execute program MOVE.L #DONE_STR,-(SP) JSR PUT_STR JSR NEW_LINE MOVE.L #RES_STR,-(SP) JSR PUT_STR JSR PUT_NUM print result (still on stack) JSR NEW_LINE BREAK ******************************************************************************** * * function: void INIT_OP_TAB() * * description: * does initialize the opcode table at OP_TAB with pointers to the subroutines * I_xxx that implement the operations xxx. * * registers affected: none * INIT_OP_TAB: MOVE.L A0,-(SP) save A0 MOVE.L #OP_TAB,A0 MOVE.L #I_PUSH_S,PUSH_S(A0) MOVE.L #I_LINK,LINK(A0) * * other ops to be filled in ... * MOVE.L #I_DONE,DONE(A0) MOVE.L (SP)+,A0 restore A0 RTS ******************************************************************************** * * function: (SP1) DEREF( (SP1), (SP2)) * * description: * dereferences the pointer (SP1) (SP2) many times and returns the resulting * pointer. It is assumed that (SP2) >= #0 holds and that all pointers to be * followed are within the legal range. * * registers affected: none * DEREF: * * to be filled in ... * RTS ******************************************************************************** * * function: (SP1) COPY_ENV( (SP1), (SP2)) * * description: * Expects (SP2) to point to an environment which is t be copied into the * memory starting at (SP1). On return, (SP1) points to the memory cell right * after the last cell copied. * * registers affected: none * COPY_ENV: * * to be filled in ... * RTS ******************************************************************************** * * function: (SP) EXEC( (SP)) * * description: * This is the main execution cycle which initializes the SECDH-2 interpreter, * and starts the interpretation at (SP). * Basically, it repeatedly reads the opcode behind the P_C, looks up the * address of the code that implements the operation (in the opcode table), and * jumps to that code. * * The last instruction should be "DONE" which leads to the jump address I_DONE * and thus exits the loop EXEC_LOOP. * The result found on top of P_S is returned via (SP). * * NOTE: A6 serves two purposes here. During the program interpretation, it * serves as pointer into the heap P_H; otherwise, it is used as frame * pointer. * * registers affected: none * EXEC: LINK A6,#0 MOVEM.L D0-D7/A0-A5,-(SP) MOVE.L 8(A6),A0 fetch SP (program ptr) MOVE.L A6,-(SP) save frame pointer MOVE.L #S_STACK_T,A2 init P_S (A2) MOVE.L #E_STACK_T,A3 init P_E (A3) MOVE.L #0,-(A3) push nil-link to P_E MOVE.L A0,A4 init P_C (A4) with prg to be evaluated MOVE.L #D_STACK_T,A5 init P_D (A5) MOVE.L #HEAP_START,A6 init P_H (A6) MOVE.L #OP_TAB,A0 EXEC_LOOP: MOVE.L (A4)+,D0 load opcode into D0 and increment P_C MOVE.L (A0,D0),A1 dispatch opcode into instruction address JSR (A1) CMPA.L #I_DONE,A1 BNE EXEC_LOOP MOVE.L (SP)+,A6 restore frame pointer MOVE.L (A2)+,8(A6) move result (top of P_S) into SP MOVEM.L (SP)+,D0-D7/A0-A5 UNLK A6 RTS ******************************************************************************** * * Now, the implementations of the individual operations follow. * ******************************************************************************** * * function: A2, A3, A4, A5, A6 I_xxx( A2, A3, A4, A5, A6) * * description: * Implements the SECDH-2 operation xxx. * A2 contains P_S, A3 contains P_E, A4 contains P_C, A5 contains P_D, * A6 contains P_H. * * registers which might be affected: D0-D7 * I_PUSH_S: MOVE.L (A4)+,D0 load atom from heap MOVE.L D0,-(A2) push atom on s RTS I_LINK: MOVE.L (A4)+,D0 fetch parameter n ADDI.L #1,D0 increment link parameter MOVE.L A3,-(SP) MOVE.L D0,-(SP) JSR DEREF get (n+1)-th indirection starting at P_E MOVE.L (SP)+,-(A2) push it on s RTS * * other ops to be filled in ... * I_DONE: RTS no operation ******************************************************************************** INCLUDE io-pack.ss