initial

parents
cc=A Condition Code (CC) encodes a result of a comparison. Four bits are used to encode the fact that the result of a cmp instruction is zero (Z), negative (N), a carry was needed (C) or overflow was detected (V). conditioncode=@cc sr=SR stands for Status Register. The status, called SR (status register) is not a real register but just an interpretation of the top of the stack. The top of the stack is used to store the condition codes resulting after a compare. Four bits, Z, N, C and V of the SR are used to encode the comparison result being zero, negative, carried and overflowed. These bits are only used by branches on conditions (i.e. beq). statusbits=See SR. prepostcondition=A kind of pre and postcondition is used to denote the effect of instructions. Behaviour is expressed using equations relating the state of the machine before (pre) execution of an instruction to the state after (post). Values of memory (M), registers (PC,SP,MP,RR) are subscripted with 'pre' resp 'post' to refer to the respective values before/after execution. No equation for a value means that the pre and post values are equal.
\ No newline at end of file
cmp_descr=Compare. Replaces 2 top stack values with the status of the comparison of those values. The status is put in SR. See also brf. cmp_prepost=SP_post = SP_pre - 1, M_post[SP_post] = status(M_pre[SP_pre - 1] - M[SP_pre]) cmp_example=ldl -2 ; if x /= 1 then x = 1, ldc 1, cmp, beq skipLabel, ldc 1, stl -2, skipLabel: ... beq_descr=Branch on condition. Notation bcc, where the cc in bcc can be eq (equal), ne (not equal), lt (less than), gt (greater than), le (less or equal) or ge (greater or equal). And some others not used often: pl (plus), mi (minus), cc (carry clear), cs (carry set), hi (high), ls (low or same). beq_prepost=SP_post = SP_pre - 1, PC_post = PC_pre + M_pre[PC_pre + 1] + 2 (if condition matches) beq_example=@cmp_example bne_descr=@beq_descr bne_prepost=@beq_prepost bne_example=@beq_example blt_descr=@beq_descr blt_prepost=@beq_prepost blt_example=@beq_example ble_descr=@beq_descr ble_prepost=@beq_prepost ble_example=@beq_example bgt_descr=@beq_descr bgt_prepost=@beq_prepost bgt_example=@beq_example bge_descr=@beq_descr bge_prepost=@beq_prepost bge_example=@beq_example
\ No newline at end of file
# General help info for Simple Stack Machine registers=Eight registers are available, some of which have a specific purpose. A register is private location in a processor, often faster accessible then external memory. Currently the Program Counter (PC), Stack Pointer (SP), Mark Pointer (MP) and Return Register (RR) as well as freely usable scratch registers are available, respectively identified by numbers 0..7. Registers are identified by the name R<x>, where <x> is the register number. Register with a specific purpose are also named with the name indicating their purpose. PC=The Program Counter (PC) is used to remember what the current next instruction is. It contains the address (i.e. points to) the location of the next instruction. The machine fetches an instruction from the location pointed to by the PC. After each fetch it is automatically updated to point to the next instruction. programcounter=@PC SP=The Stack Pointer (SP) is used to push and pop values for usage in expression evaluation. The Stack is also used to store variables. These are often accessed via the MP. stackpointer=@SP MP=The Mark Pointer (MP) is used to access local variables, allocated on the stack. Each variable is accessed using a displacement relative to the MP. markpointer=@MP RR=The Return Register (RR) is used to return a value without placing it on a stack. Strictly seen this is not necessary but a convenience, since values also can be passed via the stack. return register=@RR instruction=An instruction is an encoding of some operation, executed in the machine. A set of instructions stored in memory is called the code. Some instructions have inline operands, that is, after their location in the code an extra operand is stored, a constant, e.g. in "ldc 1". In pre/post conditions this location is indicated by M[PCpre+1] since it can be found on that location. The behavior of an instruction is both informally described as well as using pre/postcondifitions. memory=Memory stores words. A word is an 32 bits integer. Currently only a limited amount of memory words is reserver (2000), this is rather arbitrary, in the future memory size will adapt automatically to the amount needed. stack=Stack is the part of memory used to store values needed for evaluating expressions. The stack is located after the code and grows from lower addresses to higher ones. code=Code is the part of memory used to store instructions. It starts at address 0. help=The Simple Stack Runner executes instructions for a hypothetical (and thus simple) machine. See memory, registers, syntax, instruction as starting points for help. syntax=Syntax of instructions (as loaded from file) is: (label:)? (instr arg*)?. In other words, an (optional) instruction preceded by an (optional) label and followed by an argument if required. Comment may start with ";" or "//" (Java/C++ style) and ends at the end of the line. This characters are interpreted as start of comment. A label may be used as an argument. Example: "l1: beq l1 ; comment". labels=A label is an identifier indicating a position in the code. When loading, the code location of a label is calculated (called resolution). This is done in the user interface of the program and after loading labels are not kept consistent (when adding new instructions for example). False=Value False is encoded by a 0. True=Value True is encoded by a -1 (all 1 bit pattern 0xFFFFFFFF). However, when testing in the context of a BRF instruction takes place, anything else than 0 is considered to be True.
\ No newline at end of file
# Instruction help info for Simple Stack Machine ldc_descr=Load Constant. Pushes the inline constant on the stack. ldc_prepost=SP_post = SP_pre + 1, M_post[SP_post] = M_pre[PC_pre+1] ldc_example=@stl_example lds_descr=Load from Stack. Pushes a value relative to the top of the stack. lds_prepost=SP_post = SP_pre + 1, M_post[SP_post] = M_pre[SP_pre + M_pre[PC_pre+1]] lds_example=lds -1 ; multiply and leave on stack, ldc 2, mul ldms_descr=Load Multiple from Stack. Pushes values relative to the top of the stack. Same as single load variant but second inline parameter is size. ldms_prepost=displ = M_pre[PC_pre + 1], size = M_pre[PC_pre + 2], SP_post = SP_pre + size, M_post[SP_post - size + 1 .. SP_post] = M_pre[SP_pre + displ .. SP_pre + displ + size - 1] ldms_example=ldms -1 2; multiply and leave on stack, mul sts_descr=Store into Stack. Pops a value from the stack and stores it in a location relative to the top of the stack. sts_prepost=SP_post = SP_pre - 1, M_post[SP_pre + M_pre[PC_pre+1]] = M_pre[SP_pre] sts_example=lds -1 ; substract and store in stack, ldc 2, sub, sts -2 stms_descr=Store Multiple into Stack. Pops values from the stack and stores it in a location relative to the top of the stack. Same as single store variant but second inline parameter is size. stms_prepost=displ = M_pre[PC_pre + 1], size = M_pre[PC_pre + 2], SP_post = SP_pre - size, M_post[SP_pre + displ .. SP_pre + displ + size - 1] = M_pre[SP_post + 1 .. SP_post + size] stms_example=lds -1 ; substract and store in stack, ldc 2, sub, stms -2 1 ; equivalent to sts -2 ldsa_descr=Load Stack Address. Pushes the address of a value relative to the stackpointer. ldsa_prepost=SP_post = SP_pre + 1, M_post[SP_post] = SP_pre + M_pre[PC_pre+1] ldsa_example=ldsa -2 ; update value on stack using its address, ldc 5, sta 0 ldl_descr=Load Local. Pushes a value relative to the markpointer. ldl_prepost=SP_post = SP_pre + 1, M_post[SP_post] = M_pre[MP_pre + M_pre[PC_pre+1]] ldl_example=ldl -1 ; divide and leave on stack, ldc 3, div ldml_descr=Load Multiple Local. Pushes values relative to the markpointer. Same as single load variant but second inline parameter is size. ldml_prepost=displ = M_pre[PC_pre + 1], size = M_pre[PC_pre + 2], SP_post = SP_pre + size, M_post[SP_post - size + 1 .. SP_post] = M_pre[MP_pre + displ .. MP_pre + displ + size - 1] ldml_example=ldml -1 2 ; divide and leave on stack, ldc 3, div stl_descr=Store Local. Pops a value from the stack and stores it in a location relative to the markpointer. stl_prepost=SP_post = SP_pre - 1, M_post[MP_pre + M_pre[PC_pre+1]] = M_pre[SP_pre] stl_example=ldl 2 ; increment local var, ldc 1, add, stl 2 stml_descr=Store Multiple Local. Pops values from the stack and stores it in a location relative to the markpointer. Same as single store variant but second inline parameter is size. stml_prepost=displ = M_pre[PC_pre + 1], size = M_pre[PC_pre + 2], SP_post = SP_pre - size, M_post[MP_pre + displ .. MP_pre + displ + size - 1] = M_pre[SP_post + 1 .. SP_post + size] stml_example=ldl 2 ; increment local var, ldc 1, add, stml 2 1 ; equivalent to stl 2 ldla_descr=Load Local Address. Pushes the address of a value relative to the markpointer. ldla_prepost=SP_post = SP_pre + 1, M_post[SP_post] = MP_pre + M_pre[PC_pre+1] ldla_example=ldla -2 ; update local using its address, ldc 5, sta 0 lda_descr=Load via Address. Dereferencing. Pushes the value pointed to by the value at the top of the stack. The pointer value is offset by a constant offset. lda_prepost=SP_post = SP_pre, M_post[SP_post] = M_pre[M_pre[SP_pre] + M_pre[PC_pre+1]] lda_example=ldla -2 ; a different way of doing ldl -2, lda 0 ldma_descr=Load Multiple via Address. Pushes values relative to by the value at the top of the stack. Same as single load variant but second inline parameter is size. ldma_prepost=displ = M_pre[PC_pre + 1], size = M_pre[PC_pre + 2], SP_post = SP_pre + size - 1, M_post[SP_post - size + 1 .. SP_post] = M_pre[M_pre[SP_pre] + displ .. M_pre[SP_pre] + displ + size - 1] ldma_example=none ldaa_descr=Load Address of Address. Pushes the address of a value relative to the address on top of the stack. This instruction effectively adds a constant to the top of the stack. ldaa_prepost=SP_post = SP_pre + 1, M_post[SP_post] = M_pre[SP_pre] + M_pre[PC_pre+1] ldaa_example=ldaa -2 sta_descr=Store via Address. Pops 2 values from the stack and stores the second popped value in the location pointed to by the first. The pointer value is offset by a constant offset. sta_prepost=SP_post = SP_pre - 2, M_post[M_pre[SP_pre] + M_pre[PC_pre+1]] = M_pre[SP_pre-1] sta_example=@ldla_example stma_descr=Store Multiple via Address. Pops values from the stack and stores it in a location relative to the value at the top of the stack. Same as single store variant but second inline parameter is size. stma_prepost=displ = M_pre[PC_pre + 1], size = M_pre[PC_pre + 2], SP_post = SP_pre - size - 1, M_post[M_pre[SP_pre] + displ .. M_pre[SP_pre] + displ + size - 1] = M_pre[SP_post + 1 .. SP_post + size] stma_example=none ldr_descr=Load Register. Pushes a value from a register. Registers 0, 1, 2 and 3 are called PC (program counter), SP (stack pointer), MP (mark pointer) and RR (return register) respectively. ldr_prepost=SP_post = SP_pre + 1, M_post[SP_post] = REG_pre[ M_pre[PC_pre+1] ] ldr_example=ldr RR ; decrement register, ldc 1, sub, str RR ldrr_descr=Load Register from Register. Copy the content of the second register to the first. Does not affect the stack. ldrr_prepost=REG_post[ M_pre[PC_pre+1] ] = REG_pre[ M_pre[PC_pre+2] ] ldrr_example=ldrr SP MP ; SP <- MP str_descr=Store Register. Pops a value from the stack and stores it in a location relative to the markpointer. See also ldr. str_prepost=SP_post = SP_pre - 1, REG_post[ M_pre[PC_pre+1] ] = M_pre[SP_pre] str_example=@ldr_example swp_descr=Swap values. Swaps the 2 topmost values on the stack. swp_prepost=SP_post = SP_pre, M_post[SP_post] = M_pre[SP_pre-1], M_post[SP_post-1] = M_pre[SP_pre] swp_example=ldc 1 ; variant for ldc 2 followed by ldc 1, ldc 2, swp swpr_descr=Swap Register. Swaps the content of a register with the top of the stack. swpr_prepost=SP_post = SP_pre, M_post[SP_post] = REG_pre[ M_pre[PC_pre+1] ], REG_post[ M_pre[PC_pre+1] ] = M_pre[SP_pre] swpr_example= swprr_descr=Swap 2 Registers. Swaps the content of a register with another register. swprr_prepost=REG_post[ M_pre[PC_pre+1] ] = REG_pre[ M_pre[PC_pre+2] ], REG_post[ M_pre[PC_pre+2] ] = REG_pre[ M_pre[PC_pre+1] ] swprr_example=swprr MP R7 ; swap MP with scratch register ajs_descr=Adjust Stack. Adjusts the stackpointer with fixed amount. ajs_prepost=SP_post = SP_pre + M_post[PC_pre+1] ajs_example=ajs -2 ;lower stack by 2 add_descr=Addition. Replaces 2 top stack values with the addition of those values. add_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] + M_pre[SP_pre] add_example=@stl_example mul_descr=Multiplication. Replaces 2 top stack values with the multiplication of those values. mul_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] * M_pre[SP_pre] mul_example=@ld_example sub_descr=Substraction. Replaces 2 top stack values with the subtraction of those values. sub_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] - M_pre[SP_pre] sub_example=@st_example div_descr=Division. Replaces 2 top stack values with the division of those values. div_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] / M_pre[SP_pre] div_example=@ldl_example mod_descr=Division. Replaces 2 top stack values with the modulo of those values. mod_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] % M_pre[SP_pre] mod_example=ldl -2 ; x = x % y, ldl -3, mod, stl -2 and_descr=And. Replaces 2 top stack values with the bitwise and of those values. and_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] & M_pre[SP_pre] and_example=ldc 0xFF00 ; variant of ldc 0xF000, ldc 0xF0F0, and or_descr=Or. Replaces 2 top stack values with the bitwise or of those values. or_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] | M_pre[SP_pre] or_example=ldc 0xFF00 ; variant of ldc 0xFFFF, ldc 0xF0F0, or xor_descr=Exclusive Or. Replaces 2 top stack values with the bitwise exclusive or of those values. xor_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] ^ M_pre[SP_pre] xor_example=ldc 0xFF00 ; variant of ldc 0x0FF0, ldc 0xF0F0, xor eq_descr=Test for equal. Replaces 2 top stack values with boolean result of the test. False is encoded as 0, True as 1. Used in combination with brf. This is a variant of cmp combined with beq. eq_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] == M_pre[SP_pre] eq_example=ldc 2, ldc 3, eq, brf FalseAction ne_descr=Test for not equal. Replaces 2 top stack values with boolean result of the test. False is encoded as 0, True as 1. Used in combination with brf. This is a variant of cmp combined with bne. ne_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] != M_pre[SP_pre] ne_example=ldc 2, ldc 3, ne, brf FalseAction lt_descr=Test for less then. Replaces 2 top stack values with boolean result of the test. False is encoded as 0, True as 1. Used in combination with brf. This is a variant of cmp combined with blt. lt_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] < M_pre[SP_pre] lt_example=ldc 2, ldc 3, lt, brf FalseAction le_descr=Test for less or equal. Replaces 2 top stack values with boolean result of the test. False is encoded as 0, True as 1. Used in combination with brf. This is a variant of cmp combined with ble. le_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] <= M_pre[SP_pre] le_example=ldc 2, ldc 3, lr, brf FalseAction gt_descr=Test for greater then. Replaces 2 top stack values with boolean result of the test. False is encoded as 0, True as 1. Used in combination with brf. This is a variant of cmp combined with bgt. gt_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] > M_pre[SP_pre] gt_example=ldc 2, ldc 3, gt, brf FalseAction ge_descr=Test for greater or equal. Replaces 2 top stack values with boolean result of the test. False is encoded as 0, True as 1. Used in combination with brf. This is a variant of cmp combined with bge. ge_prepost=SP_post = SP_pre - 1, M_post[SP_post] = M_pre[SP_pre - 1] >= M_pre[SP_pre] ge_example=ldc 2, ldc 3, ge, brf FalseAction neg_descr=Negation. Replaces top stack values with the (integer) negative of the value. neg_prepost=SP_post = SP_pre, M_post[SP_post] = - M_pre[SP_pre] neg_example=ldc 1 ; variant of ldc -1, neg not_descr=Not. Replaces top stack values with the bitwise complement of the value. not_prepost=SP_post = SP_pre, M_post[SP_post] = ~ M_pre[SP_pre] not_example=ldc 0x0000FFFF ; variant of ldc 0xFFFF0000, not bsr_descr=Branch to subroutine. Pushes the PC on the stack and jumps to the subroutine. bsr_prepost=SP_post = SP_pre + 1, M_post[SP_post] = PC_pre + 2, PC_post = PC_pre + M_pre[PC_pre + 1] + 2 bsr_example=bra main, subroutine ldc 1, ldc 2, add, str RR, ret, main: bsr subroutine, ldr RR, ... bra_descr=Branch Allways. Jumps to the destination. Replaces the PC with the destination address. bra_prepost=PC_post = PC_pre + M_pre[PC_pre + 1] + 2 bra_example=@bsr_example brf_descr=Branch on False. If a False value is on top of the stack, jump to the destination. brf_prepost=SP_post = SP_pre - 1, PC_post = PC_pre + M_pre[PC_pre + 1] + 2 (if false on top of the stack) brf_example=@eq_example brt_descr=Branch on True. If a True value is on top of the stack, jump to the destination. brt_prepost=SP_post = SP_pre - 1, PC_post = PC_pre + M_pre[PC_pre + 1] + 2 (if true on top of the stack) brt_example= jsr_descr=Jump to subroutine. Pops a destination from the stack, pushes the PC on the stack and jumps to the destination. jsr_prepost=SP_post = SP_pre, PC_post = M_pre[SP_pre], M_post[SP_post] = PC_pre + 1 jsr_example=bra main, subroutine ldc 1, ldc 2, add, str RR, ret, main: ldc subroutine, jsr, ldr RR, ... ret_descr=Return from subroutine. Pops a previously pushed PC from the stack and jumps to it. ret_prepost=SP_post = SP_pre - 1, PC_post = M_pre[SP_pre] ret_example=bra main, subroutine ldc 1, ldc 2, add, str RR, ret, main: bsr subroutine, ldr RR, ... link_descr=Reserve memory for locals. Convenience instruction combining the push of MP and the adjustment of the SP. link_prepost=MP_post = SP_pre + 1, M_post[MP_post] = MP_pre, SP_post = MP_post + M_pre[PC_pre+1] link_example=bra main, subroutine link 2 ; reserve for 2 locals, ldc 1, ldc 2, add, stl 1 ; store in 2nd local, ldl 1, str RR, unlink, ret, main: bsr subroutine, ldr RR, ... unlink_descr=Free memory for locals. Convenience instruction combining the push of MP and the adjustment of the SP. unlink_prepost=MP_post = M_pre[MP_pre], SP_post = MP_pre - 1 unlink_example=@link_example nop_descr=No operation. Well, guess what... nop_prepost= nop_example=nop halt_descr=Halt execution. Machine stops executing instructions. halt_prepost= halt_example=halt trap_descr=Trap to environment function. Trap invokes a systemcall, which one is determined by its argument. Currently just 1 call exists, print the topmost element on the stack as an integer in the output window. trap_prepost= trap_example=ldc 5, trap 0 ; print 5 on output annote_descr=Annotate. A meta instruction (not producing code), annotating the stack display in the user interface with text and color. Annote takes 5 arguments, (1) a register name, (2) a low offset w.r.t. the register (used as starting point for annotating), (3) a high offset, (4) a color, (5) text. Color can be one of {black, blue, cyan, darkGray, gray, green, lightGray, magenta, orange, pink, red, yellow}. Text including spaces need to be enclosed in double quotes. The annote instruction is tied to the preceding (non-meta) instruction and will be performed immediately after the execution of that instruction. annote_prepost= annote_example=annote SP -1 0 red "Pushed constants" ; annote top 2 stack values
\ No newline at end of file
lx: ly: l1: lz: ldc 3 ldc 4 ldc -4 ldc 0x5 ldc -0x6 ldc l3 annote SP -3 0 red "Pushed constants" add mul sub bra l2 l3: bra l1 l2: bra l3 ldc l4: bsr l4
\ No newline at end of file
LDC 2 LDC 3 ADD
\ No newline at end of file
LDC 4 LDC 5 MUL LDC 2 LDC 6 MUL ADD
\ No newline at end of file
; ; Iterative version of faculty ; bra main Fac: link 1 ; fac( int n ) LDC 1 ; int res = 1 ; stl 1 FacTst: ldl -2 ; while ( n > 1 ) LDC 1 gt brf FacEnd ldl -2 ; res = res * n ldl 1 mul stl 1 ldl -2 ; n = n - 1 LDC 1 sub stl -2 bra FacTst FacEnd: ldl 1 ; return( res ) str RR unlink sts -1 ret main: LDC 6 bsr Fac ; fac( 6 ) trap 0 halt
\ No newline at end of file
bra main Fac: link 0 // fac( int n ) ldl -2 // if ( n <= 1 ) LDC 1 le brt FacTh ldl -2 // else return( n * fac( n-1 ) ) ; ldl -2 LDC 1 sub bsr Fac ldr RR mul bra FacEnd FacTh: LDC 1 // then return( 1 ) FacEnd: str RR unlink sts -1 ret main: LDC 6 annote SP 0 0 green argument bsr Fac // fac( 6 ) halt
\ No newline at end of file
BRA Main DoPtr: LINK 2 LDC 0x33333333 ; i = ... STL 2 LDLA 2 ; pi = & i STL 1 LDL 1 ; i = *pi LDA 0 STL 2 LDC 0x44444444 LDL 1 ; *pi = ... STA 0 LDC 0x55555555 ; invalid ref, *0x55555555 LDA 0 UNLINK RET Main: BSR DoPtr
\ No newline at end of file
BRA main Swap2Ints: LINK 1 LDL -3 LDA 0 STL 1 LDL -2 LDA 0 LDL -3 STA 0 LDL -2 LDL 1 STA 0 UNLINK STS -2 AJS -1 RET main: LINK 2 LDC 4 STL 1 LDC 6 STL 2 LDLA 1 LDLA 2 BSR Swap2Ints UNLINK
\ No newline at end of file
BRA main f: LINK 2 LDL -3 LDL -2 ADD STL 1 LDL -3 LDL -2 MUL STL 2 LDL 2 LDL 1 SUB STR RR UNLINK STS -2 AJS -1 RET g: LINK 1 LDC 3 LDC 4 LDL -2 BSR f LDR RR MUL STL 1 UNLINK STS -1 RET main: LINK 0 LDC 5 BSR g UNLINK
\ No newline at end of file
BRA main CpInts: LINK 0 CpBeg: LDL -2 LDC 0 EQ BRT CpEnd LDL -2 LDC 1 SUB STL -2 LDL -4 LDL -2 ADD LDA 0 LDL -3 LDL -2 ADD STA 0 BRA CpBeg CpEnd: UNLINK STS -3 AJS -2 RET main: LINK 12 LDLA 1 LDLA 6 LDC 4 BSR CpInts UNLINK
\ No newline at end of file
BRA Main DoIf: LINK 1 LDL -2 LDC 2 MOD LDC 0 ne brt Then LDC 0 STL 1 BRA IfEnd Then: LDC 1 STL 1 IfEnd: UNLINK STS -1 RET Main: LDC 10 BSR DoIf LDC 11 BSR DoIf
\ No newline at end of file
BRA main max3: LINK 0 LDL -3 LDL -2 le brt L1 LDL -3 STL -2 L1: LDL -4 LDL -2 le brt L2 LDL -4 STL -2 L2: LDL -2 STR RR UNLINK STS -3 AJS -2 RET main: LINK 0 LDC 4 LDC 5 MUL LDC 2 LDC 8 LDC 6 BSR max3 LDR RR ADD UNLINK
\ No newline at end of file
BRA main max3: LINK 0 LDL -3 LDL -2 GT BRF L1 LDL -3 STL -2 L1: LDL -4 LDL -2 GT BRF L2 LDL -4 STL -2 L2: LDL -2 STR RR UNLINK STS -3 AJS -2 RET main: LINK 0 LDC 4 LDC 5 MUL LDC 2 LDC 8 LDC 6 BSR max3 LDR RR ADD UNLINK
\ No newline at end of file
ldc 4 ldc 5 ldms -1 2 ldms -2 3 ldc 4 ldma 2 5 mul stml 1 4
\ No newline at end of file
<html><head><title>SSM Changes</title><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></head> <body bgcolor="#FFFFFF"><h2>Changes in SSM</h2><h3></h3><h3>Version 1.3</h3><ul> <li>20020407. <ul> <li>Added backward stepping (undoing).</li> <li>The instructions in the code pane now also display their arguments, as mnemonic if possible.</li> <li>If code changes during execution a warning is printed.</li> </ul> </li></ul><h3></h3><h3>Version 1.2.3</h3><ul> <li>20020213. Fixed documentation errors.</li></ul><h3>Version 1.2.2</h3><ul> <li>20011210. Fixed some weird splitpane behavior and other GUI stuff. The tests now reflect the the instruction set.</li></ul><h3>Version 1.2.1</h3><ul> <li>20010330. Toolbar had disappeared, it now displays again (untested on WinXX JDK1.3)</li></ul><h3></h3><h3></h3><h3>Version 1.2</h3><ul> <li>20010131. Added blockmove instructions, deleted 'cmp' and related 'brcc' instructions. Changed definition of 'sta' (swapping of parameters on stack) to be consistent with 'stma'. The address is now on top.</li></ul><h3>Version 1.1.3</h3><ul> <li>20000928. Repaired documentation bug for 'jsr'.</li></ul><h3></h3><h3>Version 1.1.2</h3><ul> <li>20000914, Added 'brt' instruction. True is 0xFFFFFFFF (-1).</li></ul><h3>Version 1.1.1</h3><ul> <li>20000912, Fixed documentation errors.</li></ul><h3></h3><h3>Version 1.1</h3><ul> <li>20000911, Added instructions 'eq', 'ne', 'lt', 'le', 'gt', 'ge' and 'brf' for comparing purposes. Added 'ldrr' and 'swprr' for register manipulation.</li></ul><h3></h3><h3>Version 1.0.2</h3><ul> <li> 20000911, Fixed examples in help w.r.t. labels &amp; ':'.</li> <li> 20000911, Tables for instruction description fixed width.</li></ul><h3>Version 1.0.1</h3><ul> <li>20000910, Added Trap instruction.</li> <li>20000909, Changed name of instruction 'ld' to 'lds', 'st' to 'sts'. Added 'ldsa', 'ldaa'. All for better orthogonality of instructionset.</li> <li>20000909, Automatic scroll of codepane to position of PC.</li></ul></body></html>
\ No newline at end of file
src/logo.GIF

853 Bytes

/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ; abstract class AbstractMemoryCellModel extends Model implements MemoryCellModel{ protected void fireCellChange( MemoryCellModel m, MemoryCellEvent ev ) { for( Enumeration e = getListeners() ; e.hasMoreElements() ; ) { MemoryCellListener l = (MemoryCellListener)e.nextElement() ; l.cellChanged( ev ) ; } } protected void fireCellChange( MemoryCellModel m, int cellIndex, int oldCellValue, Modification mdf ) { fireCellChange( m, new MemoryCellEvent( m, cellIndex, oldCellValue, mdf ) ) ; } protected void fireCellChange( MemoryCellModel m, int cellIndex, MemoryAnnotation oldCellValue, Modification mdf ) { fireCellChange( m, new MemoryCellEvent( m, cellIndex, oldCellValue, mdf ) ) ; } public void addMemoryCellListener( MemoryCellListener l ) { addListener( l ) ; } public void removeMemoryCellListener( MemoryCellListener l ) { removeListener( l ) ; } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ;import java.awt.* ; public class ColoredText{ public static final ColoredText blankDefault = new ColoredText( "", Color.gray ) ; private String text ; private Color color ; public ColoredText( String t, Color c ) { text = t ; color = c ; } public String getText() { return text ; } public Color getColor() { return color ; } public String toString() { return "ColoredText " + text ; } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ /** * Configuration * */package nl.uu.cs.ssm ; import java.awt.event.KeyEvent ; public class Config{ public static final int[] keysLoad = { KeyEvent.VK_O } ; public static final int[] keysReload = { KeyEvent.VK_R } ; public static final int[] keysPause = { KeyEvent.VK_SPACE } ; public static final int[] keysFullForward = { KeyEvent.VK_DOWN } ; public static final int[] keysFullBackward = { KeyEvent.VK_UP } ; public static final int[] keysStep1Forward = { KeyEvent.VK_RIGHT, KeyEvent.VK_SPACE } ; public static final int[] keysStep1Backward = { KeyEvent.VK_LEFT, KeyEvent.VK_BACK_SPACE } ; public static final String extensionSSM = "ssm" ; public static final int allowedAutomaticMemoryIncrease = 100 ; public static final String version() { return "1.3.3" ; } public static final String versionDate() { return "2002 04 15" ; } public static final String author() { return "Atze Dijkstra, Utrecht University" ; } public static final String authorEmail() { return "atze@cs.uu.nl" ; } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ;import java.io.* ; public abstract class HelpAccumulator{ //private StringBuffer accumulator ; protected Writer accumulator ; public HelpAccumulator( String fileName ) { try { //System.out.println( "help acc " + fileName ) ; if ( fileName == null ) accumulator = new StringWriter() ; else accumulator = new FileWriter( fileName ) ; } catch( IOException ex ) { ex.printStackTrace() ; accumulator = null ; } } protected boolean canWrite() { return accumulator != null ; } public abstract void beginHeadTitleBody( String t ) ; public abstract void endHeadTitleBody() ; public abstract void anchor( String a ) ; public abstract void a( String href, String title ) ; public abstract void anchorA( String href, String title ) ; public abstract void beginCentered() ; public abstract void endCentered() ; public abstract void beginPara() ; public abstract void endPara() ; public void para( String text ) { beginPara( ) ; append( text ) ; endPara() ; } public abstract void beginSectionTitle() ; public abstract void endSectionTitle() ; public void sectionTitle( String s ) { beginSectionTitle() ; append( s ) ; endSectionTitle() ; } public abstract void beginSubsectionTitle() ; public abstract void endSubsectionTitle() ; public void subsectionTitle( String s ) { beginSubsectionTitle() ; append( s ) ; endSubsectionTitle() ; } public abstract void beginTable( int nCols, int widthPerc, int[] colWidthWeight ) ; public abstract void endTable() ; public abstract void beginTableRow( ) ; public abstract void endTableRow() ; public abstract void beginTableData( ) ; public abstract void endTableData() ; public void tableRow( Object[] data ) // not recursive (yet) { beginTableRow() ; for ( int i = 0 ; i < data.length ; i++ ) { beginTableData() ; append( data[i].toString() ) ; endTableData() ; } endTableRow() ; } public void tableHeaderRow( Object[] data ) // not recursive (yet) { beginTableRow() ; for ( int i = 0 ; i < data.length ; i++ ) { beginTableData() ; bold( data[i].toString() ) ; endTableData() ; } endTableRow() ; } public abstract void beginBlockQuote( ) ; public abstract void endBlockQuote() ; public abstract void linebreak() ; public void append( String o ) { if ( ! canWrite() ) return ; try { accumulator.write( o ) ; } catch ( IOException ex ) { accumulator = null ; } } public void append( char o ) { append( "" + o ) ; } public void append( int o ) { append( "" + o ) ; } public void nl( ) { append( '\n' ) ; } //public abstract void font( String f, String s ) ; public abstract void bold( String s ) ; public void string( String s ) { append( "\"" ) ; append( s ) ; append( "\"" ) ; } //public abstract void define( String nm, String val ) ; public void close( ) { try { accumulator.close() ; } catch ( IOException ex ) { } } public String toString() { close() ; if ( accumulator instanceof StringWriter ) return accumulator.toString() ; else return "" ; } public abstract void mathEquationList( Enumeration e, char subscript ) ; public abstract void beginVerbatimList() ; public abstract void endVerbatimList() ; public abstract void verbatimLine( String s ) ; public void verbatimList( Enumeration e ) { if ( ! e.hasMoreElements() ) return ; beginVerbatimList() ; for ( ; e.hasMoreElements() ; ) { verbatimLine( (String)e.nextElement() ) ; } endVerbatimList() ; } public abstract void beginAttributeList( ) ; public abstract void endAttributeList( ) ; public abstract void attributeName( String s ) ; public abstract void beginAttributeValue( ) ; public abstract void endAttributeValue( ) ; public String reprAsHex( int v ) { return Utils.asHex( v, false ) ; } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ;import java.io.* ; public class HelpHTMLAccumulator extends HelpAccumulator{ private boolean isOldHtml ; public HelpHTMLAccumulator( boolean old, String fileName ) { super( fileName ) ; isOldHtml = old ; } private void beginTag( String t, boolean end ) { append( '<' ) ; if ( end ) append( '/' ) ; append( t ) ; } private void endTag( ) { append( '>' ) ; } private void tag( String t, boolean end, String params ) { beginTag( t, end ) ; if ( params != null ) { append( " " ) ; append( params ) ; } endTag() ; } private void tag( String t, boolean end ) { tag( t, end, null ) ; } private void tagged( String t, String s ) { tag( t, false ) ; append( s ) ; tag( t, true ) ; } public void beginHeadTitleBody( String t ) { if ( ! isOldHtml ) { tag( "!doctype", false, "html public \"-//w3c//dtd html 4.0 transitional//en\"" ) ; tag( "html", false ) ; tag( "head", false ) ; tag( "meta", false, "http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"" ) ; tag( "meta", false, "name=\"GENERATOR\" content=\"Simple Stack Machine, " + Config.version() + ", " + Config.versionDate() + "\"" ) ; tag( "title", false ) ; append( t ) ; tag( "title", true ) ; tag( "head", true ) ; } tag( "body", false ) ; } public void endHeadTitleBody() { tag( "body", true ) ; if ( ! isOldHtml ) { tag( "html", true ) ; } } private void beginA( String name, String href ) { beginTag( "a", false ) ; if ( href != null ) define( "href", href ) ; if ( name != null ) define( "name", name ) ; endTag() ; } private void endA() { tag( "a", true ) ; } public void anchor( String a ) { beginA( a, null ) ; endA( ) ; } public void a( String href, String title ) { beginA( null, href ) ; append( title ) ; endA( ) ; } public void anchorA( String href, String title ) { a( "#" + href, title ) ; } private void beginPara( String align ) { beginTag( "p", false ) ; if ( align != null ) define( "align", align ) ; endTag() ; } public void beginPara( ) { beginPara( null ) ; } public void endPara() { tag( "p", true ) ; } public void beginCentered( ) { beginPara( "center" ) ; } public void endCentered() { endPara() ; } public void beginSectionTitle() { tag( "h2", false ) ; } public void endSectionTitle() { tag( "h2", true ) ; } public void beginSubsectionTitle() { tag( "h3", false ) ; } public void endSubsectionTitle() { tag( "h3", true ) ; } public void beginTable( int nCols, int widthPerc, int[] colWidthWeight ) { tag( "table", false, "BORDER COLS=" + nCols + " WIDTH=\"" + (widthPerc == 0 ? 100 : widthPerc) + "%\"" ) ; } public void endTable() { tag( "table", true ) ; } public void beginTableRow( ) { tag( "tr", false ) ; } public void endTableRow() { tag( "tr", true ) ; } public void beginTableData( ) { tag( "td", false ) ; } public void endTableData() { tag( "td", true ) ; } public void beginBlockQuote( ) { tag( "blockquote", false ) ; } public void endBlockQuote() { tag( "blockquote", true ) ; } public void linebreak() { tag( "br", false ) ; } private void font( String f, String s ) { tag( f, false ) ; append( s ) ; tag( f, true ) ; } public void bold( String s ) { font( "b", s ) ; } private void define( String nm, String val ) { append( " " ) ; append( nm ) ; append( "=" ) ; string( val ) ; } public void mathEquationList( Enumeration e, char subscript ) { for ( ; e.hasMoreElements() ; ) { append( ((String)e.nextElement()) ) ; if ( e.hasMoreElements() ) linebreak() ; } } public void beginAttributeList( ) { } public void endAttributeList( ) { } public void attributeName( String s ) { subsectionTitle( s ) ; } public void beginAttributeValue( ) { beginBlockQuote() ; } public void endAttributeValue( ) { endBlockQuote() ; } public void beginVerbatimList() { tag( "pre", false ) ; nl() ; } public void endVerbatimList() { tag( "pre", true ) ; nl() ; } public void verbatimLine( String s ) { append( s ) ; nl() ; } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ;import java.io.* ; public class HelpLaTeXAccumulator extends HelpAccumulator{ public HelpLaTeXAccumulator( String fileName ) { super( fileName ) ; } private void beginEnv( String t, String param ) { macro( "begin", t ) ; if ( param != null ) bracket( param ) ; } private void beginEnv( String t ) { beginEnv( t, null ) ; } private void endEnv( String t ) { macro( "end", t ) ; } private void beginMath( ) { macro( "(" ) ; } private void endMath() { macro( ")" ) ; } private void beginParen( ) { append( '(' ) ; } private void endParen( ) { append( ')' ) ; } private void beginBracket( ) { append( '{' ) ; } private void endBracket( ) { append( '}' ) ; } private void bracket( String t ) { beginBracket( ) ; append( t ) ; endBracket() ; } private void beginMacro( String t ) { append( '\\' ) ; append( t ) ; beginBracket() ; } private void endMacro( ) { endBracket() ; } private void macro( String t, String a1 ) { append( '\\' ) ; append( t ) ; if ( a1 != null ) bracket( a1 ) ; else append( " " ) ; } private void macro( String t ) { macro( t, null ) ; } public void beginHeadTitleBody( String t ) { } public void endHeadTitleBody() { } public void anchor( String a ) { macro( "label", "ssmanchor:" + a ) ; macro( "Ix", a ) ; } public void a( String href, String title ) { append( title ) ; beginParen() ; macro( "Ref", href ) ; endParen() ; } public void anchorA( String href, String title ) { a( "ssmanchor:" + href, title ) ; } public void beginPara( ) { nl() ; nl() ; } public void endPara() { nl() ; nl() ; } public void beginCentered( ) { beginEnv( "center" ) ; } public void endCentered() { endEnv( "center" ) ; } public void beginSectionTitle() { beginMacro( "Sec" ) ; } public void endSectionTitle() { endMacro() ; } public void beginSubsectionTitle() { beginMacro( "Par" ) ; } public void endSubsectionTitle() { endMacro() ; } public void beginTable( int nCols, int widthPerc, int[] colWidthWeight ) { int perc = Math.min( 99, widthPerc ) ; StringBuffer colFmt = new StringBuffer() ; colFmt.append( "l" ) ; beginEnv( "tabular*", "0." + perc + "\\textwidth" ) ; if ( colWidthWeight == null ) { colFmt.append( "l" + Utils.repeat( "p{0." + (perc / nCols) + "\\textwidth}", nCols ) ) ; } else { int sum = 0 ; for ( int i = 0 ; i < colWidthWeight.length ; i++ ) sum += colWidthWeight[ i ] ; for ( int i = 0 ; i < colWidthWeight.length ; i++ ) colFmt.append( "p{0." + (perc * colWidthWeight[ i ] / sum) + "\\textwidth}" ) ; } bracket( colFmt.toString() ) ; } public void endTable() { endEnv( "tabular*" ) ; } public void beginTableRow( ) { } public void endTableRow() { linebreak() ; } public void beginTableData( ) { append( "& " ) ; macro( "begingroup" ) ; macro( "raggedright" ) ; } public void endTableData() { macro( "endgroup" ) ; } public void beginBlockQuote( ) { } public void endBlockQuote() { } public void linebreak() { append( "\\\\" ) ; nl() ; } public void bold( String s ) { beginBracket() ; macro( "bf" ) ; append( s ) ; endBracket() ; } private final static int MATH_NORMAL = 0 ; private final static int MATH_SUBSCRIPT = 1 ; private void mathMangle( String s, char subscript ) { StreamTokenizer t = new StreamTokenizer( new StringReader( s ) ) ; t.resetSyntax() ; t.wordChars( 'a', 'z' ) ; t.wordChars( 'A', 'Z' ) ; int tok ; int state = MATH_NORMAL ; beginMath() ; try { while ( ( tok = t.nextToken() ) != StreamTokenizer.TT_EOF ) { if ( tok == StreamTokenizer.TT_WORD ) { if ( state == MATH_SUBSCRIPT ) { bracket( t.sval ) ; state = MATH_NORMAL ; } else append( t.sval ) ; } else { if ( tok == subscript ) state = MATH_SUBSCRIPT ; if ( tok == '&' || tok == '%' ) append( '\\' ) ; append( (char)tok ) ; } } } catch ( IOException ex ) { append( ex.toString() ) ; } endMath() ; } public void mathEquationList( Enumeration e, char subscript ) { for ( ; e.hasMoreElements() ; ) { mathMangle( ((String)e.nextElement()), subscript ) ; if ( e.hasMoreElements() ) linebreak() ; } } public void beginAttributeList( ) { beginBracket() ; macro( "renewcommand", "\\arraystretch" ) ; bracket( "1.7" ) ; beginTable( 2, 90, new int[] {1,2} ) ; } public void endAttributeList( ) { endTable() ; endBracket() ; } public void attributeName( String s ) { beginTableRow() ; beginTableData() ; bold( s ) ; endTableData() ; } public void beginAttributeValue( ) { beginTableData() ; beginEnv( "minipage" ) ; append( "[t]" ) ; bracket( "0.6\\textwidth" ) ; } public void endAttributeValue( ) { endEnv( "minipage" ) ; endTableData() ; endTableRow() ; } public void beginVerbatimList() { beginEnv( "Verbatim" ) ; nl() ; } public void endVerbatimList() { endEnv( "Verbatim" ) ; nl() ; } public void verbatimLine( String s ) { append( s ) ; nl() ; } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ; public interface HelpSupplier{ public Enumeration getTopics() ; public String getHelpSupplierName() ; public String getShortSummaryForTopic( String topic ) ; public void getHelpForTopic( String topic, HelpAccumulator acc ) ; }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ; public class Instruction implements HelpSupplier{ /** * Misc constants */ protected final static int UNKNOWN = -1 ; protected final static int nWordBits = 32 ; protected final static int CONST_TRUE = 0xFFFFFFFF; protected final static int CONST_FALSE = 0x00000000; /** * Condition codes */ protected final static int SR_Z = 0 ; protected final static int SR_C = 1 ; protected final static int SR_V = 2 ; protected final static int SR_N = 3 ; protected final static int ZZ = 1<<SR_Z ; protected final static int CC = 1<<SR_C ; protected final static int VV = 1<<SR_V ; protected final static int NN = 1<<SR_N ; private final static String ccNames[] = { "Z", "C", "V", "N" } ; /** * Categories of inline operands */ protected final static int OPND_INL_PC_REL = 0 ; protected final static int OPND_INL_REG = 1 ; protected final static int OPND_INL_AS_IS = 2 ; /** * Categories of instructions */ protected final static int CTG_OP = 0 ; protected final static int CTG_BINOP = 1 ; protected final static int CTG_UNOP = 2 ; protected final static int CTG_PRAGMA = 3 ; protected final static int CTG_TRAP = 4 ; protected final static int CTG_BRCC = 5 ; protected final static int CTG_META = 6 ; private final static String[] categNames = { "Normal instruction", "Binary operator", "Unary operator", "Pragma", "Trap", "Branch on condition", "Meta" } ; /** * Binary int instructions */ protected final static int BI_ADD = 1 ; protected final static int BI_AND = 2 ; //protected final static int BI_CMP = 3 ; protected final static int BI_DIV = 4 ; protected final static int BI_LSL = 5 ; protected final static int BI_LSR = 6 ; protected final static int BI_MOD = 7 ; protected final static int BI_MUL = 8 ; protected final static int BI_OR = 9 ; protected final static int BI_ROL = 10 ; protected final static int BI_ROR = 11 ; protected final static int BI_SUB = 12 ; protected final static int BI_XOR = 13 ; protected final static int BI_EQ = 14 ; protected final static int BI_NE = 15 ; protected final static int BI_LT = 16 ; protected final static int BI_GT = 17 ; protected final static int BI_LE = 18 ; protected final static int BI_GE = 19 ; /** * Unary int instructions */ protected final static int UI_NEG = 32 ; protected final static int UI_NOT = 33 ; /** * Branch instructions */ /* protected final static int BR_CC = 64 ; protected final static int BR_CS = 65 ; protected final static int BR_EQ = 66 ; protected final static int BR_GE = 67 ; protected final static int BR_GT = 68 ; protected final static int BR_HI = 69 ; protected final static int BR_LE = 70 ; protected final static int BR_LS = 71 ; protected final static int BR_LT = 72 ; protected final static int BR_MI = 73 ; protected final static int BR_NE = 74 ; protected final static int BR_PL = 75 ; */ /** * Other instructions */ protected final static int I_ADJS = 100 ; protected final static int I_BRA = 104 ; protected final static int I_BRF = 108 ; protected final static int I_BRT = 109 ; protected final static int I_BSR = 112 ; protected final static int I_HALT = 116 ; protected final static int I_JSR = 120 ; protected final static int I_LDA = 124 ; protected final static int I_LDMA = 126 ; protected final static int I_LDAA = 128 ; protected final static int I_LDC = 132 ; protected final static int I_LDL = 136 ; protected final static int I_LDML = 138 ; protected final static int I_LDLA = 140 ; protected final static int I_LDR = 144 ; protected final static int I_LDRR = 148 ; protected final static int I_LDS = 152 ; protected final static int I_LDMS = 154 ; protected final static int I_LDSA = 156 ; protected final static int I_LINK = 160 ; protected final static int I_NOP = 164 ; protected final static int I_RET = 168 ; protected final static int I_STA = 172 ; protected final static int I_STMA = 174 ; protected final static int I_STL = 176 ; protected final static int I_STML = 178 ; protected final static int I_STR = 180 ; protected final static int I_STS = 184 ; protected final static int I_STMS = 186 ; protected final static int I_SWP = 188 ; protected final static int I_SWPR = 192 ; protected final static int I_SWPRR = 196 ; protected final static int I_TRAP = 200 ; protected final static int I_UNLINK = 204 ; /** * Pragma's */ protected final static int PR_DB = 250 ; protected final static int PR_DC = 251 ; protected final static int PR_DS = 252 ; protected final static int PR_DW = 253 ; /** * Traps */ protected final static int TR_PR_INT = 0 ; /** * Metas */ protected final static int M_ANNOTE = 255 ; private static Hashtable codeToInstr ; private static Hashtable reprToInstr ; private static void defBinOp( String repr, int code ) { new Instruction( repr, CTG_BINOP, code, 0, 2, 1, OPND_INL_AS_IS, null ) ; } private static void defMeta( String repr, int code, int nI, MetaInstrInstantiator mii ) { new Instruction( repr, CTG_META, code, nI, 0, 0, OPND_INL_AS_IS, mii ) ; } private static Instruction defBranchOp( String repr, int code ) { return new Instruction( repr, CTG_BRCC, code, 1, 1, 0, OPND_INL_PC_REL, null ) ; } private static void defInstr( String repr, int code, int nI, int nS, int nR, int inlOpndKind ) { new Instruction( repr, CTG_OP, code, nI, nS, nR, inlOpndKind, null ) ; } private static void defPragma( String repr, int code, int nI, int nS, int nR ) { new Instruction( repr, CTG_PRAGMA, code, nI, nS, nR, OPND_INL_AS_IS, null ) ; } private static void defRegInstr( String repr, int code, int nI, int nS, int nR ) { new Instruction( repr, CTG_OP, code, nI, nS, nR, OPND_INL_REG, null ) ; } private static void defUnOp( String repr, int code ) { new Instruction( repr, CTG_UNOP, code, 0, 1, 1, OPND_INL_AS_IS, null ) ; } private static void defTrap( String repr, int code ) { new Instruction( repr, CTG_TRAP, code, 0, 0, 0, OPND_INL_AS_IS, null ) ; } static { codeToInstr = new Hashtable() ; reprToInstr = new Hashtable() ; defBinOp ( "add" , BI_ADD ) ; defBinOp ( "and" , BI_AND ) ; //defBinOp ( "cmp" , BI_CMP ) ; defBinOp ( "div" , BI_DIV ) ; defBinOp ( "lsl" , BI_LSL ) ; defBinOp ( "lsr" , BI_LSR ) ; defBinOp ( "mod" , BI_MOD ) ; defBinOp ( "mul" , BI_MUL ) ; defBinOp ( "or" , BI_OR ) ; defBinOp ( "rol" , BI_ROL ) ; defBinOp ( "ror" , BI_ROR ) ; defBinOp ( "sub" , BI_SUB ) ; defBinOp ( "xor" , BI_XOR ) ; defBinOp ( "eq" , BI_EQ ) ; defBinOp ( "ne" , BI_NE ) ; defBinOp ( "lt" , BI_LT ) ; defBinOp ( "gt" , BI_GT ) ; defBinOp ( "le" , BI_LE ) ; defBinOp ( "ge" , BI_GE ) ; /* defBranchOp ( "bcc" , BR_CC ).defCCForBranch( 0, CC ) ; defBranchOp ( "bcs" , BR_CS ).defCCForBranch( CC, CC ) ; defBranchOp ( "beq" , BR_EQ ).defCCForBranch( ZZ, ZZ ) ; defBranchOp ( "bge" , BR_GE ).defCCForBranch( NN|VV, NN|VV, 0, NN|VV ) ; defBranchOp ( "bgt" , BR_GT ).defCCForBranch( NN|VV, NN|VV|ZZ, 0, NN|VV|ZZ ) ; defBranchOp ( "bhi" , BR_HI ).defCCForBranch( 0, ZZ|CC ) ; defBranchOp ( "ble" , BR_LE ).defCCForBranch( NN, NN|VV, VV, NN|VV, ZZ, ZZ ) ; defBranchOp ( "bls" , BR_LS ).defCCForBranch( CC, CC, ZZ, ZZ ) ; defBranchOp ( "blt" , BR_LT ).defCCForBranch( NN, NN|VV, VV, NN|VV ) ; defBranchOp ( "bmi" , BR_MI ).defCCForBranch( NN, NN ) ; defBranchOp ( "bne" , BR_NE ).defCCForBranch( 0, ZZ ) ; defBranchOp ( "bpl" , BR_PL ).defCCForBranch( 0, NN ) ; */ defInstr ( "ajs" , I_ADJS , 1, UNKNOWN, 0, OPND_INL_AS_IS ) ; defInstr ( "bra" , I_BRA , 1, 0, 0, OPND_INL_PC_REL ) ; defInstr ( "brf" , I_BRF , 1, 1, 0, OPND_INL_PC_REL ) ; defInstr ( "brt" , I_BRT , 1, 1, 0, OPND_INL_PC_REL ) ; defInstr ( "bsr" , I_BSR , 1, 0, 1, OPND_INL_PC_REL ) ; defInstr ( "halt", I_HALT , 0, 0, 0, OPND_INL_AS_IS ) ; defInstr ( "jsr" , I_JSR , 0, 1, 1, OPND_INL_AS_IS ) ; defInstr ( "lds" , I_LDS , 1, 0, 1, OPND_INL_AS_IS ) ; defInstr ( "ldms", I_LDMS , 2, 0, UNKNOWN, OPND_INL_AS_IS ) ; defInstr ( "ldsa", I_LDSA , 1, 0, 1, OPND_INL_AS_IS ) ; defInstr ( "lda" , I_LDA , 1, 1, 1, OPND_INL_AS_IS ) ; defInstr ( "ldma", I_LDMA , 2, 1, UNKNOWN, OPND_INL_AS_IS ) ; defInstr ( "ldaa", I_LDAA , 1, 1, 1, OPND_INL_AS_IS ) ; defInstr ( "ldc" , I_LDC , 1, 0, 1, OPND_INL_AS_IS ) ; defInstr ( "ldl" , I_LDL , 1, 0, 1, OPND_INL_AS_IS ) ; defInstr ( "ldml", I_LDML , 2, 0, UNKNOWN, OPND_INL_AS_IS ) ; defInstr ( "ldla", I_LDLA , 1, 0, 1, OPND_INL_AS_IS ) ; defInstr ( "link", I_LINK , 1, 0, UNKNOWN, OPND_INL_AS_IS ) ; defInstr ( "nop" , I_NOP , 0, 0, 0, OPND_INL_AS_IS ) ; defInstr ( "ret" , I_RET , 0, 1, 0, OPND_INL_AS_IS ) ; defInstr ( "sts" , I_STS , 1, 1, 0, OPND_INL_AS_IS ) ; defInstr ( "stms", I_STMS , 2, UNKNOWN, 0, OPND_INL_AS_IS ) ; defInstr ( "sta" , I_STA , 1, 2, 0, OPND_INL_AS_IS ) ; defInstr ( "stma", I_STMA , 2, UNKNOWN, 0, OPND_INL_AS_IS ) ; defInstr ( "stl" , I_STL , 1, 1, 0, OPND_INL_AS_IS ) ; defInstr ( "stml", I_STML , 2, UNKNOWN, 0, OPND_INL_AS_IS ) ; defInstr ( "swp" , I_SWP , 0, 2, 2, OPND_INL_AS_IS ) ; defInstr ( "trap", I_TRAP , 1, UNKNOWN, UNKNOWN, OPND_INL_AS_IS ) ; defInstr ( "unlink", I_UNLINK, 0, UNKNOWN, 0, OPND_INL_AS_IS ) ; //defPragma ( ".db" , PR_DB , UNKNOWN, 0, 0 ) ; //defPragma ( ".dc" , PR_DC , 1, 0, 0 ) ; //defPragma ( ".ds" , PR_DS , 1, 0, 0 ) ; //defPragma ( ".dw" , PR_DW , UNKNOWN, 0, 0 ) ; defRegInstr ( "ldr" , I_LDR , 1, 0, 1 ) ; defRegInstr ( "ldrr" , I_LDRR , 2, 0, 0 ) ; defRegInstr ( "str" , I_STR , 1, 1, 0 ) ; defRegInstr ( "swpr" , I_SWPR , 1, 1, 1 ) ; defRegInstr ( "swprr", I_SWPRR , 2, 0, 0 ) ; // ?? //defTrap ( "printf" , TR_PRINTF ) ; defUnOp ( "neg" , UI_NEG ) ; defUnOp ( "not" , UI_NOT ) ; defMeta ( "annote" , M_ANNOTE, 5, MetaInstrInstantiator.newAnnoteInstantiator() ) ; } public static Instruction findByRepr( String repr ) { return (Instruction)reprToInstr.get( repr ) ; } public static Instruction findByCode( int code ) { return (Instruction)codeToInstr.get( new Integer( code ) ) ; } private class CCInfo { int check, mask ; CCInfo( int c, int m ) { check = c ; mask = m ; } } private class OpndInfo { int inlineOpndKind ; OpndInfo( int io ) { inlineOpndKind = io ; } } private String repr ; private int categ ; private int code ; private int nrInlineOpnds ; private int nrStackOpnds ; private int nrStackResults ; private CCInfo[] brccInfo ; private OpndInfo[] opndInfo ; private MetaInstrInstantiator metaInstrInstantiator ; /** * Define an instruction */ private Instruction ( String repr, int categ, int code , int nInl, int nSt, int nR , int inlOpndKind , MetaInstrInstantiator mii ) { this.repr = repr ; this.categ = categ ; this.code = code ; this.nrInlineOpnds = nInl ; this.nrStackOpnds = nSt ; this.nrStackResults = nR ; codeToInstr.put( new Integer( code ), this ) ; reprToInstr.put( repr, this ) ; brccInfo = null ; metaInstrInstantiator = mii ; opndInfo = new OpndInfo[ nrInlineOpnds ] ; for ( int i = 0 ; i < opndInfo.length ; i++ ) opndInfo[ i ] = new OpndInfo( inlOpndKind ) ; } private void defCCForBranch( int check1, int mask1, int check2, int mask2, int check3, int mask3 ) { brccInfo = new CCInfo[] { new CCInfo(check1, mask1), new CCInfo(check2, mask2), new CCInfo(check3, mask3) } ; } private void defCCForBranch( int check1, int mask1, int check2, int mask2 ) { brccInfo = new CCInfo[] { new CCInfo(check1, mask1), new CCInfo(check2, mask2) } ; } private void defCCForBranch( int check1, int mask1 ) { brccInfo = new CCInfo[] { new CCInfo(check1, mask1) } ; } protected boolean srMatchesCCInfo( int sr ) { if ( brccInfo != null ) { for ( int i = 0 ; i < brccInfo.length ; i++ ) { if ( ( sr & brccInfo[i].mask ) == brccInfo[i].check ) return true ; } } return false ; } public int getNrInlineOpnds() { return nrInlineOpnds ; } public String getRepr() { return repr ; } public String getRepr( int[] args ) { String s = getRepr() ; for ( int i = 0 ; i < args.length ; i++ ) { String a ; switch( opndInfo[ i ].inlineOpndKind ) { case OPND_INL_REG : a = Registers.getRegOrAliasName( args[i] ) ; break ; default : a = Utils.asHex( args[i], false, true, false ) ; break ; } s = s + " " + a ; } return s ; } public String getRepr( String usedLabel ) { return getRepr() + " " + usedLabel ; } public int getCode() { return code ; } public int getNrMemCells() { return getNrInlineOpnds() + 1 ; } protected int getNrStackOpnds() { return nrStackOpnds ; } protected int getNrStackResults() { return nrStackResults ; } public boolean isRelativeOpnd( int arg ) { return opndInfo[ arg ].inlineOpndKind == OPND_INL_PC_REL ; } public boolean isMeta( ) { return getCategory() == CTG_META ; } public MetaInstruction instantiateMeta( Vector args ) { return metaInstrInstantiator.instantiate( this, args ) ; } protected int getCategory() { return categ ; } private String getCategoryName() { return categNames[ getCategory() ] ; } private static Enumeration getInstructionNames() { return reprToInstr.keys() ; } public static HelpSupplier getHelpSupplier() { return findByRepr( "halt" ) ; } public Enumeration getTopics() { return getInstructionNames() ; } public String getHelpSupplierName() { return "Internal administration" ; } public String getShortSummaryForTopic( String topic ) { Instruction instr ; if ( ( instr = findByRepr( topic ) ) != null ) { return instr.getRepr() + " internal administration only" ; } return "" ; } private static String textForNr( int n ) { return n == UNKNOWN ? "instruction dependent" : "" + n ; } private void getHelpOnCC( HelpAccumulator acc ) { for ( int i = 0 ; i < brccInfo.length ; i++ ) { acc.append( "(" ) ; for ( int cc = SR_Z ; cc <= SR_N ; cc++ ) { if ( ((1<<cc) & brccInfo[i].mask) > 0 ) { acc.append( ccNames[cc] + "=" + ( (brccInfo[i].check >> cc) & 1 ) ) ; if ( brccInfo[i].mask >> (cc+1) > 0 ) { acc.append( " and " ) ; } } } acc.append( ")" ) ; if ( i < (brccInfo.length - 1) ) { acc.append( " or " ) ; } } } public void getHelpForTopic( String topic, HelpAccumulator acc ) { Instruction instr ; if ( ( instr = findByRepr( topic ) ) == null ) { acc.append( "?? should not happen, no help for " + topic ) ; } else { acc.beginBlockQuote() ; acc.beginTable( 5, 85, null ) ; acc.tableHeaderRow ( new Object[] { "Instruction" , "Nr of inline Opnds" , "Nr of stack Opnds" , "Nr of stack Results" , "Instr code (hex)" } ) ; acc.tableRow ( new Object[] { topic , textForNr( instr.getNrInlineOpnds() ) , textForNr( instr.getNrStackOpnds() ) , textForNr( instr.getNrStackResults() ) , acc.reprAsHex( instr.getCode() ) } ) ; acc.endTable() ; /* acc.linebreak() ; acc.append( "Is a " + instr.getCategoryName() + "." ) ; if ( instr.brccInfo != null ) { acc.linebreak() ; acc.append( "Branches on " ) ; instr.getHelpOnCC( acc ) ; } */ acc.endBlockQuote() ; } } public String toString() { return "instr " + repr + " code=(" + Utils.asHex(categ) + "/" + Utils.asHex(code) + ") ninl=" + nrInlineOpnds ; } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ;import java.awt.* ; public class Machine{ protected Memory memory ; protected Registers registers ; protected MachineState state ; private Messenger messenger ; public Machine( MachineState st, Messenger m ) { state = st ; messenger = m ; reset() ; } public void reset() { state.reset() ; memory = state.getMemory() ; registers = state.getRegisters( ) ; } public MachineState state() { return state ; } public Memory memory() { return memory ; } public Registers registers() { return registers ; } private int dir( int v ) { return state.dir( v ) ; } private void annote( MemoryAnnotation ann ) { memory.setAnnotationAt( registers.getReg( registers.SP ), ann ) ; } private void copyMem( int fromA, int toA, int size, MemoryAnnotation ann ) { if ( dir(fromA) < dir(toA) ) { for ( int i = size-1 ; i >= 0 ; i-- ) memory.setAt( toA + dir(i), memory.getAt( fromA + dir(i) ) ) ; } else { for ( int i = 0 ; i < size ; i++ ) memory.setAt( toA + dir(i), memory.getAt( fromA + dir(i) ) ) ; } for ( int i = 0 ; i < size ; i++ ) memory.setAnnotationAt( toA + dir(i), ann ) ; } private void pushMultiple( int fromA, int sz, MemoryAnnotation ann ) { int toA = registers.getReg( registers.SP ) + dir(1) ; registers.adjustSP( dir(sz) ) ; copyMem( fromA, toA, sz, ann ) ; } private void pushMultiple( int fromA, int sz, Instruction instr ) { pushMultiple( fromA, sz, new MemoryAnnotation( instr.getRepr(), null ) ) ; } private void pushMultiple( int fromA, int sz ) { pushMultiple( fromA, sz, state.instr ) ; } private void push( int v, MemoryAnnotation ann ) { registers.adjustSP( dir(1) ) ; registers.setRegInd( registers.SP, v ) ; annote( ann ) ; } private void push( int v, Instruction instr ) { push( v, new MemoryAnnotation( instr.getRepr(), null ) ) ; } private void push( int v ) { push( v, state.instr ) ; } private void pushCopyOfReg( int r ) { push( registers.getReg(r), new MemoryAnnotation( "copy of " + registers.getRegName(r), Color.cyan ) ) ; } private void pushPCAsReturnAddr() { push( registers.getReg(registers.PC), new MemoryAnnotation( "return addr ", Color.red ) ) ; } private void pushMP() { push( registers.getReg(registers.MP), new MemoryAnnotation( "prev " + registers.getRegName(registers.MP), Color.blue ) ) ; } private int pop() { annote( null ) ; int v = registers.getRegInd( registers.SP ) ; registers.adjustSP( dir(-1) ) ; return v ; } private void popMultiple( int toA, int sz ) { registers.adjustSP( dir(-sz) ) ; int fromA = registers.getReg( registers.SP ) + dir(1) ; copyMem( fromA, toA, sz, null ) ; } public MachineState getMachineState() { return state ; } private int fetchNextInstr() { int pc = registers.getPC() ; int oldpc = pc ; int code = memory.getAt( pc ) ; pc++ ; Instruction instr = Instruction.findByCode( code ) ; if ( instr == null ) { messenger.println( "illegal instruction code " + Utils.asHex(code) ) ; code = Instruction.I_HALT ; instr = Instruction.findByCode( code ) ; } else { state.setCurrentInstr( oldpc, code, instr ) ; for ( int i = 0 ; i < state.nInlineOpnds ; i++ ) { state.inlineOpnds[ i ] = memory.getAt( pc++ ) ; } } registers.setPC( pc ) ; return code ; } public int execBinop( int code, int o1, int o2 ) { switch( code ) { case Instruction.BI_ADD : o1 += o2 ; break ; case Instruction.BI_SUB : o1 -= o2 ; break ; case Instruction.BI_MUL : o1 *= o2 ; break ; case Instruction.BI_DIV : o1 /= o2 ; break ; case Instruction.BI_MOD : o1 %= o2 ; break ; case Instruction.BI_AND : o1 &= o2 ; break ; case Instruction.BI_OR : o1 |= o2 ; break ; case Instruction.BI_XOR : o1 ^= o2 ; break ; case Instruction.BI_LSL : o1 <<= o2 ; break ; case Instruction.BI_LSR : o1 >>= o2 ; break ; case Instruction.BI_ROL : o1 = ( o1 << o2 ) | ( o1 >> ( Instruction.nWordBits - o2 ) ) ; break ; case Instruction.BI_ROR : o1 = ( o1 >> o2 ) | ( o1 << ( Instruction.nWordBits - o2 ) ) ; break ; case Instruction.BI_EQ : o1 = o1 == o2 ? Instruction.CONST_TRUE : Instruction.CONST_FALSE ; break ; case Instruction.BI_NE : o1 = o1 != o2 ? Instruction.CONST_TRUE : Instruction.CONST_FALSE ; break ; case Instruction.BI_LT : o1 = o1 < o2 ? Instruction.CONST_TRUE : Instruction.CONST_FALSE ; break ; case Instruction.BI_GT : o1 = o1 > o2 ? Instruction.CONST_TRUE : Instruction.CONST_FALSE ; break ; case Instruction.BI_LE : o1 = o1 <= o2 ? Instruction.CONST_TRUE : Instruction.CONST_FALSE ; break ; case Instruction.BI_GE : o1 = o1 >= o2 ? Instruction.CONST_TRUE : Instruction.CONST_FALSE ; break ; /* case Instruction.BI_CMP : int sr, r, c1, c2 ; sr = c1 = c2 = 0 ; r = o1 - o2 ; if ( r == 0 ) sr |= Instruction.ZZ ; if ( (int)r < 0 ) sr |= Instruction.NN ; r = ( o1 >> 1 ) + ( ( - o2 ) >> 1 ) ; if ( (int)r < 0 ) { sr |= Instruction.CC ; c1 = Instruction.VV ; } r = ( ( o1 << 1 ) >> 1 ) + ( ( ( - o2 ) << 1 ) >> 1 ) ; if ( (int)r < 0 ) c2 = Instruction.VV ; sr |= ( c1 ^ c2 ) & Instruction.VV ; o1 = sr ; break ; */ } return o1 ; } public int execUnop( int code, int o1 ) { switch( code ) { case Instruction.UI_NEG : o1 = -o1 ; break ; case Instruction.UI_NOT : o1 = ~o1 ; break ; } return o1 ; } public void halt() { state.setHalted() ; messenger.println( "machine halted" ) ; } public void executeOne() { if ( state.isHalted ) return ; int code = fetchNextInstr() ; //System.out.println( "exec1 " + state ) ; int tmp1, tmp2, tmp3 ; switch( state.instr.getCategory() ) { case Instruction.CTG_BINOP : tmp2 = pop() ; tmp1 = pop() ; push( execBinop( code, tmp1, tmp2 ) ) ; break ; case Instruction.CTG_UNOP : tmp1 = pop() ; push( execUnop( code, tmp1 ) ) ; break ; case Instruction.CTG_OP : switch( code ) { case Instruction.I_ADJS : registers.adjustReg( registers.SP, dir(state.inlineOpnds[ 0 ]) ) ; break ; case Instruction.I_BRA : registers.adjustReg( registers.PC, state.inlineOpnds[ 0 ] ) ; break ; case Instruction.I_BRF : tmp1 = pop() ; if ( tmp1 == 0 ) registers.adjustReg( registers.PC, state.inlineOpnds[ 0 ] ) ; break ; case Instruction.I_BRT : tmp1 = pop() ; if ( tmp1 != 0 ) registers.adjustReg( registers.PC, state.inlineOpnds[ 0 ] ) ; break ; case Instruction.I_BSR : pushPCAsReturnAddr() ; registers.adjustReg( registers.PC, state.inlineOpnds[ 0 ] ) ; break ; case Instruction.I_HALT : halt() ; break ; case Instruction.I_JSR : tmp1 = pop() ; pushPCAsReturnAddr() ; registers.setReg( registers.PC, tmp1 ) ; break ; case Instruction.I_LDS : push( registers.getRegDisplInd( registers.SP, dir(state.inlineOpnds[ 0 ]) ) ) ; break ; case Instruction.I_LDMS : pushMultiple( registers.getRegDispl( registers.SP, dir(state.inlineOpnds[ 0 ]) ), state.inlineOpnds[ 1 ] ) ; break ; case Instruction.I_LDA : push( memory.getAt( pop() + dir(state.inlineOpnds[ 0 ]) ) ) ; break ; case Instruction.I_LDMA : pushMultiple( pop() + dir(state.inlineOpnds[ 0 ]), state.inlineOpnds[ 1 ] ) ; break ; case Instruction.I_LDC : push( state.inlineOpnds[ 0 ] ) ; break ; case Instruction.I_LDL : push( registers.getRegDisplInd( registers.MP, dir(state.inlineOpnds[ 0 ]) ) ) ; break ; case Instruction.I_LDML : pushMultiple( registers.getRegDispl( registers.MP, dir(state.inlineOpnds[ 0 ]) ), state.inlineOpnds[ 1 ] ) ; break ; case Instruction.I_LDAA : push( pop() + state.inlineOpnds[ 0 ] ) ; break ; case Instruction.I_LDSA : push( registers.getRegDispl( registers.SP, dir(state.inlineOpnds[ 0 ]) ) ) ; break ; case Instruction.I_LDLA : push( registers.getRegDispl( registers.MP, dir(state.inlineOpnds[ 0 ]) ) ) ; break ; case Instruction.I_LDR : pushCopyOfReg( state.inlineOpnds[ 0 ] ) ; break ; case Instruction.I_LDRR : registers.setReg( state.inlineOpnds[ 0 ], registers.getReg( state.inlineOpnds[ 1 ] ) ) ; break ; case Instruction.I_LINK : pushMP( ) ; registers.setReg( registers.MP, registers.getReg( registers.SP ) ) ; tmp1 = registers.getReg( registers.SP ) + dir(1) ; registers.adjustReg( registers.SP, dir(state.inlineOpnds[ 0 ]) ) ; tmp2 = registers.getReg( registers.SP ) ; break ; case Instruction.I_NOP : break ; case Instruction.I_RET : registers.setReg( registers.PC, pop() ) ; break ; case Instruction.I_STS : tmp1 = registers.getRegDispl( registers.SP, dir(state.inlineOpnds[ 0 ]) ) ; memory.setAt( tmp1, pop() ) ; break ; case Instruction.I_STMS : popMultiple( registers.getRegDispl( registers.SP, dir(state.inlineOpnds[ 0 ]) ), state.inlineOpnds[ 1 ] ) ; break ; case Instruction.I_STA : tmp1 = pop() ; tmp2 = pop() ; memory.setAt( tmp1 + state.inlineOpnds[ 0 ], tmp2 ) ; break ; case Instruction.I_STMA : tmp1 = pop() ; popMultiple( tmp1 + state.inlineOpnds[ 0 ], state.inlineOpnds[ 1 ] ) ; break ; case Instruction.I_STL : registers.setRegDisplInd( registers.MP, dir(state.inlineOpnds[ 0 ]), pop() ) ; break ; case Instruction.I_STML : popMultiple( registers.getRegDispl( registers.MP, dir(state.inlineOpnds[ 0 ]) ), state.inlineOpnds[ 1 ] ) ; break ; case Instruction.I_STR : registers.setReg( state.inlineOpnds[ 0 ], pop() ) ; break ; case Instruction.I_SWP : tmp1 = registers.getRegDisplInd( registers.SP, dir(-1) ) ; registers.setRegDisplInd( registers.SP, dir(-1), registers.getRegInd( registers.SP ) ) ; registers.setRegInd( registers.SP, tmp1 ) ; break ; case Instruction.I_SWPR : tmp1 = registers.getRegInd( registers.SP ) ; tmp2 = state.inlineOpnds[ 0 ] ; registers.setRegInd( registers.SP, registers.getReg( tmp2 ) ) ; registers.setReg( tmp2, tmp1 ) ; break ; case Instruction.I_SWPRR : tmp1 = state.inlineOpnds[ 0 ] ; tmp2 = state.inlineOpnds[ 1 ] ; tmp3 = registers.getReg( tmp1 ) ; registers.setReg( tmp1, registers.getReg( tmp2 ) ) ; registers.setReg( tmp2, tmp3 ) ; break ; case Instruction.I_UNLINK : registers.setReg( registers.SP, registers.getReg( registers.MP ) ) ; registers.setReg( registers.MP, pop() ) ; break ; case Instruction.I_TRAP : switch( state.inlineOpnds[ 0 ] ) { case Instruction.TR_PR_INT : messenger.println( "" + pop() ) ; break ; default : break ; } break ; default : messenger.println( state.instr + " at " + Utils.asHex(state.instrPC) + " not (yet) implemented" ) ; break ; } break ; case Instruction.CTG_BRCC : if ( state.instr.srMatchesCCInfo( pop() ) ) registers.adjustReg( registers.PC, state.inlineOpnds[ 0 ] ) ; break ; default : messenger.println( state.instr + " at " + Utils.asHex(state.instrPC) + " not (yet) implemented" ) ; break ; } } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ; public class MachineState extends Model{ protected int stackBottom ; protected int stackGrowthDir ; protected int code ; protected int instrPC ; protected Instruction instr ; protected int nInlineOpnds ; protected int inlineOpnds[] ; protected Memory memory ; protected Registers registers ; protected MemoryUser memoryUser ; public boolean isHalted ; public MachineState( int initMemCapacity, Messenger m ) { memory = new Memory( initMemCapacity, m ) ; registers = new Registers( memory, m ) ; stackGrowthDir = 1 ; reset() ; } protected void fireStateChange( MachineStateEvent ev ) { for( Enumeration e = getListeners() ; e.hasMoreElements() ; ) { MachineStateListener l = (MachineStateListener)e.nextElement() ; l.stateChanged( ev ) ; } } public void addMachineStateListener( MachineStateListener l ) { addListener( l ) ; } public void removeMachineStateListener( MachineStateListener l ) { removeListener( l ) ; } public void reset( ) { memory.reset() ; registers.reset() ; resetToInitialState() ; } public void resetToInitialState() { registers.setPC( 0 ) ; stackBottom = memory.getUsedForCode() + 16 ; registers.setSP( stackBottom - stackGrowthDir ) ; registers.setMP( registers.getSP() ) ; isHalted = false ; } public int dir( int v ) { return v * stackGrowthDir ; } public void setCurrentInstr( int pc, int code, Instruction instr ) { this.code = code ; instrPC = pc ; this.instr = instr ; nInlineOpnds = instr.getNrInlineOpnds() ; if ( nInlineOpnds > 0 ) inlineOpnds = new int[ nInlineOpnds ] ; } public Memory getMemory() { return memory ; } public int getStackBottom() { return stackBottom ; } public Registers getRegisters() { return registers ; } public boolean stackIsEmpty() { return stackBottom == registers.getSP() ; } public int stackTop() { return registers.getRegInd( registers.SP ) ; } public int getSR( ) { return stackIsEmpty() ? 0 : stackTop() ; } public String getSRAsString( ) { int sr = getSR() ; return "Z=" + ((sr & Instruction.ZZ) >> Instruction.SR_Z) + " C=" + ((sr & Instruction.CC) >> Instruction.SR_C) + " V=" + ((sr & Instruction.VV) >> Instruction.SR_V) + " N=" + ((sr & Instruction.NN) >> Instruction.SR_N) ; } class UndoStateModification implements Modification { private boolean wasHalted ; UndoStateModification( boolean h ) { wasHalted = h ; } public void modify() { isHalted = wasHalted ; } } public void setHalted() { isHalted = true ; fireStateChange( new MachineStateEvent( this, new UndoStateModification( false ) ) ) ; } public boolean isHalted() { return isHalted ; } public String toString() { return "state code=" + code + " instr-pc=" + instrPC + " n-inl=" + nInlineOpnds ; } }
\ No newline at end of file
/**
* Simple Stack Machine
*
* Written by Atze Dijkstra, atze@cs.uu.nl,
* Copyright Utrecht University.
*
*/
package nl.uu.cs.ssm ;
import java.util.* ;
public class MachineStateEvent extends UndoableEvent
{
protected MachineStateEvent( Object src, Modification mdf )
{
super( src, mdf ) ;
}
}
\ No newline at end of file
/**
* Simple Stack Machine
*
* Written by Atze Dijkstra, atze@cs.uu.nl,
* Copyright Utrecht University.
*
*/
package nl.uu.cs.ssm ;
import java.util.* ;
public interface MachineStateListener extends EventListener
{
public void stateChanged( MachineStateEvent e ) ;
}
/**
* Simple Stack Machine
*
* Written by Atze Dijkstra, atze@cs.uu.nl,
* Copyright Utrecht University.
*
*/
package nl.uu.cs.ssm ;
public class Main {
public static void main(String args[]) {
System.out.println( "Hello World!" );
}
}
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ; public class Memory extends AbstractMemoryCellModel implements MemoryCellModel{ private int cells[] ; private Hashtable annotations ; private int nUsedForCode ; private Messenger messenger ; protected Memory( int initCapacity, Messenger m ) { messenger = m ; cells = new int[ initCapacity ] ; for ( int i = 0 ; i < cells.length ; i++ ) cells[ i ] = 0 ; reset() ; } public void reset() { nUsedForCode = 0 ; annotations = new Hashtable() ; for ( int i = 0 ; i < cells.length ; i++ ) setAt( i, 0 ) ; } public int getCapacity() { return cells.length ; } public int getUsedForCode() { return nUsedForCode ; } private boolean checkWithinMemory( int addr ) { boolean res ; if ( res = ( addr < 0 || addr >= cells.length ) ) { messenger.println ( java.text.MessageFormat.format ( "attempt to access location {0} outside {1}" , new Object[] { Utils.asHex(addr), ""+this } ) ) ; } return ! res ; } class UndoMemoryModification implements Modification { private int offset, value ; UndoMemoryModification( int o, int v ) { offset = o ; value = v ; } public void modify() { setAt( offset, value ) ; } } public void setAt( int addr, int v ) { if ( checkWithinMemory( addr ) ) { int oldv = cells[ addr ] ; cells[ addr ] = v ; fireCellChange( this, addr, oldv, new UndoMemoryModification( addr, oldv ) ) ; } } public void setAt( int addr, String v ) { setAt( addr, Utils.fromHex( v ) ) ; } public int getAt( int addr ) { int res = 0 ; if ( checkWithinMemory( addr ) ) { res = cells[ addr ] ; } return res ; } public int[] getAt( int addr, int len ) { int res[] = new int[ len ] ; for ( int i = 0 ; i < len && checkWithinMemory( addr + i ) ; i++ ) { res[ i ] = cells[ addr + i ] ; } return res ; } public String getAsHexAt( int addr ) { return Utils.asHex( getAt( addr ) ) ; } class UndoAnnotationModification implements Modification { private int offset ; private MemoryAnnotation value ; UndoAnnotationModification( int o, MemoryAnnotation v ) { offset = o ; value = v ; } public void modify() { setAnnotationAt( offset, value ) ; } } public void setAnnotationAt( int addr, MemoryAnnotation v ) { if ( checkWithinMemory( addr ) ) { //System.out.println( "mem set annote at " + addr + "=" + v ) ; Integer a = new Integer( addr ) ; Object oldv ; if ( v != null ) oldv = annotations.put( a, v ) ; else oldv = annotations.remove( a ) ; if ( oldv != v ) fireCellChange( this, addr, (MemoryAnnotation)oldv, new UndoAnnotationModification( addr, (MemoryAnnotation)oldv ) ) ; } } public MemoryAnnotation getAnnotationAt( int addr ) { MemoryAnnotation res ; res = (MemoryAnnotation)annotations.get( new Integer(addr) ) ; //System.out.println( "mem got annote at " + addr + "=" + res ) ; return res ; } public void ensureCapacity( int nCells ) { if ( nCells > (cells.length - nUsedForCode) ) { int newCells[] = new int[ 2 * (nCells + 10) + cells.length ] ; System.arraycopy( cells, 0, newCells, 0, cells.length ) ; cells = newCells ; } } public void deleteAt( int pos, int n ) { for( int i = pos + n ; i < nUsedForCode ; i++ ) cells[ i-n ] = cells[ i ] ; nUsedForCode -= n ; } public void reserveAt( int pos, int n ) { ensureCapacity( n ) ; for( int i = nUsedForCode - 1 ; i >= pos ; i-- ) { cells[ i+n ] = cells[ i ] ; } for( int i = 0 ; i < n ; i++ ) cells[ i+pos ] = 0 ; nUsedForCode += n ; } public void shiftAt( int pos, int n ) { if ( n > 0 ) reserveAt( pos, n ) ; else if ( n < 0 ) deleteAt( pos, -n ) ; } public void copyAt( int pos, int[] vals ) { for( int i = 0 ; i < vals.length ; i++ ) cells[ i+pos ] = vals[ i ] ; } public void insertAt( int pos, int[] vals ) { reserveAt( pos, vals.length ) ; copyAt( pos, vals ) ; } public String toString() { return "memory [0(" + Utils.asHex(nUsedForCode,false) + ").." + Utils.asHex(getCapacity()-1,false) + "]" ; } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ;import java.awt.* ; public class MemoryAnnotation extends ColoredText{ public MemoryAnnotation( String ann, Color col ) { super( ann, col ) ; } public String getAnnotation() { return getText() ; } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ; class MemoryCell{ private int value = 0 ; private String label = null ; protected MemoryCell( int v ) { setValue( v ) ; } protected MemoryCell( ) { } public int getValue() { return value ; } public int setValue( int v ) { return value = v ; } public int swapValue( int v ) { int oldv = value ; value = v ; return oldv ; } public String getLabel() { return label ; } public String setLabel( String v ) { return label = v ; } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ; public class MemoryCellEvent extends UndoableEvent{ public static final int CELL = 0 ; public static final int ANNOTATION = 1 ; public int cellIndex ; public Object oldCellValue ; public int event ; protected MemoryCellEvent( Object src, int which, int previous, Modification mdf ) { super( src, mdf ) ; event = CELL ; cellIndex = which ; oldCellValue = new Integer( previous ) ; } protected MemoryCellEvent( Object src, int which, MemoryAnnotation previous, Modification mdf ) { super( src, mdf ) ; event = ANNOTATION ; cellIndex = which ; oldCellValue = previous ; } public int getCellIndex() { return cellIndex ; } public int getOldCellValue() { return ((Integer)oldCellValue).intValue() ; } public MemoryAnnotation getOldAnnotation() { return (MemoryAnnotation)oldCellValue ; } public String toString() { return "MemCellEvent src=" + getSource() + " inx=" + cellIndex + " prev=" + oldCellValue ; }}
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ; public interface MemoryCellListener extends EventListener{ public void cellChanged( MemoryCellEvent e ) ;}
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; interface MemoryCellModel{ public void addMemoryCellListener( MemoryCellListener l ) ; public void removeMemoryCellListener( MemoryCellListener l ) ; }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; public interface MemoryUser{ public int firstLocAfterCode() ;}
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; public interface Messenger{ public void println( String s ) ; }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ; public abstract class MetaInstrInstantiator{ protected MetaInstrInstantiator() { } public abstract MetaInstruction instantiate( Instruction instr, Vector args ) ; public static MetaInstrInstantiator newAnnoteInstantiator() { return new MetaInstrInstantiator() { public MetaInstruction instantiate( Instruction instr, Vector args ) { return MetaInstruction.newAnnote( instr, args ) ; } } ; }}
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ;import java.awt.* ; public abstract class MetaInstruction{ private static Hashtable colorMap ; static { colorMap = new Hashtable() ; colorMap.put( "black" , Color.black ) ; colorMap.put( "blue" , Color.blue ) ; colorMap.put( "cyan" , Color.cyan ) ; colorMap.put( "darkGray" , Color.darkGray ) ; colorMap.put( "gray" , Color.gray ) ; colorMap.put( "green" , Color.green ) ; colorMap.put( "lightGray" , Color.lightGray ) ; colorMap.put( "magenta" , Color.magenta ) ; colorMap.put( "orange" , Color.orange ) ; colorMap.put( "pink" , Color.pink ) ; colorMap.put( "red" , Color.red ) ; colorMap.put( "yellow" , Color.yellow ) ; } protected Instruction instruction ; private MetaInstruction( Instruction instr ) { instruction = instr ; } public abstract void exec( MachineState machineState ) ; private static class Annote extends MetaInstruction { int register ; int loDispl, hiDispl ; Color color ; String text ; Annote( Instruction i, int r, int l, int h, Color c, String t ) { super( i ) ; register = r ; loDispl = l ; hiDispl = h ; color = c ; text = t ; } public void exec( MachineState machineState ) { Memory mem = machineState.getMemory() ; Registers regs = machineState.getRegisters() ; for ( int i = loDispl ; i <= hiDispl ; i++ ) { mem.setAnnotationAt( regs.getRegDispl( register, i ), new MemoryAnnotation( text, color ) ) ; } } public String toString() { return "Annote reg=" + register + " displ=" + loDispl + "/" + hiDispl + " col=" + color + " text=" + text ; } } public static MetaInstruction newAnnote( Instruction instr, Vector args ) { int r = Registers.findRegOfName( (String)args.elementAt(0) ) ; int l = Utils.fromHex( (String)args.elementAt(1) ) ; int h = Utils.fromHex( (String)args.elementAt(2) ) ; Color c = (Color)colorMap.get( (String)args.elementAt(3) ) ; String t = (String)args.elementAt(4) ; if ( r >= 0 && l <= h && c != null && t != null ) return new Annote( instr, r, l, h, c, t ) ; else return null ; } }
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ; public class Model{ private Vector listeners = new Vector() ; protected void addListener( EventListener l ) { listeners.addElement( l ) ; } protected void removeListener( EventListener l ) { listeners.removeElement( l ) ; } protected Enumeration getListeners() { return listeners.elements() ; } }
\ No newline at end of file
/**
* Simple Stack Machine
*
* Written by Atze Dijkstra, atze@cs.uu.nl,
* Copyright Utrecht University.
*
*/
package nl.uu.cs.ssm ;
public interface Modification
{
public void modify() ;
}
\ No newline at end of file
/** * Simple Stack Machine * * Written by Atze Dijkstra, atze@cs.uu.nl, * Copyright Utrecht University. * */ package nl.uu.cs.ssm ; import java.util.* ; public class Registers extends AbstractMemoryCellModel implements MemoryCellModel{ public static final int PC = 0 ; public static final int SP = 1 ; public static final int MP = 2 ; //public static final int RR = 3 ; private static final int nrRegs = 8 ; private static final String[] regNames = { "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7" } ; private static final String[] regNamesAlias = { "PC", "SP", "MP", "RR" } ; //private MemoryCell cells[] ; private int cells[] ; private Memory memory ; private Messenger messenger ; protected Registers( Memory m, Messenger msgr ) { messenger = msgr ; cells = new int[ nrRegs ] ; for ( int i = 0 ; i < cells.length ; i++ ) //cells[ i ] = new MemoryCell() ; cells[ i ] = 0 ; memory = m ; reset() ; } public void reset() { for ( int i = 0 ; i < cells.length ; i++ ) //cells[ i ].setValue( 0 ) ; cells[ i ] = 0 ; } public static int getNrRegs( ) { return nrRegs ; } /* private static String[] getRegNames( ) { return regNames ; } */ public static String getRegName( int r ) { return (r < regNames.length && r >= 0) ? regNames[ r ] : ("R"+r) ; } public static String getRegOrAliasName( int r ) { return r < regNamesAlias.length ? regNamesAlias[r] : getRegName( r ) ; } public static String getRegNAliasName( int r ) { return getRegName(r) + ( r < regNamesAlias.length ? ("(" + regNamesAlias[r] + ")") : "" ) ; } public static Enumeration getRegNAliasNames( ) { Vector v = new Vector() ; Utils.addAllTo( v, Utils.asVector( regNames ) ) ; Utils.addAllTo( v, Utils.asVector( regNamesAlias ) ) ; return v.elements() ; } public static int findRegOfName( String nm ) // should be in some kinda environment { for ( int i = 0 ; i < regNames.length ; i++ ) { if ( regNames[i].equals( nm ) ) return i ; } for ( int i = 0 ; i < regNamesAlias.length ; i++ ) { if ( regNamesAlias[i].equals( nm ) ) return i ; } return -1 ; } private boolean checkWithinMemory( int r ) { boolean res ; if ( res = ( r < 0 || r >= cells.length ) ) { messenger.println ( java.text.MessageFormat.format ( "attempt to access nonexisting register {0,number,integer}" , new Object[] { new Integer(r) } ) ) ; } return ! res ; } public int getReg( int r ) { int res = 0 ; if ( checkWithinMemory( r ) ) { res = cells[ r ] ; } return res ; } public int getRegDispl( int r, int d ) { return getReg( r ) + d ; } public int getRegDisplInd( int r, int d ) { return memory.getAt( getRegDispl( r, d ) ) ; } public int getRegInd( int r ) { return getRegDisplInd( r, 0 ) ; } class UndoRegistersModification implements Modification { private int offset, value ; UndoRegistersModification( int o, int v ) { offset = o ; value = v ; } public void modify() { setReg( offset, value ) ; } } public void setReg( int r, int v ) { if ( checkWithinMemory( r ) ) { int oldv = cells[ r ] ; cells[ r ] = v ; fireCellChange( this, r, oldv, new UndoRegistersModification( r, oldv ) ) ; } } public void setRegDisplInd( int r, int d, int v ) { memory.setAt( getRegDispl( r, d ), v ) ; } public void setRegInd( int r, int v ) { setRegDisplInd( r, 0, v ) ; } public int swapReg( int r, int v ) { int oldVal = getReg( r ) ; setReg( r, v ) ; return oldVal ; } public void adjustReg( int r, int v ) { setReg( r, getReg( r ) + v ) ; } public void setPC( int v ) { setReg( PC, v ) ; } public int getPC( ) { return getReg( PC ) ; } public void adjustPC( int v ) { setPC( getPC() + v ) ; } public void setSP( int v ) { setReg( SP, v ) ; } public int getSP( ) { return getReg( SP ) ; } public void adjustSP( int v ) { setSP( getSP() + v ) ; } public void setMP( int v ) { setReg( MP, v ) ; } public int getMP( ) { return getReg( MP ) ; } public void adjustMP( int v ) { setMP( getMP() + v ) ; } public int getTOS() { return getRegInd( SP ) ; } public String toString() { return "Register PC=" + getReg( PC ) + " SP=" + getReg( SP ) + " MP=" + getReg( MP ) ; } }
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment