304 lines
7.3 KiB
Plaintext
304 lines
7.3 KiB
Plaintext
#
|
|
# Extensions to MAL:
|
|
# ------------------
|
|
#
|
|
# - absolute labels; the syntax for labels have been extended to
|
|
# allow for absolute placement of instructions, as required
|
|
# by the implementation of IJVM. To have an instruction
|
|
# placed e.g. at address 0x2A, write:
|
|
#
|
|
# imul = 0x2A:
|
|
# MAR = SP = SP - 1; rd
|
|
# ...
|
|
#
|
|
# The micro code immediately following is guaranteed to be
|
|
# placed at address 0x2A, provided it does not collide with
|
|
# other absolute labels. The label `imul' will also serve as
|
|
# a target for both conditional and unconditional gotos.
|
|
#
|
|
# - nop instruction; since the assembler ignores blank lines, a
|
|
# means to instruct the assembler to generate an empty cycle
|
|
# is needed. This is used in the implementation of pop and
|
|
# ireturn. More specifically, in the control word generated
|
|
# by nop, NEXT_ADDRESS points to the following instruction,
|
|
# the JAM field is 0, the ALU operation is unspecified, all C
|
|
# and memory bits are 0 and B is unspecified.
|
|
#
|
|
|
|
#
|
|
# Wed Apr 21 19:48:26 CEST 1999
|
|
# -----------------------------
|
|
#
|
|
# Okay, "nop" is not a clever name since it is a java bytecode.
|
|
# How about "empty"? But what about the label "goto"?
|
|
#
|
|
|
|
goto mic1_entry
|
|
|
|
main:
|
|
PC = PC + 1; fetch; goto (MBR)
|
|
|
|
nop = 0x00:
|
|
goto main
|
|
|
|
iadd = 0x60:
|
|
MAR = SP = SP - 1; rd
|
|
H = TOS
|
|
MDR = TOS = MDR + H; wr; goto main
|
|
|
|
isub = 0x64:
|
|
MAR = SP = SP - 1; rd
|
|
H = TOS
|
|
MDR = TOS = MDR - H; wr; goto main
|
|
|
|
iand = 0x7E:
|
|
MAR = SP = SP - 1; rd
|
|
H = TOS
|
|
MDR = TOS = MDR AND H; wr; goto main
|
|
|
|
ior = 0x80:
|
|
MAR = SP = SP - 1; rd
|
|
H = TOS
|
|
MDR = TOS = MDR OR H; wr; goto main
|
|
|
|
dup = 0x59:
|
|
MAR = SP = SP + 1
|
|
MDR = TOS; wr; goto main
|
|
|
|
pop = 0x57:
|
|
MAR = SP = SP - 1; rd
|
|
empty
|
|
TOS = MDR; goto main
|
|
|
|
swap = 0x5F:
|
|
MAR = SP - 1; rd
|
|
MAR = SP
|
|
H = MDR; wr
|
|
MDR = TOS
|
|
MAR = SP - 1; wr
|
|
TOS = H; goto main
|
|
|
|
bipush = 0x10:
|
|
SP = MAR = SP + 1
|
|
PC = PC + 1; fetch
|
|
MDR = TOS = MBR; wr; goto main
|
|
|
|
iload = 0x15:
|
|
H = LV
|
|
MAR = MBRU + H; rd
|
|
iload_cont:
|
|
MAR = SP = SP + 1
|
|
PC = PC + 1; fetch; wr
|
|
TOS = MDR; goto main
|
|
|
|
istore = 0x36:
|
|
H = LV
|
|
MAR = MBRU + H
|
|
istore_cont:
|
|
MDR = TOS; wr
|
|
SP = MAR = SP - 1; rd
|
|
PC = PC + 1; fetch
|
|
TOS = MDR; goto main
|
|
|
|
wide = 0xC4:
|
|
PC = PC + 1; fetch; goto (MBR OR 0x100)
|
|
|
|
wide_iload = 0x115:
|
|
PC = PC + 1; fetch
|
|
H = MBRU << 8
|
|
H = MBRU OR H
|
|
MAR = LV + H; rd; goto iload_cont
|
|
|
|
wide_istore = 0x136:
|
|
PC = PC + 1; fetch
|
|
H = MBRU << 8
|
|
H = MBRU OR H
|
|
MAR = LV + H; goto istore_cont
|
|
|
|
ldc_w = 0x13:
|
|
PC = PC + 1; fetch
|
|
H = MBRU << 8
|
|
H = MBRU OR H
|
|
MAR = H + CPP; rd; goto iload_cont
|
|
|
|
iinc = 0x84:
|
|
H = LV
|
|
MAR = MBRU + H; rd
|
|
PC = PC + 1; fetch
|
|
H = MDR
|
|
PC = PC + 1; fetch
|
|
MDR = MBR + H; wr; goto main
|
|
|
|
ijvm_goto = 0xA7:
|
|
OPC = PC - 1
|
|
goto_cont:
|
|
PC = PC + 1; fetch
|
|
H = MBR << 8
|
|
H = MBRU OR H
|
|
PC = OPC + H; fetch
|
|
goto main
|
|
|
|
iflt = 0x9B:
|
|
MAR = SP = SP - 1; rd
|
|
OPC = TOS
|
|
TOS = MDR
|
|
N = OPC; if (N) goto T; else goto F
|
|
|
|
ifeq = 0x99:
|
|
MAR = SP = SP - 1; rd
|
|
OPC = TOS
|
|
TOS = MDR
|
|
Z = OPC; if (Z) goto T; else goto F
|
|
|
|
if_icmpeq = 0x9F:
|
|
MAR = SP = SP - 1; rd
|
|
MAR = SP = SP - 1
|
|
H = MDR; rd
|
|
OPC = TOS
|
|
TOS = MDR
|
|
Z = OPC - H; if (Z) goto T; else goto F
|
|
|
|
T:
|
|
OPC = PC - 1; fetch; goto goto_cont
|
|
|
|
F:
|
|
PC = PC + 1
|
|
PC = PC + 1; fetch
|
|
goto main
|
|
|
|
invokevirtual = 0xB6:
|
|
PC = PC + 1; fetch
|
|
H = MBRU << 8
|
|
H = MBRU OR H
|
|
mic1_entry:
|
|
MAR = CPP + H; rd
|
|
OPC = PC + 1
|
|
PC = MDR; fetch
|
|
PC = PC + 1; fetch
|
|
H = MBRU << 8
|
|
H = MBRU OR H
|
|
PC = PC + 1; fetch
|
|
TOS = SP - H
|
|
TOS = MAR = TOS + 1
|
|
PC = PC + 1; fetch
|
|
H = MBRU << 8
|
|
H = MBRU OR H
|
|
MDR = SP + H + 1; wr
|
|
MAR = SP = MDR
|
|
MDR = OPC; wr
|
|
MAR = SP = SP + 1
|
|
MDR = LV; wr
|
|
PC = PC + 1; fetch
|
|
LV = TOS; goto main
|
|
|
|
ireturn = 0xAC:
|
|
MAR = SP = LV; rd
|
|
empty
|
|
LV = MAR = MDR; rd
|
|
MAR = LV + 1
|
|
PC = MDR; rd; fetch
|
|
MAR = SP
|
|
LV = MDR
|
|
MDR = TOS; wr
|
|
Z = PC - 1; if (Z) goto mic1_exit; else goto main
|
|
|
|
mic1_exit:
|
|
halt
|
|
|
|
ishl = 0x78:
|
|
# It is possible to use the value of
|
|
# the MBRU register to create the mask.
|
|
H = MBRU >> 1 # MBRU = 1111000, H = 111100
|
|
H = H >> 1 # H = 11110
|
|
H = H + 1 # H = 11111
|
|
# Read second-to-top word from stack and
|
|
# set SP to point to this position.
|
|
MAR = SP = SP - 1; rd
|
|
TOS = TOS AND H # Apply bit mask to the top word from
|
|
# the stack which signifies the number
|
|
# of shifts to perform.
|
|
H = OPC = MDR # Load the value to be shifted.
|
|
|
|
ishl_loop: # If the counter (TOS) is 0, end loop.
|
|
Z = TOS; if (Z) goto ishl_end; else goto ishl_shift
|
|
ishl_shift:
|
|
H = OPC = OPC + H # Perform an arithmetic left-shift by
|
|
# multiplying H and OPC. H and OPC is
|
|
# loaded with the result to prepare for
|
|
# possible further multiplications.
|
|
|
|
TOS = TOS - 1 # Decrease the counter by one.
|
|
goto ishl_loop
|
|
ishl_end: # Customary push of result to the TOS
|
|
# register and the stack in memory.
|
|
# MAR = SP is not necessary, due to
|
|
# MAR already being set to SP earlier.
|
|
MDR = TOS = H; wr; goto main
|
|
|
|
ishr = 0x7A:
|
|
# It is possible to use the value of
|
|
# the MBRU register to create the mask.
|
|
H = MBRU >> 1 # MBRU = 1111010, H = 111101
|
|
H = H >> 1 # H = 11110
|
|
H = H + 1 # H = 11111
|
|
# Read second-to-top word from stack and
|
|
# set SP to point to this position.
|
|
MAR = SP = SP - 1; rd
|
|
TOS = TOS AND H # Apply bit mask to the top word from
|
|
# the stack.
|
|
|
|
H = MDR # Load the value to be shifted into H.
|
|
|
|
ishr_loop: # If the counter (TOS) is 0, end loop.
|
|
Z = TOS; if (Z) goto ishr_end; else goto ishr_shift
|
|
ishr_shift: # The actual shifting takes place here
|
|
H = H >> 1 # The value is shifted arithmetically
|
|
# right by 1-bit using the ALU.
|
|
TOS = TOS - 1 # The counter is decreased.
|
|
goto ishr_loop
|
|
ishr_end: # Customary push of result to the TOS
|
|
# register and the stack in memory.
|
|
MDR = TOS = H; wr; goto main
|
|
|
|
iushr = 0x7C:
|
|
H = MBRU >> 1 # MBRU = 1111100, H = 111110
|
|
# Set H to the value of OPC to prepare
|
|
# for the creation of a new bit-mask
|
|
# later in the instruction.
|
|
OPC = H = H >> 1 # H = 11111
|
|
# Read second-to-top word from stack and
|
|
# set SP to point to this position.
|
|
MAR = SP = SP - 1; rd
|
|
TOS = TOS AND H # Apply bit mask to the top word from
|
|
# the stack.
|
|
# Create new bit mask from the previous
|
|
# bit mask.
|
|
H = OPC = OPC + 1 # H = 100000
|
|
H = OPC = H + OPC # H, OPC = 01000000
|
|
# The value of OPC after the following
|
|
# instructions is listed in the
|
|
# comments of each line:
|
|
OPC = H + OPC # 00000000 00000000 00000000 10000000
|
|
OPC = OPC << 8 # 00000000 00000000 10000000 00000000
|
|
OPC = OPC << 8 # 00000000 10000000 00000000 00000000
|
|
OPC = OPC << 8 # 10000000 00000000 00000000 00000000
|
|
OPC = inv(OPC) # 01111111 11111111 11111111 11111111
|
|
# If anything is AND with OPC, it will
|
|
# remove the most significant bit of
|
|
# that value with OPC.
|
|
|
|
H = MDR # Load H with the value to be shifted
|
|
iushr_loop:
|
|
Z = TOS; if (Z) goto iushr_end; else goto iushr_shift
|
|
iushr_shift:
|
|
H = H >> 1 # Do a 1-bit arithmetic right-shift
|
|
H = H AND OPC # Use the bit-mask to remove the most
|
|
# significant bit, effectively making
|
|
# the arithmetic right-shift into a
|
|
# logical right-shift.
|
|
TOS = TOS - 1 # Decrease the counter by one.
|
|
goto iushr_loop
|
|
iushr_end: # Customary push of result to the TOS
|
|
# register and the stack in memory.
|
|
MDR = TOS = H; wr; goto main
|