parent
9f1681bb23
commit
9786fbbc69
@ -0,0 +1,19 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Launch Current File",
|
||||
"request": "launch",
|
||||
"classPaths": ["chocopy-ref.jar:target/assignment.jar"],
|
||||
"mainClass": "chocopy.ChocoPy",
|
||||
"args": [ "--pass=rrs", "--test","--dir", "src/test/data/pa3/sample/list_set_element_oob_1.py"],
|
||||
"sourcePaths": []
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"java.configuration.updateBuildConfiguration": "interactive"
|
||||
}
|
@ -0,0 +1,795 @@
|
||||
.equiv @sbrk, 9
|
||||
.equiv @print_string, 4
|
||||
.equiv @print_char, 11
|
||||
.equiv @print_int, 1
|
||||
.equiv @exit2, 17
|
||||
.equiv @read_string, 8
|
||||
.equiv @fill_line_buffer, 18
|
||||
.equiv @.__obj_size__, 4
|
||||
.equiv @.__len__, 12
|
||||
.equiv @.__int__, 12
|
||||
.equiv @.__bool__, 12
|
||||
.equiv @.__str__, 16
|
||||
.equiv @.__elts__, 16
|
||||
.equiv @error_div_zero, 2
|
||||
.equiv @error_arg, 1
|
||||
.equiv @error_oob, 3
|
||||
.equiv @error_none, 4
|
||||
.equiv @error_oom, 5
|
||||
.equiv @error_nyi, 6
|
||||
.equiv @listHeaderWords, 4
|
||||
.equiv @strHeaderWords, 4
|
||||
.equiv @bool.True, const_1
|
||||
.equiv @bool.False, const_0
|
||||
|
||||
.data
|
||||
|
||||
.globl $object$prototype
|
||||
$object$prototype:
|
||||
.word 0 # Type tag for class: object
|
||||
.word 3 # Object size
|
||||
.word $object$dispatchTable # Pointer to dispatch table
|
||||
.align 2
|
||||
|
||||
.globl $int$prototype
|
||||
$int$prototype:
|
||||
.word 1 # Type tag for class: int
|
||||
.word 4 # Object size
|
||||
.word $int$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __int__
|
||||
.align 2
|
||||
|
||||
.globl $bool$prototype
|
||||
$bool$prototype:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl $str$prototype
|
||||
$str$prototype:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 5 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.word 0 # Initial value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl $.list$prototype
|
||||
$.list$prototype:
|
||||
.word -1 # Type tag for class: .list
|
||||
.word 4 # Object size
|
||||
.word 0 # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.align 2
|
||||
|
||||
.globl $object$dispatchTable
|
||||
$object$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: object.__init__
|
||||
|
||||
.globl $int$dispatchTable
|
||||
$int$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: int.__init__
|
||||
|
||||
.globl $bool$dispatchTable
|
||||
$bool$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: bool.__init__
|
||||
|
||||
.globl $str$dispatchTable
|
||||
$str$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: str.__init__
|
||||
|
||||
.globl $n
|
||||
$n:
|
||||
.word 42 # Initial value of global var: n
|
||||
|
||||
.globl $i
|
||||
$i:
|
||||
.word 0 # Initial value of global var: i
|
||||
|
||||
.text
|
||||
|
||||
.globl main
|
||||
main:
|
||||
lui a0, 8192 # Initialize heap size (in multiples of 4KB)
|
||||
add s11, s11, a0 # Save heap size
|
||||
jal heap.init # Call heap.init routine
|
||||
mv gp, a0 # Initialize heap pointer
|
||||
mv s10, gp # Set beginning of heap
|
||||
add s11, s10, s11 # Set end of heap (= start of heap + heap size)
|
||||
mv ra, zero # No normal return from main program.
|
||||
mv fp, zero # No preceding frame.
|
||||
addi sp, sp, -@..main.size # Reserve space for stack frame.
|
||||
sw ra, @..main.size-4(sp) # return address
|
||||
sw fp, @..main.size-8(sp) # control link
|
||||
addi fp, sp, @..main.size # New fp is at old SP.
|
||||
jal initchars # Initialize one-character strings.
|
||||
j label_2 # Jump to loop test
|
||||
label_1: # Top of while loop
|
||||
li a0, 2 # Load integer literal 2
|
||||
sw a0, -28(fp) # Push argument 1 from last.
|
||||
lw a0, $i # Load global: i
|
||||
sw a0, -36(fp) # Push on stack slot 9
|
||||
li a0, 31 # Load integer literal 31
|
||||
lw t0, -36(fp) # Pop stack slot 9
|
||||
bnez a0, label_3 # Ensure non-zero divisor
|
||||
j error.Div # Go to error handler
|
||||
label_3: # Divisor is non-zero
|
||||
rem t2, t0, a0 # Operator rem
|
||||
beqz t2, label_4 # If no remainder, no adjustment
|
||||
xor t3, t2, a0 # Check for differing signs.
|
||||
bgez t3, label_4 # Don't adjust if signs equal.
|
||||
add a0, t2, a0 # Adjust
|
||||
j label_5
|
||||
label_4: # Store result
|
||||
mv a0, t2
|
||||
label_5: # End of %
|
||||
sw a0, -32(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -32 # Set SP to last argument.
|
||||
jal $exp # Invoke function: exp
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
jal makeint # Box integer
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
lw a0, $i # Load global: i
|
||||
sw a0, -12(fp) # Push on stack slot 3
|
||||
li a0, 1 # Load integer literal 1
|
||||
lw t0, -12(fp) # Pop stack slot 3
|
||||
add a0, t0, a0 # Operator +
|
||||
sw a0, $i, t0 # Assign global: i (using tmp register)
|
||||
label_2: # Test loop condition
|
||||
lw a0, $i # Load global: i
|
||||
sw a0, -12(fp) # Push on stack slot 3
|
||||
lw a0, $n # Load global: n
|
||||
lw t0, -12(fp) # Pop stack slot 3
|
||||
bge a0, t0, label_1 # Branch on <=
|
||||
.equiv @..main.size, 48
|
||||
label_0: # End of program
|
||||
li a0, 10 # Code for ecall: exit
|
||||
ecall
|
||||
|
||||
.globl $object.__init__
|
||||
$object.__init__:
|
||||
# Init method for type object.
|
||||
mv a0, zero # `None` constant
|
||||
jr ra # Return
|
||||
|
||||
.globl $print
|
||||
$print:
|
||||
# Function print
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, print_6 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 1 # Load type tag of `int`
|
||||
beq t0, t1, print_7 # Go to print(int)
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, print_8 # Go to print(str)
|
||||
li t1, 2 # Load type tag of `bool`
|
||||
beq t0, t1, print_9 # Go to print(bool)
|
||||
print_6: # Invalid argument
|
||||
li a0, 1 # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
# Printing bools
|
||||
print_9: # Print bool object in A0
|
||||
lw a0, @.__bool__(a0) # Load attribute __bool__
|
||||
beq a0, zero, print_10 # Go to: print(False)
|
||||
la a0, const_3 # String representation: True
|
||||
j print_8 # Go to: print(str)
|
||||
print_10: # Print False object in A0
|
||||
la a0, const_4 # String representation: False
|
||||
j print_8 # Go to: print(str)
|
||||
|
||||
# Printing strs.
|
||||
print_8: # Print str object in A0
|
||||
addi a1, a0, @.__str__ # Load address of attribute __str__
|
||||
j print_11 # Print the null-terminated string is now in A1
|
||||
mv a0, zero # Load None
|
||||
j print_5 # Go to return
|
||||
print_11: # Print null-terminated string in A1
|
||||
li a0, @print_string # Code for ecall: print_string
|
||||
ecall # Print string
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
j print_5 # Go to return
|
||||
|
||||
# Printing ints.
|
||||
print_7: # Print int object in A0
|
||||
lw a1, @.__int__(a0) # Load attribute __int__
|
||||
li a0, @print_int # Code for ecall: print_int
|
||||
ecall # Print integer
|
||||
li a1, 10 # Load newline character
|
||||
li a0, 11 # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
|
||||
print_5: # End of function
|
||||
mv a0, zero # Load None
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $len
|
||||
$len:
|
||||
# Function len
|
||||
# We do not save/restore fp/ra for this function
|
||||
# because we know that it does not use the stack or does not
|
||||
# call other functions.
|
||||
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, len_12 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, len_13 # Go to len(str)
|
||||
li t1, -1 # Load type tag for list objects
|
||||
beq t0, t1, len_13 # Go to len(list)
|
||||
len_12: # Invalid argument
|
||||
li a0, @error_arg # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
len_13: # Get length of string
|
||||
lw a0, @.__len__(a0) # Load attribute: __len__
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $input
|
||||
$input:
|
||||
# Function input
|
||||
addi sp, sp, -16 # Reserve stack
|
||||
sw ra, 12(sp) # Save registers
|
||||
sw fp, 8(sp)
|
||||
sw s1, 4(sp)
|
||||
addi fp, sp, 16 # Set fp
|
||||
|
||||
li a0, @fill_line_buffer # Fill the internal line buffer.
|
||||
ecall
|
||||
bgez a0, input_nonempty # More input found
|
||||
la a0, $str$prototype # EOF: Return empty string.
|
||||
j input_done
|
||||
|
||||
input_nonempty:
|
||||
mv s1, a0
|
||||
addi t0, s1, 5 # Compute bytes for string (+NL+NUL),
|
||||
addi t0, t0, @.__str__ # Including header.
|
||||
srli a1, t0, 2 # Convert to words.
|
||||
la a0, $str$prototype # Load address of string prototype.
|
||||
jal ra, alloc2 # Allocate string.
|
||||
sw s1, @.__len__(a0) # Store string length.
|
||||
mv a2, s1 # Pass length.
|
||||
mv s1, a0 # Save string object address.
|
||||
addi a1, a0, @.__str__ # Pass address of string data.
|
||||
li a0, @read_string # ecall to read from internal buffer.
|
||||
ecall
|
||||
addi a0, a0, 1 # Actual length (including NL).
|
||||
sw a0, @.__len__(s1) # Store actual length.
|
||||
add t0, a0, s1
|
||||
li t1, 10 # Store newline and null byte
|
||||
sb t1, @.__str__-1(t0)
|
||||
sb zero, @.__str__(t0) # Store null byte at end.
|
||||
mv a0, s1 # Return string object.
|
||||
|
||||
input_done:
|
||||
lw s1, -12(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 16
|
||||
jr ra
|
||||
|
||||
.globl $exp.f.geta
|
||||
$exp.f.geta:
|
||||
addi sp, sp, -@exp.f.geta.size # Reserve space for stack frame.
|
||||
sw ra, @exp.f.geta.size-4(sp) # return address
|
||||
sw fp, @exp.f.geta.size-8(sp) # control link
|
||||
addi fp, sp, @exp.f.geta.size # New fp is at old SP.
|
||||
lw t0, 0(fp) # Load static link from exp.f.geta to exp.f
|
||||
lw t0, 4(t0) # Load static link from exp.f to exp
|
||||
lw a0, -12(t0) # Load var: exp.a
|
||||
j label_7 # Go to return
|
||||
mv a0, zero # Load None
|
||||
j label_7 # Jump to function epilogue
|
||||
label_7: # Epilogue
|
||||
.equiv @exp.f.geta.size, 16
|
||||
lw ra, -4(fp) # Get return address
|
||||
lw fp, -8(fp) # Use control link to restore caller's fp
|
||||
addi sp, sp, @exp.f.geta.size # Restore stack pointer
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $exp.f
|
||||
$exp.f:
|
||||
addi sp, sp, -@exp.f.size # Reserve space for stack frame.
|
||||
sw ra, @exp.f.size-4(sp) # return address
|
||||
sw fp, @exp.f.size-8(sp) # control link
|
||||
addi fp, sp, @exp.f.size # New fp is at old SP.
|
||||
lw a0, 0(fp) # Load var: exp.f.i
|
||||
sw a0, -12(fp) # Push on stack slot 3
|
||||
li a0, 0 # Load integer literal 0
|
||||
lw t0, -12(fp) # Pop stack slot 3
|
||||
blt a0, t0, label_11 # Branch on not <=
|
||||
mv t0, fp # Get static link to exp.f
|
||||
sw t0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $exp.f.geta # Invoke function: exp.f.geta
|
||||
addi sp, fp, -@exp.f.size # Set SP to stack frame top.
|
||||
j label_9 # Go to return
|
||||
j label_10 # Then body complete; jump to end-if
|
||||
label_11: # Else body
|
||||
lw t0, 4(fp) # Load static link from exp.f to exp
|
||||
lw a0, -12(t0) # Load var: exp.a
|
||||
sw a0, -12(fp) # Push on stack slot 3
|
||||
lw t0, 4(fp) # Load static link from exp.f to exp
|
||||
lw a0, 4(t0) # Load var: exp.x
|
||||
lw t0, -12(fp) # Pop stack slot 3
|
||||
mul a0, t0, a0 # Operator *
|
||||
lw t0, 4(fp) # Load static link from exp.f to exp
|
||||
sw a0, -12(t0) # Assign var: exp.a
|
||||
mv t0, fp # Get static link to exp.f
|
||||
lw t0, 4(t0) # Get static link to exp
|
||||
sw t0, -12(fp) # Push argument 1 from last.
|
||||
lw a0, 0(fp) # Load var: exp.f.i
|
||||
sw a0, -20(fp) # Push on stack slot 5
|
||||
li a0, 1 # Load integer literal 1
|
||||
lw t0, -20(fp) # Pop stack slot 5
|
||||
sub a0, t0, a0 # Operator -
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $exp.f # Invoke function: exp.f
|
||||
addi sp, fp, -@exp.f.size # Set SP to stack frame top.
|
||||
j label_9 # Go to return
|
||||
label_10: # End of if-else statement
|
||||
mv a0, zero # Load None
|
||||
j label_9 # Jump to function epilogue
|
||||
label_9: # Epilogue
|
||||
.equiv @exp.f.size, 32
|
||||
lw ra, -4(fp) # Get return address
|
||||
lw fp, -8(fp) # Use control link to restore caller's fp
|
||||
addi sp, sp, @exp.f.size # Restore stack pointer
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $exp
|
||||
$exp:
|
||||
addi sp, sp, -@exp.size # Reserve space for stack frame.
|
||||
sw ra, @exp.size-4(sp) # return address
|
||||
sw fp, @exp.size-8(sp) # control link
|
||||
addi fp, sp, @exp.size # New fp is at old SP.
|
||||
li a0, 0 # Load integer literal 0
|
||||
sw a0, -12(fp) # local variable a
|
||||
li a0, 1 # Load integer literal 1
|
||||
sw a0, -12(fp) # Assign var: exp.a
|
||||
mv t0, fp # Get static link to exp
|
||||
sw t0, -28(fp) # Push argument 1 from last.
|
||||
lw a0, 0(fp) # Load var: exp.y
|
||||
sw a0, -32(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -32 # Set SP to last argument.
|
||||
jal $exp.f # Invoke function: exp.f
|
||||
addi sp, fp, -@exp.size # Set SP to stack frame top.
|
||||
j label_13 # Go to return
|
||||
mv a0, zero # Load None
|
||||
j label_13 # Jump to function epilogue
|
||||
label_13: # Epilogue
|
||||
.equiv @exp.size, 32
|
||||
lw ra, -4(fp) # Get return address
|
||||
lw fp, -8(fp) # Use control link to restore caller's fp
|
||||
addi sp, sp, @exp.size # Restore stack pointer
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl alloc
|
||||
alloc:
|
||||
# Runtime support function alloc.
|
||||
# Prototype address is in a0.
|
||||
lw a1, 4(a0) # Get size of object in words
|
||||
j alloc2 # Allocate object with exact size
|
||||
|
||||
.globl alloc2
|
||||
alloc2:
|
||||
# Runtime support function alloc2 (realloc).
|
||||
# Prototype address is in a0.
|
||||
# Number of words to allocate is in a1.
|
||||
li a2, 4 # Word size in bytes
|
||||
mul a2, a1, a2 # Calculate number of bytes to allocate
|
||||
add a2, gp, a2 # Estimate where GP will move
|
||||
bgeu a2, s11, alloc2_15 # Go to OOM handler if too large
|
||||
lw t0, @.__obj_size__(a0) # Get size of object in words
|
||||
mv t2, a0 # Initialize src ptr
|
||||
mv t3, gp # Initialize dest ptr
|
||||
alloc2_16: # Copy-loop header
|
||||
lw t1, 0(t2) # Load next word from src
|
||||
sw t1, 0(t3) # Store next word to dest
|
||||
addi t2, t2, 4 # Increment src
|
||||
addi t3, t3, 4 # Increment dest
|
||||
addi t0, t0, -1 # Decrement counter
|
||||
bne t0, zero, alloc2_16 # Loop if more words left to copy
|
||||
mv a0, gp # Save new object's address to return
|
||||
sw a1, @.__obj_size__(a0) # Set size of new object in words
|
||||
# (same as requested size)
|
||||
mv gp, a2 # Set next free slot in the heap
|
||||
jr ra # Return to caller
|
||||
alloc2_15: # OOM handler
|
||||
li a0, @error_oom # Exit code for: Out of memory
|
||||
la a1, const_5 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl abort
|
||||
abort:
|
||||
# Runtime support function abort (does not return).
|
||||
mv t0, a0 # Save exit code in temp
|
||||
li a0, @print_string # Code for print_string ecall
|
||||
ecall # Print error message in a1
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for print_char ecall
|
||||
ecall # Print newline
|
||||
mv a1, t0 # Move exit code to a1
|
||||
li a0, @exit2 # Code for exit2 ecall
|
||||
ecall # Exit with code
|
||||
abort_17: # Infinite loop
|
||||
j abort_17 # Prevent fallthrough
|
||||
|
||||
.globl heap.init
|
||||
heap.init:
|
||||
# Runtime support function heap.init.
|
||||
mv a1, a0 # Move requested size to A1
|
||||
li a0, @sbrk # Code for ecall: sbrk
|
||||
ecall # Request A1 bytes
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl concat
|
||||
concat:
|
||||
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw fp, 24(sp)
|
||||
addi fp, sp, 32
|
||||
sw s1, -12(fp)
|
||||
sw s2, -16(fp)
|
||||
sw s3, -20(fp)
|
||||
sw s4, -24(fp)
|
||||
sw s5, -28(fp)
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
beqz t0, concat_none
|
||||
beqz t1, concat_none
|
||||
lw t0, @.__len__(t0)
|
||||
lw t1, @.__len__(t1)
|
||||
add s5, t0, t1
|
||||
addi a1, s5, @listHeaderWords
|
||||
la a0, $.list$prototype
|
||||
jal alloc2
|
||||
sw s5, @.__len__(a0)
|
||||
mv s5, a0
|
||||
addi s3, s5, @.__elts__
|
||||
lw s1, 4(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 12(fp)
|
||||
concat_1:
|
||||
beqz s2, concat_2
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_1
|
||||
concat_2:
|
||||
lw s1, 0(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 8(fp)
|
||||
concat_3:
|
||||
beqz s2, concat_4
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_3
|
||||
concat_4:
|
||||
mv a0, s5
|
||||
lw s1, -12(fp)
|
||||
lw s2, -16(fp)
|
||||
lw s3, -20(fp)
|
||||
lw s4, -24(fp)
|
||||
lw s5, -28(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 32
|
||||
jr ra
|
||||
concat_none:
|
||||
j error.None
|
||||
|
||||
|
||||
.globl conslist
|
||||
conslist:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 0(fp)
|
||||
la a0, $.list$prototype
|
||||
beqz a1, conslist_done
|
||||
addi a1, a1, @listHeaderWords
|
||||
jal alloc2
|
||||
lw t0, 0(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
slli t1, t0, 2
|
||||
add t1, t1, fp
|
||||
addi t2, a0, @.__elts__
|
||||
conslist_1:
|
||||
lw t3, 0(t1)
|
||||
sw t3, 0(t2)
|
||||
addi t1, t1, -4
|
||||
addi t2, t2, 4
|
||||
addi t0, t0, -1
|
||||
bnez t0, conslist_1
|
||||
conslist_done:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strcat
|
||||
strcat:
|
||||
|
||||
addi sp, sp, -12
|
||||
sw ra, 8(sp)
|
||||
sw fp, 4(sp)
|
||||
addi fp, sp, 12
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
lw t0, @.__len__(t0)
|
||||
beqz t0, strcat_4
|
||||
lw t1, @.__len__(t1)
|
||||
beqz t1, strcat_5
|
||||
add t1, t0, t1
|
||||
sw t1, -12(fp)
|
||||
addi t1, t1, 4
|
||||
srli t1, t1, 2
|
||||
addi a1, t1, @listHeaderWords
|
||||
la a0, $str$prototype
|
||||
jal alloc2
|
||||
lw t0, -12(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
addi t2, a0, 16
|
||||
lw t0, 4(fp)
|
||||
lw t1, @.__len__(t0)
|
||||
addi t0, t0, @.__str__
|
||||
strcat_1:
|
||||
beqz t1, strcat_2
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_1
|
||||
strcat_2:
|
||||
lw t0, 0(fp)
|
||||
lw t1, 12(t0)
|
||||
addi t0, t0, 16
|
||||
strcat_3:
|
||||
beqz t1, strcat_6
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_3
|
||||
strcat_4:
|
||||
lw a0, 0(fp)
|
||||
j strcat_7
|
||||
strcat_5:
|
||||
lw a0, 4(fp)
|
||||
j strcat_7
|
||||
strcat_6:
|
||||
sb zero, 0(t2)
|
||||
strcat_7:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 12
|
||||
jr ra
|
||||
|
||||
|
||||
.globl streql
|
||||
streql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, streql_no
|
||||
streql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, streql_no
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, streql_1
|
||||
li a0, 1
|
||||
j streql_end
|
||||
streql_no:
|
||||
xor a0, a0, a0
|
||||
streql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strneql
|
||||
strneql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, strneql_yes
|
||||
strneql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, strneql_yes
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, strneql_1
|
||||
xor a0, a0, a0
|
||||
j strneql_end
|
||||
strneql_yes:
|
||||
li a0, 1
|
||||
strneql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makeint
|
||||
makeint:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw a0, 0(sp)
|
||||
la a0, $int$prototype
|
||||
jal ra, alloc
|
||||
lw t0, 0(sp)
|
||||
sw t0, @.__int__(a0)
|
||||
lw ra, 4(sp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makebool
|
||||
makebool:
|
||||
|
||||
slli a0, a0, 4
|
||||
la t0, @bool.False
|
||||
add a0, a0, t0
|
||||
jr ra
|
||||
|
||||
|
||||
.globl noconv
|
||||
noconv:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl initchars
|
||||
initchars:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl error.None
|
||||
error.None:
|
||||
li a0, 4 # Exit code for: Operation on None
|
||||
la a1, const_6 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.Div
|
||||
error.Div:
|
||||
li a0, 2 # Exit code for: Division by zero
|
||||
la a1, const_7 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.OOB
|
||||
error.OOB:
|
||||
li a0, 3 # Exit code for: Index out of bounds
|
||||
la a1, const_8 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.data
|
||||
|
||||
.globl const_0
|
||||
const_0:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_1
|
||||
const_1:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 1 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_7
|
||||
const_7:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Division by zero" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_5
|
||||
const_5:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 8 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 13 # Constant value of attribute: __len__
|
||||
.string "Out of memory" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_8
|
||||
const_8:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 19 # Constant value of attribute: __len__
|
||||
.string "Index out of bounds" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_3
|
||||
const_3:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 4 # Constant value of attribute: __len__
|
||||
.string "True" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_6
|
||||
const_6:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 17 # Constant value of attribute: __len__
|
||||
.string "Operation on None" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_2
|
||||
const_2:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Invalid argument" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_4
|
||||
const_4:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "False" # Constant value of attribute: __str__
|
||||
.align 2
|
@ -0,0 +1,789 @@
|
||||
.equiv @sbrk, 9
|
||||
.equiv @print_string, 4
|
||||
.equiv @print_char, 11
|
||||
.equiv @print_int, 1
|
||||
.equiv @exit2, 17
|
||||
.equiv @read_string, 8
|
||||
.equiv @fill_line_buffer, 18
|
||||
.equiv @.__obj_size__, 4
|
||||
.equiv @.__len__, 12
|
||||
.equiv @.__int__, 12
|
||||
.equiv @.__bool__, 12
|
||||
.equiv @.__str__, 16
|
||||
.equiv @.__elts__, 16
|
||||
.equiv @error_div_zero, 2
|
||||
.equiv @error_arg, 1
|
||||
.equiv @error_oob, 3
|
||||
.equiv @error_none, 4
|
||||
.equiv @error_oom, 5
|
||||
.equiv @error_nyi, 6
|
||||
.equiv @listHeaderWords, 4
|
||||
.equiv @strHeaderWords, 4
|
||||
.equiv @bool.True, const_1
|
||||
.equiv @bool.False, const_0
|
||||
|
||||
.data
|
||||
|
||||
.globl $object$prototype
|
||||
$object$prototype:
|
||||
.word 0 # Type tag for class: object
|
||||
.word 3 # Object size
|
||||
.word $object$dispatchTable # Pointer to dispatch table
|
||||
.align 2
|
||||
|
||||
.globl $int$prototype
|
||||
$int$prototype:
|
||||
.word 1 # Type tag for class: int
|
||||
.word 4 # Object size
|
||||
.word $int$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __int__
|
||||
.align 2
|
||||
|
||||
.globl $bool$prototype
|
||||
$bool$prototype:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl $str$prototype
|
||||
$str$prototype:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 5 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.word 0 # Initial value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl $.list$prototype
|
||||
$.list$prototype:
|
||||
.word -1 # Type tag for class: .list
|
||||
.word 4 # Object size
|
||||
.word 0 # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.align 2
|
||||
|
||||
.globl $object$dispatchTable
|
||||
$object$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: object.__init__
|
||||
|
||||
.globl $int$dispatchTable
|
||||
$int$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: int.__init__
|
||||
|
||||
.globl $bool$dispatchTable
|
||||
$bool$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: bool.__init__
|
||||
|
||||
.globl $str$dispatchTable
|
||||
$str$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: str.__init__
|
||||
|
||||
.globl $n
|
||||
$n:
|
||||
.word 15 # Initial value of global var: n
|
||||
|
||||
.globl $i
|
||||
$i:
|
||||
.word 1 # Initial value of global var: i
|
||||
|
||||
.text
|
||||
|
||||
.globl main
|
||||
main:
|
||||
lui a0, 8192 # Initialize heap size (in multiples of 4KB)
|
||||
add s11, s11, a0 # Save heap size
|
||||
jal heap.init # Call heap.init routine
|
||||
mv gp, a0 # Initialize heap pointer
|
||||
mv s10, gp # Set beginning of heap
|
||||
add s11, s10, s11 # Set end of heap (= start of heap + heap size)
|
||||
mv ra, zero # No normal return from main program.
|
||||
mv fp, zero # No preceding frame.
|
||||
addi sp, sp, -@..main.size # Reserve space for stack frame.
|
||||
sw ra, @..main.size-4(sp) # return address
|
||||
sw fp, @..main.size-8(sp) # control link
|
||||
addi fp, sp, @..main.size # New fp is at old SP.
|
||||
jal initchars # Initialize one-character strings.
|
||||
j label_2 # Jump to loop test
|
||||
label_1: # Top of while loop
|
||||
lw a0, $i # Load global: i
|
||||
sw a0, -32(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -32 # Set SP to last argument.
|
||||
jal $get_prime # Invoke function: get_prime
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
jal makeint # Box integer
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
lw a0, $i # Load global: i
|
||||
sw a0, -12(fp) # Push on stack slot 3
|
||||
li a0, 1 # Load integer literal 1
|
||||
lw t0, -12(fp) # Pop stack slot 3
|
||||
add a0, t0, a0 # Operator +
|
||||
sw a0, $i, t0 # Assign global: i (using tmp register)
|
||||
label_2: # Test loop condition
|
||||
lw a0, $i # Load global: i
|
||||
sw a0, -12(fp) # Push on stack slot 3
|
||||
lw a0, $n # Load global: n
|
||||
lw t0, -12(fp) # Pop stack slot 3
|
||||
bge a0, t0, label_1 # Branch on <=
|
||||
.equiv @..main.size, 32
|
||||
label_0: # End of program
|
||||
li a0, 10 # Code for ecall: exit
|
||||
ecall
|
||||
|
||||
.globl $object.__init__
|
||||
$object.__init__:
|
||||
# Init method for type object.
|
||||
mv a0, zero # `None` constant
|
||||
jr ra # Return
|
||||
|
||||
.globl $print
|
||||
$print:
|
||||
# Function print
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, print_6 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 1 # Load type tag of `int`
|
||||
beq t0, t1, print_7 # Go to print(int)
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, print_8 # Go to print(str)
|
||||
li t1, 2 # Load type tag of `bool`
|
||||
beq t0, t1, print_9 # Go to print(bool)
|
||||
print_6: # Invalid argument
|
||||
li a0, 1 # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
# Printing bools
|
||||
print_9: # Print bool object in A0
|
||||
lw a0, @.__bool__(a0) # Load attribute __bool__
|
||||
beq a0, zero, print_10 # Go to: print(False)
|
||||
la a0, const_3 # String representation: True
|
||||
j print_8 # Go to: print(str)
|
||||
print_10: # Print False object in A0
|
||||
la a0, const_4 # String representation: False
|
||||
j print_8 # Go to: print(str)
|
||||
|
||||
# Printing strs.
|
||||
print_8: # Print str object in A0
|
||||
addi a1, a0, @.__str__ # Load address of attribute __str__
|
||||
j print_11 # Print the null-terminated string is now in A1
|
||||
mv a0, zero # Load None
|
||||
j print_5 # Go to return
|
||||
print_11: # Print null-terminated string in A1
|
||||
li a0, @print_string # Code for ecall: print_string
|
||||
ecall # Print string
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
j print_5 # Go to return
|
||||
|
||||
# Printing ints.
|
||||
print_7: # Print int object in A0
|
||||
lw a1, @.__int__(a0) # Load attribute __int__
|
||||
li a0, @print_int # Code for ecall: print_int
|
||||
ecall # Print integer
|
||||
li a1, 10 # Load newline character
|
||||
li a0, 11 # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
|
||||
print_5: # End of function
|
||||
mv a0, zero # Load None
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $len
|
||||
$len:
|
||||
# Function len
|
||||
# We do not save/restore fp/ra for this function
|
||||
# because we know that it does not use the stack or does not
|
||||
# call other functions.
|
||||
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, len_12 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, len_13 # Go to len(str)
|
||||
li t1, -1 # Load type tag for list objects
|
||||
beq t0, t1, len_13 # Go to len(list)
|
||||
len_12: # Invalid argument
|
||||
li a0, @error_arg # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
len_13: # Get length of string
|
||||
lw a0, @.__len__(a0) # Load attribute: __len__
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $input
|
||||
$input:
|
||||
# Function input
|
||||
addi sp, sp, -16 # Reserve stack
|
||||
sw ra, 12(sp) # Save registers
|
||||
sw fp, 8(sp)
|
||||
sw s1, 4(sp)
|
||||
addi fp, sp, 16 # Set fp
|
||||
|
||||
li a0, @fill_line_buffer # Fill the internal line buffer.
|
||||
ecall
|
||||
bgez a0, input_nonempty # More input found
|
||||
la a0, $str$prototype # EOF: Return empty string.
|
||||
j input_done
|
||||
|
||||
input_nonempty:
|
||||
mv s1, a0
|
||||
addi t0, s1, 5 # Compute bytes for string (+NL+NUL),
|
||||
addi t0, t0, @.__str__ # Including header.
|
||||
srli a1, t0, 2 # Convert to words.
|
||||
la a0, $str$prototype # Load address of string prototype.
|
||||
jal ra, alloc2 # Allocate string.
|
||||
sw s1, @.__len__(a0) # Store string length.
|
||||
mv a2, s1 # Pass length.
|
||||
mv s1, a0 # Save string object address.
|
||||
addi a1, a0, @.__str__ # Pass address of string data.
|
||||
li a0, @read_string # ecall to read from internal buffer.
|
||||
ecall
|
||||
addi a0, a0, 1 # Actual length (including NL).
|
||||
sw a0, @.__len__(s1) # Store actual length.
|
||||
add t0, a0, s1
|
||||
li t1, 10 # Store newline and null byte
|
||||
sb t1, @.__str__-1(t0)
|
||||
sb zero, @.__str__(t0) # Store null byte at end.
|
||||
mv a0, s1 # Return string object.
|
||||
|
||||
input_done:
|
||||
lw s1, -12(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 16
|
||||
jr ra
|
||||
|
||||
.globl $get_prime
|
||||
$get_prime:
|
||||
addi sp, sp, -@get_prime.size # Reserve space for stack frame.
|
||||
sw ra, @get_prime.size-4(sp) # return address
|
||||
sw fp, @get_prime.size-8(sp) # control link
|
||||
addi fp, sp, @get_prime.size # New fp is at old SP.
|
||||
li a0, 2 # Load integer literal 2
|
||||
sw a0, -12(fp) # local variable candidate
|
||||
li a0, 0 # Load integer literal 0
|
||||
sw a0, -16(fp) # local variable found
|
||||
j label_6 # Jump to loop test
|
||||
label_5: # Top of while loop
|
||||
lw a0, -12(fp) # Load var: get_prime.candidate
|
||||
sw a0, -32(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -32 # Set SP to last argument.
|
||||
jal $is_prime # Invoke function: is_prime
|
||||
addi sp, fp, -@get_prime.size # Set SP to stack frame top.
|
||||
beqz a0, label_7 # Branch on false.
|
||||
lw a0, -16(fp) # Load var: get_prime.found
|
||||
sw a0, -20(fp) # Push on stack slot 5
|
||||
li a0, 1 # Load integer literal 1
|
||||
lw t0, -20(fp) # Pop stack slot 5
|
||||
add a0, t0, a0 # Operator +
|
||||
sw a0, -16(fp) # Assign var: get_prime.found
|
||||
lw a0, -16(fp) # Load var: get_prime.found
|
||||
sw a0, -20(fp) # Push on stack slot 5
|
||||
lw a0, 0(fp) # Load var: get_prime.n
|
||||
lw t0, -20(fp) # Pop stack slot 5
|
||||
bne t0, a0, label_8 # Branch on not ==
|
||||
lw a0, -12(fp) # Load var: get_prime.candidate
|
||||
j label_4 # Go to return
|
||||
label_8: # End of if-else statement
|
||||
label_7: # End of if-else statement
|
||||
lw a0, -12(fp) # Load var: get_prime.candidate
|
||||
sw a0, -20(fp) # Push on stack slot 5
|
||||
li a0, 1 # Load integer literal 1
|
||||
lw t0, -20(fp) # Pop stack slot 5
|
||||
add a0, t0, a0 # Operator +
|
||||
sw a0, -12(fp) # Assign var: get_prime.candidate
|
||||
label_6: # Test loop condition
|
||||
j label_5 # Branch on true.
|
||||
li a0, 0 # Load integer literal 0
|
||||
j label_4 # Go to return
|
||||
mv a0, zero # Load None
|
||||
j label_4 # Jump to function epilogue
|
||||
label_4: # Epilogue
|
||||
.equiv @get_prime.size, 32
|
||||
lw ra, -4(fp) # Get return address
|
||||
lw fp, -8(fp) # Use control link to restore caller's fp
|
||||
addi sp, sp, @get_prime.size # Restore stack pointer
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $is_prime
|
||||
$is_prime:
|
||||
addi sp, sp, -@is_prime.size # Reserve space for stack frame.
|
||||
sw ra, @is_prime.size-4(sp) # return address
|
||||
sw fp, @is_prime.size-8(sp) # control link
|
||||
addi fp, sp, @is_prime.size # New fp is at old SP.
|
||||
li a0, 2 # Load integer literal 2
|
||||
sw a0, -12(fp) # local variable div
|
||||
j label_12 # Jump to loop test
|
||||
label_11: # Top of while loop
|
||||
lw a0, 0(fp) # Load var: is_prime.x
|
||||
sw a0, -16(fp) # Push on stack slot 4
|
||||
lw a0, -12(fp) # Load var: is_prime.div
|
||||
lw t0, -16(fp) # Pop stack slot 4
|
||||
bnez a0, label_14 # Ensure non-zero divisor
|
||||
j error.Div # Go to error handler
|
||||
label_14: # Divisor is non-zero
|
||||
rem t2, t0, a0 # Operator rem
|
||||
beqz t2, label_15 # If no remainder, no adjustment
|
||||
xor t3, t2, a0 # Check for differing signs.
|
||||
bgez t3, label_15 # Don't adjust if signs equal.
|
||||
add a0, t2, a0 # Adjust
|
||||
j label_16
|
||||
label_15: # Store result
|
||||
mv a0, t2
|
||||
label_16: # End of %
|
||||
sw a0, -16(fp) # Push on stack slot 4
|
||||
li a0, 0 # Load integer literal 0
|
||||
lw t0, -16(fp) # Pop stack slot 4
|
||||
bne t0, a0, label_13 # Branch on not ==
|
||||
li a0, 0 # Load boolean literal: false
|
||||
j label_10 # Go to return
|
||||
label_13: # End of if-else statement
|
||||
lw a0, -12(fp) # Load var: is_prime.div
|
||||
sw a0, -16(fp) # Push on stack slot 4
|
||||
li a0, 1 # Load integer literal 1
|
||||
lw t0, -16(fp) # Pop stack slot 4
|
||||
add a0, t0, a0 # Operator +
|
||||
sw a0, -12(fp) # Assign var: is_prime.div
|
||||
label_12: # Test loop condition
|
||||
lw a0, -12(fp) # Load var: is_prime.div
|
||||
sw a0, -16(fp) # Push on stack slot 4
|
||||
lw a0, 0(fp) # Load var: is_prime.x
|
||||
lw t0, -16(fp) # Pop stack slot 4
|
||||
blt t0, a0, label_11 # Branch on <
|
||||
li a0, 1 # Load boolean literal: true
|
||||
j label_10 # Go to return
|
||||
mv a0, zero # Load None
|
||||
j label_10 # Jump to function epilogue
|
||||
label_10: # Epilogue
|
||||
.equiv @is_prime.size, 16
|
||||
lw ra, -4(fp) # Get return address
|
||||
lw fp, -8(fp) # Use control link to restore caller's fp
|
||||
addi sp, sp, @is_prime.size # Restore stack pointer
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl alloc
|
||||
alloc:
|
||||
# Runtime support function alloc.
|
||||
# Prototype address is in a0.
|
||||
lw a1, 4(a0) # Get size of object in words
|
||||
j alloc2 # Allocate object with exact size
|
||||
|
||||
.globl alloc2
|
||||
alloc2:
|
||||
# Runtime support function alloc2 (realloc).
|
||||
# Prototype address is in a0.
|
||||
# Number of words to allocate is in a1.
|
||||
li a2, 4 # Word size in bytes
|
||||
mul a2, a1, a2 # Calculate number of bytes to allocate
|
||||
add a2, gp, a2 # Estimate where GP will move
|
||||
bgeu a2, s11, alloc2_15 # Go to OOM handler if too large
|
||||
lw t0, @.__obj_size__(a0) # Get size of object in words
|
||||
mv t2, a0 # Initialize src ptr
|
||||
mv t3, gp # Initialize dest ptr
|
||||
alloc2_16: # Copy-loop header
|
||||
lw t1, 0(t2) # Load next word from src
|
||||
sw t1, 0(t3) # Store next word to dest
|
||||
addi t2, t2, 4 # Increment src
|
||||
addi t3, t3, 4 # Increment dest
|
||||
addi t0, t0, -1 # Decrement counter
|
||||
bne t0, zero, alloc2_16 # Loop if more words left to copy
|
||||
mv a0, gp # Save new object's address to return
|
||||
sw a1, @.__obj_size__(a0) # Set size of new object in words
|
||||
# (same as requested size)
|
||||
mv gp, a2 # Set next free slot in the heap
|
||||
jr ra # Return to caller
|
||||
alloc2_15: # OOM handler
|
||||
li a0, @error_oom # Exit code for: Out of memory
|
||||
la a1, const_5 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl abort
|
||||
abort:
|
||||
# Runtime support function abort (does not return).
|
||||
mv t0, a0 # Save exit code in temp
|
||||
li a0, @print_string # Code for print_string ecall
|
||||
ecall # Print error message in a1
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for print_char ecall
|
||||
ecall # Print newline
|
||||
mv a1, t0 # Move exit code to a1
|
||||
li a0, @exit2 # Code for exit2 ecall
|
||||
ecall # Exit with code
|
||||
abort_17: # Infinite loop
|
||||
j abort_17 # Prevent fallthrough
|
||||
|
||||
.globl heap.init
|
||||
heap.init:
|
||||
# Runtime support function heap.init.
|
||||
mv a1, a0 # Move requested size to A1
|
||||
li a0, @sbrk # Code for ecall: sbrk
|
||||
ecall # Request A1 bytes
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl concat
|
||||
concat:
|
||||
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw fp, 24(sp)
|
||||
addi fp, sp, 32
|
||||
sw s1, -12(fp)
|
||||
sw s2, -16(fp)
|
||||
sw s3, -20(fp)
|
||||
sw s4, -24(fp)
|
||||
sw s5, -28(fp)
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
beqz t0, concat_none
|
||||
beqz t1, concat_none
|
||||
lw t0, @.__len__(t0)
|
||||
lw t1, @.__len__(t1)
|
||||
add s5, t0, t1
|
||||
addi a1, s5, @listHeaderWords
|
||||
la a0, $.list$prototype
|
||||
jal alloc2
|
||||
sw s5, @.__len__(a0)
|
||||
mv s5, a0
|
||||
addi s3, s5, @.__elts__
|
||||
lw s1, 4(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 12(fp)
|
||||
concat_1:
|
||||
beqz s2, concat_2
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_1
|
||||
concat_2:
|
||||
lw s1, 0(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 8(fp)
|
||||
concat_3:
|
||||
beqz s2, concat_4
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_3
|
||||
concat_4:
|
||||
mv a0, s5
|
||||
lw s1, -12(fp)
|
||||
lw s2, -16(fp)
|
||||
lw s3, -20(fp)
|
||||
lw s4, -24(fp)
|
||||
lw s5, -28(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 32
|
||||
jr ra
|
||||
concat_none:
|
||||
j error.None
|
||||
|
||||
|
||||
.globl conslist
|
||||
conslist:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 0(fp)
|
||||
la a0, $.list$prototype
|
||||
beqz a1, conslist_done
|
||||
addi a1, a1, @listHeaderWords
|
||||
jal alloc2
|
||||
lw t0, 0(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
slli t1, t0, 2
|
||||
add t1, t1, fp
|
||||
addi t2, a0, @.__elts__
|
||||
conslist_1:
|
||||
lw t3, 0(t1)
|
||||
sw t3, 0(t2)
|
||||
addi t1, t1, -4
|
||||
addi t2, t2, 4
|
||||
addi t0, t0, -1
|
||||
bnez t0, conslist_1
|
||||
conslist_done:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strcat
|
||||
strcat:
|
||||
|
||||
addi sp, sp, -12
|
||||
sw ra, 8(sp)
|
||||
sw fp, 4(sp)
|
||||
addi fp, sp, 12
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
lw t0, @.__len__(t0)
|
||||
beqz t0, strcat_4
|
||||
lw t1, @.__len__(t1)
|
||||
beqz t1, strcat_5
|
||||
add t1, t0, t1
|
||||
sw t1, -12(fp)
|
||||
addi t1, t1, 4
|
||||
srli t1, t1, 2
|
||||
addi a1, t1, @listHeaderWords
|
||||
la a0, $str$prototype
|
||||
jal alloc2
|
||||
lw t0, -12(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
addi t2, a0, 16
|
||||
lw t0, 4(fp)
|
||||
lw t1, @.__len__(t0)
|
||||
addi t0, t0, @.__str__
|
||||
strcat_1:
|
||||
beqz t1, strcat_2
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_1
|
||||
strcat_2:
|
||||
lw t0, 0(fp)
|
||||
lw t1, 12(t0)
|
||||
addi t0, t0, 16
|
||||
strcat_3:
|
||||
beqz t1, strcat_6
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_3
|
||||
strcat_4:
|
||||
lw a0, 0(fp)
|
||||
j strcat_7
|
||||
strcat_5:
|
||||
lw a0, 4(fp)
|
||||
j strcat_7
|
||||
strcat_6:
|
||||
sb zero, 0(t2)
|
||||
strcat_7:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 12
|
||||
jr ra
|
||||
|
||||
|
||||
.globl streql
|
||||
streql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, streql_no
|
||||
streql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, streql_no
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, streql_1
|
||||
li a0, 1
|
||||
j streql_end
|
||||
streql_no:
|
||||
xor a0, a0, a0
|
||||
streql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strneql
|
||||
strneql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, strneql_yes
|
||||
strneql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, strneql_yes
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, strneql_1
|
||||
xor a0, a0, a0
|
||||
j strneql_end
|
||||
strneql_yes:
|
||||
li a0, 1
|
||||
strneql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makeint
|
||||
makeint:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw a0, 0(sp)
|
||||
la a0, $int$prototype
|
||||
jal ra, alloc
|
||||
lw t0, 0(sp)
|
||||
sw t0, @.__int__(a0)
|
||||
lw ra, 4(sp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makebool
|
||||
makebool:
|
||||
|
||||
slli a0, a0, 4
|
||||
la t0, @bool.False
|
||||
add a0, a0, t0
|
||||
jr ra
|
||||
|
||||
|
||||
.globl noconv
|
||||
noconv:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl initchars
|
||||
initchars:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl error.None
|
||||
error.None:
|
||||
li a0, 4 # Exit code for: Operation on None
|
||||
la a1, const_6 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.Div
|
||||
error.Div:
|
||||
li a0, 2 # Exit code for: Division by zero
|
||||
la a1, const_7 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.OOB
|
||||
error.OOB:
|
||||
li a0, 3 # Exit code for: Index out of bounds
|
||||
la a1, const_8 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.data
|
||||
|
||||
.globl const_0
|
||||
const_0:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_1
|
||||
const_1:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 1 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_7
|
||||
const_7:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Division by zero" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_5
|
||||
const_5:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 8 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 13 # Constant value of attribute: __len__
|
||||
.string "Out of memory" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_8
|
||||
const_8:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 19 # Constant value of attribute: __len__
|
||||
.string "Index out of bounds" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_3
|
||||
const_3:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 4 # Constant value of attribute: __len__
|
||||
.string "True" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_6
|
||||
const_6:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 17 # Constant value of attribute: __len__
|
||||
.string "Operation on None" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_2
|
||||
const_2:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Invalid argument" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_4
|
||||
const_4:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "False" # Constant value of attribute: __str__
|
||||
.align 2
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,794 @@
|
||||
.equiv @sbrk, 9
|
||||
.equiv @print_string, 4
|
||||
.equiv @print_char, 11
|
||||
.equiv @print_int, 1
|
||||
.equiv @exit2, 17
|
||||
.equiv @read_string, 8
|
||||
.equiv @fill_line_buffer, 18
|
||||
.equiv @.__obj_size__, 4
|
||||
.equiv @.__len__, 12
|
||||
.equiv @.__int__, 12
|
||||
.equiv @.__bool__, 12
|
||||
.equiv @.__str__, 16
|
||||
.equiv @.__elts__, 16
|
||||
.equiv @error_div_zero, 2
|
||||
.equiv @error_arg, 1
|
||||
.equiv @error_oob, 3
|
||||
.equiv @error_none, 4
|
||||
.equiv @error_oom, 5
|
||||
.equiv @error_nyi, 6
|
||||
.equiv @listHeaderWords, 4
|
||||
.equiv @strHeaderWords, 4
|
||||
.equiv @bool.True, const_1
|
||||
.equiv @bool.False, const_0
|
||||
|
||||
.data
|
||||
|
||||
.globl $object$prototype
|
||||
$object$prototype:
|
||||
.word 0 # Type tag for class: object
|
||||
.word 3 # Object size
|
||||
.word $object$dispatchTable # Pointer to dispatch table
|
||||
.align 2
|
||||
|
||||
.globl $int$prototype
|
||||
$int$prototype:
|
||||
.word 1 # Type tag for class: int
|
||||
.word 4 # Object size
|
||||
.word $int$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __int__
|
||||
.align 2
|
||||
|
||||
.globl $bool$prototype
|
||||
$bool$prototype:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl $str$prototype
|
||||
$str$prototype:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 5 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.word 0 # Initial value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl $.list$prototype
|
||||
$.list$prototype:
|
||||
.word -1 # Type tag for class: .list
|
||||
.word 4 # Object size
|
||||
.word 0 # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.align 2
|
||||
|
||||
.globl $object$dispatchTable
|
||||
$object$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: object.__init__
|
||||
|
||||
.globl $int$dispatchTable
|
||||
$int$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: int.__init__
|
||||
|
||||
.globl $bool$dispatchTable
|
||||
$bool$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: bool.__init__
|
||||
|
||||
.globl $str$dispatchTable
|
||||
$str$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: str.__init__
|
||||
|
||||
.text
|
||||
|
||||
.globl main
|
||||
main:
|
||||
lui a0, 8192 # Initialize heap size (in multiples of 4KB)
|
||||
add s11, s11, a0 # Save heap size
|
||||
jal heap.init # Call heap.init routine
|
||||
mv gp, a0 # Initialize heap pointer
|
||||
mv s10, gp # Set beginning of heap
|
||||
add s11, s10, s11 # Set end of heap (= start of heap + heap size)
|
||||
mv ra, zero # No normal return from main program.
|
||||
mv fp, zero # No preceding frame.
|
||||
addi sp, sp, -@..main.size # Reserve space for stack frame.
|
||||
sw ra, @..main.size-4(sp) # return address
|
||||
sw fp, @..main.size-8(sp) # control link
|
||||
addi fp, sp, @..main.size # New fp is at old SP.
|
||||
jal initchars # Initialize one-character strings.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $f # Invoke function: f
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
jal makeint # Box integer
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
.equiv @..main.size, 16
|
||||
label_0: # End of program
|
||||
li a0, 10 # Code for ecall: exit
|
||||
ecall
|
||||
|
||||
.globl $object.__init__
|
||||
$object.__init__:
|
||||
# Init method for type object.
|
||||
mv a0, zero # `None` constant
|
||||
jr ra # Return
|
||||
|
||||
.globl $print
|
||||
$print:
|
||||
# Function print
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, print_6 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 1 # Load type tag of `int`
|
||||
beq t0, t1, print_7 # Go to print(int)
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, print_8 # Go to print(str)
|
||||
li t1, 2 # Load type tag of `bool`
|
||||
beq t0, t1, print_9 # Go to print(bool)
|
||||
print_6: # Invalid argument
|
||||
li a0, 1 # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
# Printing bools
|
||||
print_9: # Print bool object in A0
|
||||
lw a0, @.__bool__(a0) # Load attribute __bool__
|
||||
beq a0, zero, print_10 # Go to: print(False)
|
||||
la a0, const_3 # String representation: True
|
||||
j print_8 # Go to: print(str)
|
||||
print_10: # Print False object in A0
|
||||
la a0, const_4 # String representation: False
|
||||
j print_8 # Go to: print(str)
|
||||
|
||||
# Printing strs.
|
||||
print_8: # Print str object in A0
|
||||
addi a1, a0, @.__str__ # Load address of attribute __str__
|
||||
j print_11 # Print the null-terminated string is now in A1
|
||||
mv a0, zero # Load None
|
||||
j print_5 # Go to return
|
||||
print_11: # Print null-terminated string in A1
|
||||
li a0, @print_string # Code for ecall: print_string
|
||||
ecall # Print string
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
j print_5 # Go to return
|
||||
|
||||
# Printing ints.
|
||||
print_7: # Print int object in A0
|
||||
lw a1, @.__int__(a0) # Load attribute __int__
|
||||
li a0, @print_int # Code for ecall: print_int
|
||||
ecall # Print integer
|
||||
li a1, 10 # Load newline character
|
||||
li a0, 11 # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
|
||||
print_5: # End of function
|
||||
mv a0, zero # Load None
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $len
|
||||
$len:
|
||||
# Function len
|
||||
# We do not save/restore fp/ra for this function
|
||||
# because we know that it does not use the stack or does not
|
||||
# call other functions.
|
||||
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, len_12 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, len_13 # Go to len(str)
|
||||
li t1, -1 # Load type tag for list objects
|
||||
beq t0, t1, len_13 # Go to len(list)
|
||||
len_12: # Invalid argument
|
||||
li a0, @error_arg # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
len_13: # Get length of string
|
||||
lw a0, @.__len__(a0) # Load attribute: __len__
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $input
|
||||
$input:
|
||||
# Function input
|
||||
addi sp, sp, -16 # Reserve stack
|
||||
sw ra, 12(sp) # Save registers
|
||||
sw fp, 8(sp)
|
||||
sw s1, 4(sp)
|
||||
addi fp, sp, 16 # Set fp
|
||||
|
||||
li a0, @fill_line_buffer # Fill the internal line buffer.
|
||||
ecall
|
||||
bgez a0, input_nonempty # More input found
|
||||
la a0, $str$prototype # EOF: Return empty string.
|
||||
j input_done
|
||||
|
||||
input_nonempty:
|
||||
mv s1, a0
|
||||
addi t0, s1, 5 # Compute bytes for string (+NL+NUL),
|
||||
addi t0, t0, @.__str__ # Including header.
|
||||
srli a1, t0, 2 # Convert to words.
|
||||
la a0, $str$prototype # Load address of string prototype.
|
||||
jal ra, alloc2 # Allocate string.
|
||||
sw s1, @.__len__(a0) # Store string length.
|
||||
mv a2, s1 # Pass length.
|
||||
mv s1, a0 # Save string object address.
|
||||
addi a1, a0, @.__str__ # Pass address of string data.
|
||||
li a0, @read_string # ecall to read from internal buffer.
|
||||
ecall
|
||||
addi a0, a0, 1 # Actual length (including NL).
|
||||
sw a0, @.__len__(s1) # Store actual length.
|
||||
add t0, a0, s1
|
||||
li t1, 10 # Store newline and null byte
|
||||
sb t1, @.__str__-1(t0)
|
||||
sb zero, @.__str__(t0) # Store null byte at end.
|
||||
mv a0, s1 # Return string object.
|
||||
|
||||
input_done:
|
||||
lw s1, -12(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 16
|
||||
jr ra
|
||||
|
||||
.globl $f
|
||||
$f:
|
||||
addi sp, sp, -@f.size # Reserve space for stack frame.
|
||||
sw ra, @f.size-4(sp) # return address
|
||||
sw fp, @f.size-8(sp) # control link
|
||||
addi fp, sp, @f.size # New fp is at old SP.
|
||||
la a0, const_5 # Load string literal
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@f.size # Set SP to stack frame top.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $g # Invoke function: g
|
||||
addi sp, fp, -@f.size # Set SP to stack frame top.
|
||||
la a0, const_6 # Load string literal
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@f.size # Set SP to stack frame top.
|
||||
li a0, 42 # Load integer literal 42
|
||||
j label_2 # Go to return
|
||||
mv a0, zero # Load None
|
||||
j label_2 # Jump to function epilogue
|
||||
label_2: # Epilogue
|
||||
.equiv @f.size, 16
|
||||
lw ra, -4(fp) # Get return address
|
||||
lw fp, -8(fp) # Use control link to restore caller's fp
|
||||
addi sp, sp, @f.size # Restore stack pointer
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $g
|
||||
$g:
|
||||
addi sp, sp, -@g.size # Reserve space for stack frame.
|
||||
sw ra, @g.size-4(sp) # return address
|
||||
sw fp, @g.size-8(sp) # control link
|
||||
addi fp, sp, @g.size # New fp is at old SP.
|
||||
la a0, const_7 # Load string literal
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@g.size # Set SP to stack frame top.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $h # Invoke function: h
|
||||
addi sp, fp, -@g.size # Set SP to stack frame top.
|
||||
la a0, const_8 # Load string literal
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@g.size # Set SP to stack frame top.
|
||||
mv a0, zero # Load None
|
||||
j label_4 # Jump to function epilogue
|
||||
label_4: # Epilogue
|
||||
.equiv @g.size, 16
|
||||
lw ra, -4(fp) # Get return address
|
||||
lw fp, -8(fp) # Use control link to restore caller's fp
|
||||
addi sp, sp, @g.size # Restore stack pointer
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $h
|
||||
$h:
|
||||
addi sp, sp, -@h.size # Reserve space for stack frame.
|
||||
sw ra, @h.size-4(sp) # return address
|
||||
sw fp, @h.size-8(sp) # control link
|
||||
addi fp, sp, @h.size # New fp is at old SP.
|
||||
la a0, const_9 # Load string literal
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@h.size # Set SP to stack frame top.
|
||||
la a0, const_10 # Load string literal
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@h.size # Set SP to stack frame top.
|
||||
mv a0, zero # Load None
|
||||
j label_6 # Jump to function epilogue
|
||||
label_6: # Epilogue
|
||||
.equiv @h.size, 16
|
||||
lw ra, -4(fp) # Get return address
|
||||
lw fp, -8(fp) # Use control link to restore caller's fp
|
||||
addi sp, sp, @h.size # Restore stack pointer
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl alloc
|
||||
alloc:
|
||||
# Runtime support function alloc.
|
||||
# Prototype address is in a0.
|
||||
lw a1, 4(a0) # Get size of object in words
|
||||
j alloc2 # Allocate object with exact size
|
||||
|
||||
.globl alloc2
|
||||
alloc2:
|
||||
# Runtime support function alloc2 (realloc).
|
||||
# Prototype address is in a0.
|
||||
# Number of words to allocate is in a1.
|
||||
li a2, 4 # Word size in bytes
|
||||
mul a2, a1, a2 # Calculate number of bytes to allocate
|
||||
add a2, gp, a2 # Estimate where GP will move
|
||||
bgeu a2, s11, alloc2_15 # Go to OOM handler if too large
|
||||
lw t0, @.__obj_size__(a0) # Get size of object in words
|
||||
mv t2, a0 # Initialize src ptr
|
||||
mv t3, gp # Initialize dest ptr
|
||||
alloc2_16: # Copy-loop header
|
||||
lw t1, 0(t2) # Load next word from src
|
||||
sw t1, 0(t3) # Store next word to dest
|
||||
addi t2, t2, 4 # Increment src
|
||||
addi t3, t3, 4 # Increment dest
|
||||
addi t0, t0, -1 # Decrement counter
|
||||
bne t0, zero, alloc2_16 # Loop if more words left to copy
|
||||
mv a0, gp # Save new object's address to return
|
||||
sw a1, @.__obj_size__(a0) # Set size of new object in words
|
||||
# (same as requested size)
|
||||
mv gp, a2 # Set next free slot in the heap
|
||||
jr ra # Return to caller
|
||||
alloc2_15: # OOM handler
|
||||
li a0, @error_oom # Exit code for: Out of memory
|
||||
la a1, const_11 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl abort
|
||||
abort:
|
||||
# Runtime support function abort (does not return).
|
||||
mv t0, a0 # Save exit code in temp
|
||||
li a0, @print_string # Code for print_string ecall
|
||||
ecall # Print error message in a1
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for print_char ecall
|
||||
ecall # Print newline
|
||||
mv a1, t0 # Move exit code to a1
|
||||
li a0, @exit2 # Code for exit2 ecall
|
||||
ecall # Exit with code
|
||||
abort_17: # Infinite loop
|
||||
j abort_17 # Prevent fallthrough
|
||||
|
||||
.globl heap.init
|
||||
heap.init:
|
||||
# Runtime support function heap.init.
|
||||
mv a1, a0 # Move requested size to A1
|
||||
li a0, @sbrk # Code for ecall: sbrk
|
||||
ecall # Request A1 bytes
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl concat
|
||||
concat:
|
||||
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw fp, 24(sp)
|
||||
addi fp, sp, 32
|
||||
sw s1, -12(fp)
|
||||
sw s2, -16(fp)
|
||||
sw s3, -20(fp)
|
||||
sw s4, -24(fp)
|
||||
sw s5, -28(fp)
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
beqz t0, concat_none
|
||||
beqz t1, concat_none
|
||||
lw t0, @.__len__(t0)
|
||||
lw t1, @.__len__(t1)
|
||||
add s5, t0, t1
|
||||
addi a1, s5, @listHeaderWords
|
||||
la a0, $.list$prototype
|
||||
jal alloc2
|
||||
sw s5, @.__len__(a0)
|
||||
mv s5, a0
|
||||
addi s3, s5, @.__elts__
|
||||
lw s1, 4(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 12(fp)
|
||||
concat_1:
|
||||
beqz s2, concat_2
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_1
|
||||
concat_2:
|
||||
lw s1, 0(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 8(fp)
|
||||
concat_3:
|
||||
beqz s2, concat_4
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_3
|
||||
concat_4:
|
||||
mv a0, s5
|
||||
lw s1, -12(fp)
|
||||
lw s2, -16(fp)
|
||||
lw s3, -20(fp)
|
||||
lw s4, -24(fp)
|
||||
lw s5, -28(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 32
|
||||
jr ra
|
||||
concat_none:
|
||||
j error.None
|
||||
|
||||
|
||||
.globl conslist
|
||||
conslist:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 0(fp)
|
||||
la a0, $.list$prototype
|
||||
beqz a1, conslist_done
|
||||
addi a1, a1, @listHeaderWords
|
||||
jal alloc2
|
||||
lw t0, 0(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
slli t1, t0, 2
|
||||
add t1, t1, fp
|
||||
addi t2, a0, @.__elts__
|
||||
conslist_1:
|
||||
lw t3, 0(t1)
|
||||
sw t3, 0(t2)
|
||||
addi t1, t1, -4
|
||||
addi t2, t2, 4
|
||||
addi t0, t0, -1
|
||||
bnez t0, conslist_1
|
||||
conslist_done:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strcat
|
||||
strcat:
|
||||
|
||||
addi sp, sp, -12
|
||||
sw ra, 8(sp)
|
||||
sw fp, 4(sp)
|
||||
addi fp, sp, 12
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
lw t0, @.__len__(t0)
|
||||
beqz t0, strcat_4
|
||||
lw t1, @.__len__(t1)
|
||||
beqz t1, strcat_5
|
||||
add t1, t0, t1
|
||||
sw t1, -12(fp)
|
||||
addi t1, t1, 4
|
||||
srli t1, t1, 2
|
||||
addi a1, t1, @listHeaderWords
|
||||
la a0, $str$prototype
|
||||
jal alloc2
|
||||
lw t0, -12(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
addi t2, a0, 16
|
||||
lw t0, 4(fp)
|
||||
lw t1, @.__len__(t0)
|
||||
addi t0, t0, @.__str__
|
||||
strcat_1:
|
||||
beqz t1, strcat_2
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_1
|
||||
strcat_2:
|
||||
lw t0, 0(fp)
|
||||
lw t1, 12(t0)
|
||||
addi t0, t0, 16
|
||||
strcat_3:
|
||||
beqz t1, strcat_6
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_3
|
||||
strcat_4:
|
||||
lw a0, 0(fp)
|
||||
j strcat_7
|
||||
strcat_5:
|
||||
lw a0, 4(fp)
|
||||
j strcat_7
|
||||
strcat_6:
|
||||
sb zero, 0(t2)
|
||||
strcat_7:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 12
|
||||
jr ra
|
||||
|
||||
|
||||
.globl streql
|
||||
streql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, streql_no
|
||||
streql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, streql_no
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, streql_1
|
||||
li a0, 1
|
||||
j streql_end
|
||||
streql_no:
|
||||
xor a0, a0, a0
|
||||
streql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strneql
|
||||
strneql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, strneql_yes
|
||||
strneql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, strneql_yes
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, strneql_1
|
||||
xor a0, a0, a0
|
||||
j strneql_end
|
||||
strneql_yes:
|
||||
li a0, 1
|
||||
strneql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makeint
|
||||
makeint:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw a0, 0(sp)
|
||||
la a0, $int$prototype
|
||||
jal ra, alloc
|
||||
lw t0, 0(sp)
|
||||
sw t0, @.__int__(a0)
|
||||
lw ra, 4(sp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makebool
|
||||
makebool:
|
||||
|
||||
slli a0, a0, 4
|
||||
la t0, @bool.False
|
||||
add a0, a0, t0
|
||||
jr ra
|
||||
|
||||
|
||||
.globl noconv
|
||||
noconv:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl initchars
|
||||
initchars:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl error.None
|
||||
error.None:
|
||||
li a0, 4 # Exit code for: Operation on None
|
||||
la a1, const_12 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.Div
|
||||
error.Div:
|
||||
li a0, 2 # Exit code for: Division by zero
|
||||
la a1, const_13 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.OOB
|
||||
error.OOB:
|
||||
li a0, 3 # Exit code for: Index out of bounds
|
||||
la a1, const_14 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.data
|
||||
|
||||
.globl const_0
|
||||
const_0:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_1
|
||||
const_1:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 1 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_8
|
||||
const_8:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "end g" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_9
|
||||
const_9:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 7 # Constant value of attribute: __len__
|
||||
.string "start h" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_10
|
||||
const_10:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "end h" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_7
|
||||
const_7:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 7 # Constant value of attribute: __len__
|
||||
.string "start g" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_5
|
||||
const_5:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 7 # Constant value of attribute: __len__
|
||||
.string "start f" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_6
|
||||
const_6:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "end f" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_11
|
||||
const_11:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 8 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 13 # Constant value of attribute: __len__
|
||||
.string "Out of memory" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_3
|
||||
const_3:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 4 # Constant value of attribute: __len__
|
||||
.string "True" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_4
|
||||
const_4:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "False" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_13
|
||||
const_13:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Division by zero" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_14
|
||||
const_14:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 19 # Constant value of attribute: __len__
|
||||
.string "Index out of bounds" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_12
|
||||
const_12:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 17 # Constant value of attribute: __len__
|
||||
.string "Operation on None" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_2
|
||||
const_2:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Invalid argument" # Constant value of attribute: __str__
|
||||
.align 2
|
@ -0,0 +1,806 @@
|
||||
.equiv @sbrk, 9
|
||||
.equiv @print_string, 4
|
||||
.equiv @print_char, 11
|
||||
.equiv @print_int, 1
|
||||
.equiv @exit2, 17
|
||||
.equiv @read_string, 8
|
||||
.equiv @fill_line_buffer, 18
|
||||
.equiv @.__obj_size__, 4
|
||||
.equiv @.__len__, 12
|
||||
.equiv @.__int__, 12
|
||||
.equiv @.__bool__, 12
|
||||
.equiv @.__str__, 16
|
||||
.equiv @.__elts__, 16
|
||||
.equiv @error_div_zero, 2
|
||||
.equiv @error_arg, 1
|
||||
.equiv @error_oob, 3
|
||||
.equiv @error_none, 4
|
||||
.equiv @error_oom, 5
|
||||
.equiv @error_nyi, 6
|
||||
.equiv @listHeaderWords, 4
|
||||
.equiv @strHeaderWords, 4
|
||||
.equiv @bool.True, const_1
|
||||
.equiv @bool.False, const_0
|
||||
|
||||
.data
|
||||
|
||||
.globl $object$prototype
|
||||
$object$prototype:
|
||||
.word 0 # Type tag for class: object
|
||||
.word 3 # Object size
|
||||
.word $object$dispatchTable # Pointer to dispatch table
|
||||
.align 2
|
||||
|
||||
.globl $int$prototype
|
||||
$int$prototype:
|
||||
.word 1 # Type tag for class: int
|
||||
.word 4 # Object size
|
||||
.word $int$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __int__
|
||||
.align 2
|
||||
|
||||
.globl $bool$prototype
|
||||
$bool$prototype:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl $str$prototype
|
||||
$str$prototype:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 5 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.word 0 # Initial value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl $.list$prototype
|
||||
$.list$prototype:
|
||||
.word -1 # Type tag for class: .list
|
||||
.word 4 # Object size
|
||||
.word 0 # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.align 2
|
||||
|
||||
.globl $object$dispatchTable
|
||||
$object$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: object.__init__
|
||||
|
||||
.globl $int$dispatchTable
|
||||
$int$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: int.__init__
|
||||
|
||||
.globl $bool$dispatchTable
|
||||
$bool$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: bool.__init__
|
||||
|
||||
.globl $str$dispatchTable
|
||||
$str$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: str.__init__
|
||||
|
||||
.text
|
||||
|
||||
.globl main
|
||||
main:
|
||||
lui a0, 8192 # Initialize heap size (in multiples of 4KB)
|
||||
add s11, s11, a0 # Save heap size
|
||||
jal heap.init # Call heap.init routine
|
||||
mv gp, a0 # Initialize heap pointer
|
||||
mv s10, gp # Set beginning of heap
|
||||
add s11, s10, s11 # Set end of heap (= start of heap + heap size)
|
||||
mv ra, zero # No normal return from main program.
|
||||
mv fp, zero # No preceding frame.
|
||||
addi sp, sp, -@..main.size # Reserve space for stack frame.
|
||||
sw ra, @..main.size-4(sp) # return address
|
||||
sw fp, @..main.size-8(sp) # control link
|
||||
addi fp, sp, @..main.size # New fp is at old SP.
|
||||
jal initchars # Initialize one-character strings.
|
||||
li a0, 4 # Load integer literal 4
|
||||
sw a0, -32(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -32 # Set SP to last argument.
|
||||
jal $f # Invoke function: f
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
jal makeint # Box integer
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
.equiv @..main.size, 32
|
||||
label_0: # End of program
|
||||
li a0, 10 # Code for ecall: exit
|
||||
ecall
|
||||
|
||||
.globl $object.__init__
|
||||
$object.__init__:
|
||||
# Init method for type object.
|
||||
mv a0, zero # `None` constant
|
||||
jr ra # Return
|
||||
|
||||
.globl $print
|
||||
$print:
|
||||
# Function print
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, print_6 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 1 # Load type tag of `int`
|
||||
beq t0, t1, print_7 # Go to print(int)
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, print_8 # Go to print(str)
|
||||
li t1, 2 # Load type tag of `bool`
|
||||
beq t0, t1, print_9 # Go to print(bool)
|
||||
print_6: # Invalid argument
|
||||
li a0, 1 # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
# Printing bools
|
||||
print_9: # Print bool object in A0
|
||||
lw a0, @.__bool__(a0) # Load attribute __bool__
|
||||
beq a0, zero, print_10 # Go to: print(False)
|
||||
la a0, const_3 # String representation: True
|
||||
j print_8 # Go to: print(str)
|
||||
print_10: # Print False object in A0
|
||||
la a0, const_4 # String representation: False
|
||||
j print_8 # Go to: print(str)
|
||||
|
||||
# Printing strs.
|
||||
print_8: # Print str object in A0
|
||||
addi a1, a0, @.__str__ # Load address of attribute __str__
|
||||
j print_11 # Print the null-terminated string is now in A1
|
||||
mv a0, zero # Load None
|
||||
j print_5 # Go to return
|
||||
print_11: # Print null-terminated string in A1
|
||||
li a0, @print_string # Code for ecall: print_string
|
||||
ecall # Print string
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
j print_5 # Go to return
|
||||
|
||||
# Printing ints.
|
||||
print_7: # Print int object in A0
|
||||
lw a1, @.__int__(a0) # Load attribute __int__
|
||||
li a0, @print_int # Code for ecall: print_int
|
||||
ecall # Print integer
|
||||
li a1, 10 # Load newline character
|
||||
li a0, 11 # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
|
||||
print_5: # End of function
|
||||
mv a0, zero # Load None
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $len
|
||||
$len:
|
||||
# Function len
|
||||
# We do not save/restore fp/ra for this function
|
||||
# because we know that it does not use the stack or does not
|
||||
# call other functions.
|
||||
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, len_12 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, len_13 # Go to len(str)
|
||||
li t1, -1 # Load type tag for list objects
|
||||
beq t0, t1, len_13 # Go to len(list)
|
||||
len_12: # Invalid argument
|
||||
li a0, @error_arg # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
len_13: # Get length of string
|
||||
lw a0, @.__len__(a0) # Load attribute: __len__
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $input
|
||||
$input:
|
||||
# Function input
|
||||
addi sp, sp, -16 # Reserve stack
|
||||
sw ra, 12(sp) # Save registers
|
||||
sw fp, 8(sp)
|
||||
sw s1, 4(sp)
|
||||
addi fp, sp, 16 # Set fp
|
||||
|
||||
li a0, @fill_line_buffer # Fill the internal line buffer.
|
||||
ecall
|
||||
bgez a0, input_nonempty # More input found
|
||||
la a0, $str$prototype # EOF: Return empty string.
|
||||
j input_done
|
||||
|
||||
input_nonempty:
|
||||
mv s1, a0
|
||||
addi t0, s1, 5 # Compute bytes for string (+NL+NUL),
|
||||
addi t0, t0, @.__str__ # Including header.
|
||||
srli a1, t0, 2 # Convert to words.
|
||||
la a0, $str$prototype # Load address of string prototype.
|
||||
jal ra, alloc2 # Allocate string.
|
||||
sw s1, @.__len__(a0) # Store string length.
|
||||
mv a2, s1 # Pass length.
|
||||
mv s1, a0 # Save string object address.
|
||||
addi a1, a0, @.__str__ # Pass address of string data.
|
||||
li a0, @read_string # ecall to read from internal buffer.
|
||||
ecall
|
||||
addi a0, a0, 1 # Actual length (including NL).
|
||||
sw a0, @.__len__(s1) # Store actual length.
|
||||
add t0, a0, s1
|
||||
li t1, 10 # Store newline and null byte
|
||||
sb t1, @.__str__-1(t0)
|
||||
sb zero, @.__str__(t0) # Store null byte at end.
|
||||
mv a0, s1 # Return string object.
|
||||
|
||||
input_done:
|
||||
lw s1, -12(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 16
|
||||
jr ra
|
||||
|
||||
.globl $f
|
||||
$f:
|
||||
addi sp, sp, -@f.size # Reserve space for stack frame.
|
||||
sw ra, @f.size-4(sp) # return address
|
||||
sw fp, @f.size-8(sp) # control link
|
||||
addi fp, sp, @f.size # New fp is at old SP.
|
||||
la a0, const_5 # Load string literal
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@f.size # Set SP to stack frame top.
|
||||
lw a0, 0(fp) # Load var: f.x
|
||||
jal makeint # Box integer
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@f.size # Set SP to stack frame top.
|
||||
li a0, 1 # Load integer literal 1
|
||||
sw a0, -12(fp) # Push argument 1 from last.
|
||||
lw a0, 0(fp) # Load var: f.x
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $g # Invoke function: g
|
||||
addi sp, fp, -@f.size # Set SP to stack frame top.
|
||||
la a0, const_6 # Load string literal
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@f.size # Set SP to stack frame top.
|
||||
lw a0, 0(fp) # Load var: f.x
|
||||
j label_2 # Go to return
|
||||
mv a0, zero # Load None
|
||||
j label_2 # Jump to function epilogue
|
||||
label_2: # Epilogue
|
||||
.equiv @f.size, 16
|
||||
lw ra, -4(fp) # Get return address
|
||||
lw fp, -8(fp) # Use control link to restore caller's fp
|
||||
addi sp, sp, @f.size # Restore stack pointer
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $g
|
||||
$g:
|
||||
addi sp, sp, -@g.size # Reserve space for stack frame.
|
||||
sw ra, @g.size-4(sp) # return address
|
||||
sw fp, @g.size-8(sp) # control link
|
||||
addi fp, sp, @g.size # New fp is at old SP.
|
||||
la a0, const_7 # Load string literal
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@g.size # Set SP to stack frame top.
|
||||
lw a0, 4(fp) # Load var: g.y
|
||||
jal makeint # Box integer
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@g.size # Set SP to stack frame top.
|
||||
lw a0, 0(fp) # Load var: g.z
|
||||
jal makeint # Box integer
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@g.size # Set SP to stack frame top.
|
||||
la a0, const_8 # Load string literal
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $h # Invoke function: h
|
||||
addi sp, fp, -@g.size # Set SP to stack frame top.
|
||||
la a0, const_9 # Load string literal
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@g.size # Set SP to stack frame top.
|
||||
mv a0, zero # Load None
|
||||
j label_4 # Jump to function epilogue
|
||||
label_4: # Epilogue
|
||||
.equiv @g.size, 16
|
||||
lw ra, -4(fp) # Get return address
|
||||
lw fp, -8(fp) # Use control link to restore caller's fp
|
||||
addi sp, sp, @g.size # Restore stack pointer
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $h
|
||||
$h:
|
||||
addi sp, sp, -@h.size # Reserve space for stack frame.
|
||||
sw ra, @h.size-4(sp) # return address
|
||||
sw fp, @h.size-8(sp) # control link
|
||||
addi fp, sp, @h.size # New fp is at old SP.
|
||||
lw a0, 0(fp) # Load var: h.msg
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@h.size # Set SP to stack frame top.
|
||||
mv a0, zero # Load None
|
||||
j label_6 # Jump to function epilogue
|
||||
label_6: # Epilogue
|
||||
.equiv @h.size, 16
|
||||
lw ra, -4(fp) # Get return address
|
||||
lw fp, -8(fp) # Use control link to restore caller's fp
|
||||
addi sp, sp, @h.size # Restore stack pointer
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl alloc
|
||||
alloc:
|
||||
# Runtime support function alloc.
|
||||
# Prototype address is in a0.
|
||||
lw a1, 4(a0) # Get size of object in words
|
||||
j alloc2 # Allocate object with exact size
|
||||
|
||||
.globl alloc2
|
||||
alloc2:
|
||||
# Runtime support function alloc2 (realloc).
|
||||
# Prototype address is in a0.
|
||||
# Number of words to allocate is in a1.
|
||||
li a2, 4 # Word size in bytes
|
||||
mul a2, a1, a2 # Calculate number of bytes to allocate
|
||||
add a2, gp, a2 # Estimate where GP will move
|
||||
bgeu a2, s11, alloc2_15 # Go to OOM handler if too large
|
||||
lw t0, @.__obj_size__(a0) # Get size of object in words
|
||||
mv t2, a0 # Initialize src ptr
|
||||
mv t3, gp # Initialize dest ptr
|
||||
alloc2_16: # Copy-loop header
|
||||
lw t1, 0(t2) # Load next word from src
|
||||
sw t1, 0(t3) # Store next word to dest
|
||||
addi t2, t2, 4 # Increment src
|
||||
addi t3, t3, 4 # Increment dest
|
||||
addi t0, t0, -1 # Decrement counter
|
||||
bne t0, zero, alloc2_16 # Loop if more words left to copy
|
||||
mv a0, gp # Save new object's address to return
|
||||
sw a1, @.__obj_size__(a0) # Set size of new object in words
|
||||
# (same as requested size)
|
||||
mv gp, a2 # Set next free slot in the heap
|
||||
jr ra # Return to caller
|
||||
alloc2_15: # OOM handler
|
||||
li a0, @error_oom # Exit code for: Out of memory
|
||||
la a1, const_10 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl abort
|
||||
abort:
|
||||
# Runtime support function abort (does not return).
|
||||
mv t0, a0 # Save exit code in temp
|
||||
li a0, @print_string # Code for print_string ecall
|
||||
ecall # Print error message in a1
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for print_char ecall
|
||||
ecall # Print newline
|
||||
mv a1, t0 # Move exit code to a1
|
||||
li a0, @exit2 # Code for exit2 ecall
|
||||
ecall # Exit with code
|
||||
abort_17: # Infinite loop
|
||||
j abort_17 # Prevent fallthrough
|
||||
|
||||
.globl heap.init
|
||||
heap.init:
|
||||
# Runtime support function heap.init.
|
||||
mv a1, a0 # Move requested size to A1
|
||||
li a0, @sbrk # Code for ecall: sbrk
|
||||
ecall # Request A1 bytes
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl concat
|
||||
concat:
|
||||
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw fp, 24(sp)
|
||||
addi fp, sp, 32
|
||||
sw s1, -12(fp)
|
||||
sw s2, -16(fp)
|
||||
sw s3, -20(fp)
|
||||
sw s4, -24(fp)
|
||||
sw s5, -28(fp)
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
beqz t0, concat_none
|
||||
beqz t1, concat_none
|
||||
lw t0, @.__len__(t0)
|
||||
lw t1, @.__len__(t1)
|
||||
add s5, t0, t1
|
||||
addi a1, s5, @listHeaderWords
|
||||
la a0, $.list$prototype
|
||||
jal alloc2
|
||||
sw s5, @.__len__(a0)
|
||||
mv s5, a0
|
||||
addi s3, s5, @.__elts__
|
||||
lw s1, 4(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 12(fp)
|
||||
concat_1:
|
||||
beqz s2, concat_2
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_1
|
||||
concat_2:
|
||||
lw s1, 0(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 8(fp)
|
||||
concat_3:
|
||||
beqz s2, concat_4
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_3
|
||||
concat_4:
|
||||
mv a0, s5
|
||||
lw s1, -12(fp)
|
||||
lw s2, -16(fp)
|
||||
lw s3, -20(fp)
|
||||
lw s4, -24(fp)
|
||||
lw s5, -28(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 32
|
||||
jr ra
|
||||
concat_none:
|
||||
j error.None
|
||||
|
||||
|
||||
.globl conslist
|
||||
conslist:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 0(fp)
|
||||
la a0, $.list$prototype
|
||||
beqz a1, conslist_done
|
||||
addi a1, a1, @listHeaderWords
|
||||
jal alloc2
|
||||
lw t0, 0(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
slli t1, t0, 2
|
||||
add t1, t1, fp
|
||||
addi t2, a0, @.__elts__
|
||||
conslist_1:
|
||||
lw t3, 0(t1)
|
||||
sw t3, 0(t2)
|
||||
addi t1, t1, -4
|
||||
addi t2, t2, 4
|
||||
addi t0, t0, -1
|
||||
bnez t0, conslist_1
|
||||
conslist_done:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strcat
|
||||
strcat:
|
||||
|
||||
addi sp, sp, -12
|
||||
sw ra, 8(sp)
|
||||
sw fp, 4(sp)
|
||||
addi fp, sp, 12
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
lw t0, @.__len__(t0)
|
||||
beqz t0, strcat_4
|
||||
lw t1, @.__len__(t1)
|
||||
beqz t1, strcat_5
|
||||
add t1, t0, t1
|
||||
sw t1, -12(fp)
|
||||
addi t1, t1, 4
|
||||
srli t1, t1, 2
|
||||
addi a1, t1, @listHeaderWords
|
||||
la a0, $str$prototype
|
||||
jal alloc2
|
||||
lw t0, -12(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
addi t2, a0, 16
|
||||
lw t0, 4(fp)
|
||||
lw t1, @.__len__(t0)
|
||||
addi t0, t0, @.__str__
|
||||
strcat_1:
|
||||
beqz t1, strcat_2
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_1
|
||||
strcat_2:
|
||||
lw t0, 0(fp)
|
||||
lw t1, 12(t0)
|
||||
addi t0, t0, 16
|
||||
strcat_3:
|
||||
beqz t1, strcat_6
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_3
|
||||
strcat_4:
|
||||
lw a0, 0(fp)
|
||||
j strcat_7
|
||||
strcat_5:
|
||||
lw a0, 4(fp)
|
||||
j strcat_7
|
||||
strcat_6:
|
||||
sb zero, 0(t2)
|
||||
strcat_7:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 12
|
||||
jr ra
|
||||
|
||||
|
||||
.globl streql
|
||||
streql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, streql_no
|
||||
streql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, streql_no
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, streql_1
|
||||
li a0, 1
|
||||
j streql_end
|
||||
streql_no:
|
||||
xor a0, a0, a0
|
||||
streql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strneql
|
||||
strneql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, strneql_yes
|
||||
strneql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, strneql_yes
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, strneql_1
|
||||
xor a0, a0, a0
|
||||
j strneql_end
|
||||
strneql_yes:
|
||||
li a0, 1
|
||||
strneql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makeint
|
||||
makeint:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw a0, 0(sp)
|
||||
la a0, $int$prototype
|
||||
jal ra, alloc
|
||||
lw t0, 0(sp)
|
||||
sw t0, @.__int__(a0)
|
||||
lw ra, 4(sp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makebool
|
||||
makebool:
|
||||
|
||||
slli a0, a0, 4
|
||||
la t0, @bool.False
|
||||
add a0, a0, t0
|
||||
jr ra
|
||||
|
||||
|
||||
.globl noconv
|
||||
noconv:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl initchars
|
||||
initchars:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl error.None
|
||||
error.None:
|
||||
li a0, 4 # Exit code for: Operation on None
|
||||
la a1, const_11 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.Div
|
||||
error.Div:
|
||||
li a0, 2 # Exit code for: Division by zero
|
||||
la a1, const_12 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.OOB
|
||||
error.OOB:
|
||||
li a0, 3 # Exit code for: Index out of bounds
|
||||
la a1, const_13 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.data
|
||||
|
||||
.globl const_0
|
||||
const_0:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_1
|
||||
const_1:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 1 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_9
|
||||
const_9:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "end g" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_12
|
||||
const_12:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Division by zero" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_7
|
||||
const_7:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 7 # Constant value of attribute: __len__
|
||||
.string "start g" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_5
|
||||
const_5:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 7 # Constant value of attribute: __len__
|
||||
.string "start f" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_6
|
||||
const_6:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "end f" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_10
|
||||
const_10:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 8 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 13 # Constant value of attribute: __len__
|
||||
.string "Out of memory" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_13
|
||||
const_13:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 19 # Constant value of attribute: __len__
|
||||
.string "Index out of bounds" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_8
|
||||
const_8:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 5 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 1 # Constant value of attribute: __len__
|
||||
.string "h" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_3
|
||||
const_3:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 4 # Constant value of attribute: __len__
|
||||
.string "True" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_11
|
||||
const_11:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 17 # Constant value of attribute: __len__
|
||||
.string "Operation on None" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_2
|
||||
const_2:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Invalid argument" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_4
|
||||
const_4:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "False" # Constant value of attribute: __str__
|
||||
.align 2
|
@ -0,0 +1,673 @@
|
||||
.equiv @sbrk, 9
|
||||
.equiv @print_string, 4
|
||||
.equiv @print_char, 11
|
||||
.equiv @print_int, 1
|
||||
.equiv @exit2, 17
|
||||
.equiv @read_string, 8
|
||||
.equiv @fill_line_buffer, 18
|
||||
.equiv @.__obj_size__, 4
|
||||
.equiv @.__len__, 12
|
||||
.equiv @.__int__, 12
|
||||
.equiv @.__bool__, 12
|
||||
.equiv @.__str__, 16
|
||||
.equiv @.__elts__, 16
|
||||
.equiv @error_div_zero, 2
|
||||
.equiv @error_arg, 1
|
||||
.equiv @error_oob, 3
|
||||
.equiv @error_none, 4
|
||||
.equiv @error_oom, 5
|
||||
.equiv @error_nyi, 6
|
||||
.equiv @listHeaderWords, 4
|
||||
.equiv @strHeaderWords, 4
|
||||
.equiv @bool.True, const_1
|
||||
.equiv @bool.False, const_0
|
||||
|
||||
.data
|
||||
|
||||
.globl $object$prototype
|
||||
$object$prototype:
|
||||
.word 0 # Type tag for class: object
|
||||
.word 3 # Object size
|
||||
.word $object$dispatchTable # Pointer to dispatch table
|
||||
.align 2
|
||||
|
||||
.globl $int$prototype
|
||||
$int$prototype:
|
||||
.word 1 # Type tag for class: int
|
||||
.word 4 # Object size
|
||||
.word $int$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __int__
|
||||
.align 2
|
||||
|
||||
.globl $bool$prototype
|
||||
$bool$prototype:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl $str$prototype
|
||||
$str$prototype:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 5 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.word 0 # Initial value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl $.list$prototype
|
||||
$.list$prototype:
|
||||
.word -1 # Type tag for class: .list
|
||||
.word 4 # Object size
|
||||
.word 0 # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.align 2
|
||||
|
||||
.globl $object$dispatchTable
|
||||
$object$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: object.__init__
|
||||
|
||||
.globl $int$dispatchTable
|
||||
$int$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: int.__init__
|
||||
|
||||
.globl $bool$dispatchTable
|
||||
$bool$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: bool.__init__
|
||||
|
||||
.globl $str$dispatchTable
|
||||
$str$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: str.__init__
|
||||
|
||||
.text
|
||||
|
||||
.globl main
|
||||
main:
|
||||
lui a0, 8192 # Initialize heap size (in multiples of 4KB)
|
||||
add s11, s11, a0 # Save heap size
|
||||
jal heap.init # Call heap.init routine
|
||||
mv gp, a0 # Initialize heap pointer
|
||||
mv s10, gp # Set beginning of heap
|
||||
add s11, s10, s11 # Set end of heap (= start of heap + heap size)
|
||||
mv ra, zero # No normal return from main program.
|
||||
mv fp, zero # No preceding frame.
|
||||
addi sp, sp, -@..main.size # Reserve space for stack frame.
|
||||
sw ra, @..main.size-4(sp) # return address
|
||||
sw fp, @..main.size-8(sp) # control link
|
||||
addi fp, sp, @..main.size # New fp is at old SP.
|
||||
jal initchars # Initialize one-character strings.
|
||||
li a0, 42 # Load integer literal 42
|
||||
sw a0, -20(fp) # Push on stack slot 5
|
||||
li a0, 0 # Load integer literal 0
|
||||
lw t0, -20(fp) # Pop stack slot 5
|
||||
bnez a0, label_1 # Ensure non-zero divisor
|
||||
j error.Div # Go to error handler
|
||||
label_1: # Divisor is non-zero
|
||||
xor t2, t0, a0 # Check for same sign
|
||||
bltz t2, label_3 # If !=, need to adjust left operand
|
||||
div a0, t0, a0 # Operator //
|
||||
j label_2
|
||||
label_3: # Operands have differing signs
|
||||
slt t2, zero, a0 # tmp = 1 if right > 0 else 0
|
||||
add t2, t2, t2 # tmp *= 2
|
||||
addi t2, t2, -1 # tmp = 1 if right>=0 else -1
|
||||
add t2, t0, t2 # Adjust left operand
|
||||
div t2, t2, a0 # Adjusted division, toward 0
|
||||
addi a0, t2, -1 # Complete division when signs !=
|
||||
label_2: # End of //
|
||||
jal makeint # Box integer
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
.equiv @..main.size, 32
|
||||
label_0: # End of program
|
||||
li a0, 10 # Code for ecall: exit
|
||||
ecall
|
||||
|
||||
.globl $object.__init__
|
||||
$object.__init__:
|
||||
# Init method for type object.
|
||||
mv a0, zero # `None` constant
|
||||
jr ra # Return
|
||||
|
||||
.globl $print
|
||||
$print:
|
||||
# Function print
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, print_6 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 1 # Load type tag of `int`
|
||||
beq t0, t1, print_7 # Go to print(int)
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, print_8 # Go to print(str)
|
||||
li t1, 2 # Load type tag of `bool`
|
||||
beq t0, t1, print_9 # Go to print(bool)
|
||||
print_6: # Invalid argument
|
||||
li a0, 1 # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
# Printing bools
|
||||
print_9: # Print bool object in A0
|
||||
lw a0, @.__bool__(a0) # Load attribute __bool__
|
||||
beq a0, zero, print_10 # Go to: print(False)
|
||||
la a0, const_3 # String representation: True
|
||||
j print_8 # Go to: print(str)
|
||||
print_10: # Print False object in A0
|
||||
la a0, const_4 # String representation: False
|
||||
j print_8 # Go to: print(str)
|
||||
|
||||
# Printing strs.
|
||||
print_8: # Print str object in A0
|
||||
addi a1, a0, @.__str__ # Load address of attribute __str__
|
||||
j print_11 # Print the null-terminated string is now in A1
|
||||
mv a0, zero # Load None
|
||||
j print_5 # Go to return
|
||||
print_11: # Print null-terminated string in A1
|
||||
li a0, @print_string # Code for ecall: print_string
|
||||
ecall # Print string
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
j print_5 # Go to return
|
||||
|
||||
# Printing ints.
|
||||
print_7: # Print int object in A0
|
||||
lw a1, @.__int__(a0) # Load attribute __int__
|
||||
li a0, @print_int # Code for ecall: print_int
|
||||
ecall # Print integer
|
||||
li a1, 10 # Load newline character
|
||||
li a0, 11 # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
|
||||
print_5: # End of function
|
||||
mv a0, zero # Load None
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $len
|
||||
$len:
|
||||
# Function len
|
||||
# We do not save/restore fp/ra for this function
|
||||
# because we know that it does not use the stack or does not
|
||||
# call other functions.
|
||||
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, len_12 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, len_13 # Go to len(str)
|
||||
li t1, -1 # Load type tag for list objects
|
||||
beq t0, t1, len_13 # Go to len(list)
|
||||
len_12: # Invalid argument
|
||||
li a0, @error_arg # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
len_13: # Get length of string
|
||||
lw a0, @.__len__(a0) # Load attribute: __len__
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $input
|
||||
$input:
|
||||
# Function input
|
||||
addi sp, sp, -16 # Reserve stack
|
||||
sw ra, 12(sp) # Save registers
|
||||
sw fp, 8(sp)
|
||||
sw s1, 4(sp)
|
||||
addi fp, sp, 16 # Set fp
|
||||
|
||||
li a0, @fill_line_buffer # Fill the internal line buffer.
|
||||
ecall
|
||||
bgez a0, input_nonempty # More input found
|
||||
la a0, $str$prototype # EOF: Return empty string.
|
||||
j input_done
|
||||
|
||||
input_nonempty:
|
||||
mv s1, a0
|
||||
addi t0, s1, 5 # Compute bytes for string (+NL+NUL),
|
||||
addi t0, t0, @.__str__ # Including header.
|
||||
srli a1, t0, 2 # Convert to words.
|
||||
la a0, $str$prototype # Load address of string prototype.
|
||||
jal ra, alloc2 # Allocate string.
|
||||
sw s1, @.__len__(a0) # Store string length.
|
||||
mv a2, s1 # Pass length.
|
||||
mv s1, a0 # Save string object address.
|
||||
addi a1, a0, @.__str__ # Pass address of string data.
|
||||
li a0, @read_string # ecall to read from internal buffer.
|
||||
ecall
|
||||
addi a0, a0, 1 # Actual length (including NL).
|
||||
sw a0, @.__len__(s1) # Store actual length.
|
||||
add t0, a0, s1
|
||||
li t1, 10 # Store newline and null byte
|
||||
sb t1, @.__str__-1(t0)
|
||||
sb zero, @.__str__(t0) # Store null byte at end.
|
||||
mv a0, s1 # Return string object.
|
||||
|
||||
input_done:
|
||||
lw s1, -12(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 16
|
||||
jr ra
|
||||
|
||||
.globl alloc
|
||||
alloc:
|
||||
# Runtime support function alloc.
|
||||
# Prototype address is in a0.
|
||||
lw a1, 4(a0) # Get size of object in words
|
||||
j alloc2 # Allocate object with exact size
|
||||
|
||||
.globl alloc2
|
||||
alloc2:
|
||||
# Runtime support function alloc2 (realloc).
|
||||
# Prototype address is in a0.
|
||||
# Number of words to allocate is in a1.
|
||||
li a2, 4 # Word size in bytes
|
||||
mul a2, a1, a2 # Calculate number of bytes to allocate
|
||||
add a2, gp, a2 # Estimate where GP will move
|
||||
bgeu a2, s11, alloc2_15 # Go to OOM handler if too large
|
||||
lw t0, @.__obj_size__(a0) # Get size of object in words
|
||||
mv t2, a0 # Initialize src ptr
|
||||
mv t3, gp # Initialize dest ptr
|
||||
alloc2_16: # Copy-loop header
|
||||
lw t1, 0(t2) # Load next word from src
|
||||
sw t1, 0(t3) # Store next word to dest
|
||||
addi t2, t2, 4 # Increment src
|
||||
addi t3, t3, 4 # Increment dest
|
||||
addi t0, t0, -1 # Decrement counter
|
||||
bne t0, zero, alloc2_16 # Loop if more words left to copy
|
||||
mv a0, gp # Save new object's address to return
|
||||
sw a1, @.__obj_size__(a0) # Set size of new object in words
|
||||
# (same as requested size)
|
||||
mv gp, a2 # Set next free slot in the heap
|
||||
jr ra # Return to caller
|
||||
alloc2_15: # OOM handler
|
||||
li a0, @error_oom # Exit code for: Out of memory
|
||||
la a1, const_5 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl abort
|
||||
abort:
|
||||
# Runtime support function abort (does not return).
|
||||
mv t0, a0 # Save exit code in temp
|
||||
li a0, @print_string # Code for print_string ecall
|
||||
ecall # Print error message in a1
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for print_char ecall
|
||||
ecall # Print newline
|
||||
mv a1, t0 # Move exit code to a1
|
||||
li a0, @exit2 # Code for exit2 ecall
|
||||
ecall # Exit with code
|
||||
abort_17: # Infinite loop
|
||||
j abort_17 # Prevent fallthrough
|
||||
|
||||
.globl heap.init
|
||||
heap.init:
|
||||
# Runtime support function heap.init.
|
||||
mv a1, a0 # Move requested size to A1
|
||||
li a0, @sbrk # Code for ecall: sbrk
|
||||
ecall # Request A1 bytes
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl concat
|
||||
concat:
|
||||
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw fp, 24(sp)
|
||||
addi fp, sp, 32
|
||||
sw s1, -12(fp)
|
||||
sw s2, -16(fp)
|
||||
sw s3, -20(fp)
|
||||
sw s4, -24(fp)
|
||||
sw s5, -28(fp)
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
beqz t0, concat_none
|
||||
beqz t1, concat_none
|
||||
lw t0, @.__len__(t0)
|
||||
lw t1, @.__len__(t1)
|
||||
add s5, t0, t1
|
||||
addi a1, s5, @listHeaderWords
|
||||
la a0, $.list$prototype
|
||||
jal alloc2
|
||||
sw s5, @.__len__(a0)
|
||||
mv s5, a0
|
||||
addi s3, s5, @.__elts__
|
||||
lw s1, 4(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 12(fp)
|
||||
concat_1:
|
||||
beqz s2, concat_2
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_1
|
||||
concat_2:
|
||||
lw s1, 0(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 8(fp)
|
||||
concat_3:
|
||||
beqz s2, concat_4
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_3
|
||||
concat_4:
|
||||
mv a0, s5
|
||||
lw s1, -12(fp)
|
||||
lw s2, -16(fp)
|
||||
lw s3, -20(fp)
|
||||
lw s4, -24(fp)
|
||||
lw s5, -28(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 32
|
||||
jr ra
|
||||
concat_none:
|
||||
j error.None
|
||||
|
||||
|
||||
.globl conslist
|
||||
conslist:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 0(fp)
|
||||
la a0, $.list$prototype
|
||||
beqz a1, conslist_done
|
||||
addi a1, a1, @listHeaderWords
|
||||
jal alloc2
|
||||
lw t0, 0(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
slli t1, t0, 2
|
||||
add t1, t1, fp
|
||||
addi t2, a0, @.__elts__
|
||||
conslist_1:
|
||||
lw t3, 0(t1)
|
||||
sw t3, 0(t2)
|
||||
addi t1, t1, -4
|
||||
addi t2, t2, 4
|
||||
addi t0, t0, -1
|
||||
bnez t0, conslist_1
|
||||
conslist_done:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strcat
|
||||
strcat:
|
||||
|
||||
addi sp, sp, -12
|
||||
sw ra, 8(sp)
|
||||
sw fp, 4(sp)
|
||||
addi fp, sp, 12
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
lw t0, @.__len__(t0)
|
||||
beqz t0, strcat_4
|
||||
lw t1, @.__len__(t1)
|
||||
beqz t1, strcat_5
|
||||
add t1, t0, t1
|
||||
sw t1, -12(fp)
|
||||
addi t1, t1, 4
|
||||
srli t1, t1, 2
|
||||
addi a1, t1, @listHeaderWords
|
||||
la a0, $str$prototype
|
||||
jal alloc2
|
||||
lw t0, -12(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
addi t2, a0, 16
|
||||
lw t0, 4(fp)
|
||||
lw t1, @.__len__(t0)
|
||||
addi t0, t0, @.__str__
|
||||
strcat_1:
|
||||
beqz t1, strcat_2
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_1
|
||||
strcat_2:
|
||||
lw t0, 0(fp)
|
||||
lw t1, 12(t0)
|
||||
addi t0, t0, 16
|
||||
strcat_3:
|
||||
beqz t1, strcat_6
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_3
|
||||
strcat_4:
|
||||
lw a0, 0(fp)
|
||||
j strcat_7
|
||||
strcat_5:
|
||||
lw a0, 4(fp)
|
||||
j strcat_7
|
||||
strcat_6:
|
||||
sb zero, 0(t2)
|
||||
strcat_7:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 12
|
||||
jr ra
|
||||
|
||||
|
||||
.globl streql
|
||||
streql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, streql_no
|
||||
streql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, streql_no
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, streql_1
|
||||
li a0, 1
|
||||
j streql_end
|
||||
streql_no:
|
||||
xor a0, a0, a0
|
||||
streql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strneql
|
||||
strneql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, strneql_yes
|
||||
strneql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, strneql_yes
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, strneql_1
|
||||
xor a0, a0, a0
|
||||
j strneql_end
|
||||
strneql_yes:
|
||||
li a0, 1
|
||||
strneql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makeint
|
||||
makeint:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw a0, 0(sp)
|
||||
la a0, $int$prototype
|
||||
jal ra, alloc
|
||||
lw t0, 0(sp)
|
||||
sw t0, @.__int__(a0)
|
||||
lw ra, 4(sp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makebool
|
||||
makebool:
|
||||
|
||||
slli a0, a0, 4
|
||||
la t0, @bool.False
|
||||
add a0, a0, t0
|
||||
jr ra
|
||||
|
||||
|
||||
.globl noconv
|
||||
noconv:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl initchars
|
||||
initchars:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl error.None
|
||||
error.None:
|
||||
li a0, 4 # Exit code for: Operation on None
|
||||
la a1, const_6 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.Div
|
||||
error.Div:
|
||||
li a0, 2 # Exit code for: Division by zero
|
||||
la a1, const_7 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.OOB
|
||||
error.OOB:
|
||||
li a0, 3 # Exit code for: Index out of bounds
|
||||
la a1, const_8 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.data
|
||||
|
||||
.globl const_0
|
||||
const_0:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_1
|
||||
const_1:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 1 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_7
|
||||
const_7:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Division by zero" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_5
|
||||
const_5:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 8 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 13 # Constant value of attribute: __len__
|
||||
.string "Out of memory" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_8
|
||||
const_8:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 19 # Constant value of attribute: __len__
|
||||
.string "Index out of bounds" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_3
|
||||
const_3:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 4 # Constant value of attribute: __len__
|
||||
.string "True" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_6
|
||||
const_6:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 17 # Constant value of attribute: __len__
|
||||
.string "Operation on None" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_2
|
||||
const_2:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Invalid argument" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_4
|
||||
const_4:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "False" # Constant value of attribute: __str__
|
||||
.align 2
|
@ -0,0 +1,654 @@
|
||||
.equiv @sbrk, 9
|
||||
.equiv @print_string, 4
|
||||
.equiv @print_char, 11
|
||||
.equiv @print_int, 1
|
||||
.equiv @exit2, 17
|
||||
.equiv @read_string, 8
|
||||
.equiv @fill_line_buffer, 18
|
||||
.equiv @.__obj_size__, 4
|
||||
.equiv @.__len__, 12
|
||||
.equiv @.__int__, 12
|
||||
.equiv @.__bool__, 12
|
||||
.equiv @.__str__, 16
|
||||
.equiv @.__elts__, 16
|
||||
.equiv @error_div_zero, 2
|
||||
.equiv @error_arg, 1
|
||||
.equiv @error_oob, 3
|
||||
.equiv @error_none, 4
|
||||
.equiv @error_oom, 5
|
||||
.equiv @error_nyi, 6
|
||||
.equiv @listHeaderWords, 4
|
||||
.equiv @strHeaderWords, 4
|
||||
.equiv @bool.True, const_1
|
||||
.equiv @bool.False, const_0
|
||||
|
||||
.data
|
||||
|
||||
.globl $object$prototype
|
||||
$object$prototype:
|
||||
.word 0 # Type tag for class: object
|
||||
.word 3 # Object size
|
||||
.word $object$dispatchTable # Pointer to dispatch table
|
||||
.align 2
|
||||
|
||||
.globl $int$prototype
|
||||
$int$prototype:
|
||||
.word 1 # Type tag for class: int
|
||||
.word 4 # Object size
|
||||
.word $int$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __int__
|
||||
.align 2
|
||||
|
||||
.globl $bool$prototype
|
||||
$bool$prototype:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl $str$prototype
|
||||
$str$prototype:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 5 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.word 0 # Initial value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl $.list$prototype
|
||||
$.list$prototype:
|
||||
.word -1 # Type tag for class: .list
|
||||
.word 4 # Object size
|
||||
.word 0 # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.align 2
|
||||
|
||||
.globl $object$dispatchTable
|
||||
$object$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: object.__init__
|
||||
|
||||
.globl $int$dispatchTable
|
||||
$int$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: int.__init__
|
||||
|
||||
.globl $bool$dispatchTable
|
||||
$bool$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: bool.__init__
|
||||
|
||||
.globl $str$dispatchTable
|
||||
$str$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: str.__init__
|
||||
|
||||
.text
|
||||
|
||||
.globl main
|
||||
main:
|
||||
lui a0, 8192 # Initialize heap size (in multiples of 4KB)
|
||||
add s11, s11, a0 # Save heap size
|
||||
jal heap.init # Call heap.init routine
|
||||
mv gp, a0 # Initialize heap pointer
|
||||
mv s10, gp # Set beginning of heap
|
||||
add s11, s10, s11 # Set end of heap (= start of heap + heap size)
|
||||
mv ra, zero # No normal return from main program.
|
||||
mv fp, zero # No preceding frame.
|
||||
addi sp, sp, -@..main.size # Reserve space for stack frame.
|
||||
sw ra, @..main.size-4(sp) # return address
|
||||
sw fp, @..main.size-8(sp) # control link
|
||||
addi fp, sp, @..main.size # New fp is at old SP.
|
||||
jal initchars # Initialize one-character strings.
|
||||
mv a0, zero # Load None
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
.equiv @..main.size, 16
|
||||
label_0: # End of program
|
||||
li a0, 10 # Code for ecall: exit
|
||||
ecall
|
||||
|
||||
.globl $object.__init__
|
||||
$object.__init__:
|
||||
# Init method for type object.
|
||||
mv a0, zero # `None` constant
|
||||
jr ra # Return
|
||||
|
||||
.globl $print
|
||||
$print:
|
||||
# Function print
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, print_6 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 1 # Load type tag of `int`
|
||||
beq t0, t1, print_7 # Go to print(int)
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, print_8 # Go to print(str)
|
||||
li t1, 2 # Load type tag of `bool`
|
||||
beq t0, t1, print_9 # Go to print(bool)
|
||||
print_6: # Invalid argument
|
||||
li a0, 1 # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
# Printing bools
|
||||
print_9: # Print bool object in A0
|
||||
lw a0, @.__bool__(a0) # Load attribute __bool__
|
||||
beq a0, zero, print_10 # Go to: print(False)
|
||||
la a0, const_3 # String representation: True
|
||||
j print_8 # Go to: print(str)
|
||||
print_10: # Print False object in A0
|
||||
la a0, const_4 # String representation: False
|
||||
j print_8 # Go to: print(str)
|
||||
|
||||
# Printing strs.
|
||||
print_8: # Print str object in A0
|
||||
addi a1, a0, @.__str__ # Load address of attribute __str__
|
||||
j print_11 # Print the null-terminated string is now in A1
|
||||
mv a0, zero # Load None
|
||||
j print_5 # Go to return
|
||||
print_11: # Print null-terminated string in A1
|
||||
li a0, @print_string # Code for ecall: print_string
|
||||
ecall # Print string
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
j print_5 # Go to return
|
||||
|
||||
# Printing ints.
|
||||
print_7: # Print int object in A0
|
||||
lw a1, @.__int__(a0) # Load attribute __int__
|
||||
li a0, @print_int # Code for ecall: print_int
|
||||
ecall # Print integer
|
||||
li a1, 10 # Load newline character
|
||||
li a0, 11 # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
|
||||
print_5: # End of function
|
||||
mv a0, zero # Load None
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $len
|
||||
$len:
|
||||
# Function len
|
||||
# We do not save/restore fp/ra for this function
|
||||
# because we know that it does not use the stack or does not
|
||||
# call other functions.
|
||||
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, len_12 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, len_13 # Go to len(str)
|
||||
li t1, -1 # Load type tag for list objects
|
||||
beq t0, t1, len_13 # Go to len(list)
|
||||
len_12: # Invalid argument
|
||||
li a0, @error_arg # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
len_13: # Get length of string
|
||||
lw a0, @.__len__(a0) # Load attribute: __len__
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $input
|
||||
$input:
|
||||
# Function input
|
||||
addi sp, sp, -16 # Reserve stack
|
||||
sw ra, 12(sp) # Save registers
|
||||
sw fp, 8(sp)
|
||||
sw s1, 4(sp)
|
||||
addi fp, sp, 16 # Set fp
|
||||
|
||||
li a0, @fill_line_buffer # Fill the internal line buffer.
|
||||
ecall
|
||||
bgez a0, input_nonempty # More input found
|
||||
la a0, $str$prototype # EOF: Return empty string.
|
||||
j input_done
|
||||
|
||||
input_nonempty:
|
||||
mv s1, a0
|
||||
addi t0, s1, 5 # Compute bytes for string (+NL+NUL),
|
||||
addi t0, t0, @.__str__ # Including header.
|
||||
srli a1, t0, 2 # Convert to words.
|
||||
la a0, $str$prototype # Load address of string prototype.
|
||||
jal ra, alloc2 # Allocate string.
|
||||
sw s1, @.__len__(a0) # Store string length.
|
||||
mv a2, s1 # Pass length.
|
||||
mv s1, a0 # Save string object address.
|
||||
addi a1, a0, @.__str__ # Pass address of string data.
|
||||
li a0, @read_string # ecall to read from internal buffer.
|
||||
ecall
|
||||
addi a0, a0, 1 # Actual length (including NL).
|
||||
sw a0, @.__len__(s1) # Store actual length.
|
||||
add t0, a0, s1
|
||||
li t1, 10 # Store newline and null byte
|
||||
sb t1, @.__str__-1(t0)
|
||||
sb zero, @.__str__(t0) # Store null byte at end.
|
||||
mv a0, s1 # Return string object.
|
||||
|
||||
input_done:
|
||||
lw s1, -12(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 16
|
||||
jr ra
|
||||
|
||||
.globl alloc
|
||||
alloc:
|
||||
# Runtime support function alloc.
|
||||
# Prototype address is in a0.
|
||||
lw a1, 4(a0) # Get size of object in words
|
||||
j alloc2 # Allocate object with exact size
|
||||
|
||||
.globl alloc2
|
||||
alloc2:
|
||||
# Runtime support function alloc2 (realloc).
|
||||
# Prototype address is in a0.
|
||||
# Number of words to allocate is in a1.
|
||||
li a2, 4 # Word size in bytes
|
||||
mul a2, a1, a2 # Calculate number of bytes to allocate
|
||||
add a2, gp, a2 # Estimate where GP will move
|
||||
bgeu a2, s11, alloc2_15 # Go to OOM handler if too large
|
||||
lw t0, @.__obj_size__(a0) # Get size of object in words
|
||||
mv t2, a0 # Initialize src ptr
|
||||
mv t3, gp # Initialize dest ptr
|
||||
alloc2_16: # Copy-loop header
|
||||
lw t1, 0(t2) # Load next word from src
|
||||
sw t1, 0(t3) # Store next word to dest
|
||||
addi t2, t2, 4 # Increment src
|
||||
addi t3, t3, 4 # Increment dest
|
||||
addi t0, t0, -1 # Decrement counter
|
||||
bne t0, zero, alloc2_16 # Loop if more words left to copy
|
||||
mv a0, gp # Save new object's address to return
|
||||
sw a1, @.__obj_size__(a0) # Set size of new object in words
|
||||
# (same as requested size)
|
||||
mv gp, a2 # Set next free slot in the heap
|
||||
jr ra # Return to caller
|
||||
alloc2_15: # OOM handler
|
||||
li a0, @error_oom # Exit code for: Out of memory
|
||||
la a1, const_5 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl abort
|
||||
abort:
|
||||
# Runtime support function abort (does not return).
|
||||
mv t0, a0 # Save exit code in temp
|
||||
li a0, @print_string # Code for print_string ecall
|
||||
ecall # Print error message in a1
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for print_char ecall
|
||||
ecall # Print newline
|
||||
mv a1, t0 # Move exit code to a1
|
||||
li a0, @exit2 # Code for exit2 ecall
|
||||
ecall # Exit with code
|
||||
abort_17: # Infinite loop
|
||||
j abort_17 # Prevent fallthrough
|
||||
|
||||
.globl heap.init
|
||||
heap.init:
|
||||
# Runtime support function heap.init.
|
||||
mv a1, a0 # Move requested size to A1
|
||||
li a0, @sbrk # Code for ecall: sbrk
|
||||
ecall # Request A1 bytes
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl concat
|
||||
concat:
|
||||
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw fp, 24(sp)
|
||||
addi fp, sp, 32
|
||||
sw s1, -12(fp)
|
||||
sw s2, -16(fp)
|
||||
sw s3, -20(fp)
|
||||
sw s4, -24(fp)
|
||||
sw s5, -28(fp)
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
beqz t0, concat_none
|
||||
beqz t1, concat_none
|
||||
lw t0, @.__len__(t0)
|
||||
lw t1, @.__len__(t1)
|
||||
add s5, t0, t1
|
||||
addi a1, s5, @listHeaderWords
|
||||
la a0, $.list$prototype
|
||||
jal alloc2
|
||||
sw s5, @.__len__(a0)
|
||||
mv s5, a0
|
||||
addi s3, s5, @.__elts__
|
||||
lw s1, 4(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 12(fp)
|
||||
concat_1:
|
||||
beqz s2, concat_2
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_1
|
||||
concat_2:
|
||||
lw s1, 0(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 8(fp)
|
||||
concat_3:
|
||||
beqz s2, concat_4
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_3
|
||||
concat_4:
|
||||
mv a0, s5
|
||||
lw s1, -12(fp)
|
||||
lw s2, -16(fp)
|
||||
lw s3, -20(fp)
|
||||
lw s4, -24(fp)
|
||||
lw s5, -28(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 32
|
||||
jr ra
|
||||
concat_none:
|
||||
j error.None
|
||||
|
||||
|
||||
.globl conslist
|
||||
conslist:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 0(fp)
|
||||
la a0, $.list$prototype
|
||||
beqz a1, conslist_done
|
||||
addi a1, a1, @listHeaderWords
|
||||
jal alloc2
|
||||
lw t0, 0(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
slli t1, t0, 2
|
||||
add t1, t1, fp
|
||||
addi t2, a0, @.__elts__
|
||||
conslist_1:
|
||||
lw t3, 0(t1)
|
||||
sw t3, 0(t2)
|
||||
addi t1, t1, -4
|
||||
addi t2, t2, 4
|
||||
addi t0, t0, -1
|
||||
bnez t0, conslist_1
|
||||
conslist_done:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strcat
|
||||
strcat:
|
||||
|
||||
addi sp, sp, -12
|
||||
sw ra, 8(sp)
|
||||
sw fp, 4(sp)
|
||||
addi fp, sp, 12
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
lw t0, @.__len__(t0)
|
||||
beqz t0, strcat_4
|
||||
lw t1, @.__len__(t1)
|
||||
beqz t1, strcat_5
|
||||
add t1, t0, t1
|
||||
sw t1, -12(fp)
|
||||
addi t1, t1, 4
|
||||
srli t1, t1, 2
|
||||
addi a1, t1, @listHeaderWords
|
||||
la a0, $str$prototype
|
||||
jal alloc2
|
||||
lw t0, -12(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
addi t2, a0, 16
|
||||
lw t0, 4(fp)
|
||||
lw t1, @.__len__(t0)
|
||||
addi t0, t0, @.__str__
|
||||
strcat_1:
|
||||
beqz t1, strcat_2
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_1
|
||||
strcat_2:
|
||||
lw t0, 0(fp)
|
||||
lw t1, 12(t0)
|
||||
addi t0, t0, 16
|
||||
strcat_3:
|
||||
beqz t1, strcat_6
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_3
|
||||
strcat_4:
|
||||
lw a0, 0(fp)
|
||||
j strcat_7
|
||||
strcat_5:
|
||||
lw a0, 4(fp)
|
||||
j strcat_7
|
||||
strcat_6:
|
||||
sb zero, 0(t2)
|
||||
strcat_7:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 12
|
||||
jr ra
|
||||
|
||||
|
||||
.globl streql
|
||||
streql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, streql_no
|
||||
streql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, streql_no
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, streql_1
|
||||
li a0, 1
|
||||
j streql_end
|
||||
streql_no:
|
||||
xor a0, a0, a0
|
||||
streql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strneql
|
||||
strneql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, strneql_yes
|
||||
strneql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, strneql_yes
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, strneql_1
|
||||
xor a0, a0, a0
|
||||
j strneql_end
|
||||
strneql_yes:
|
||||
li a0, 1
|
||||
strneql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makeint
|
||||
makeint:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw a0, 0(sp)
|
||||
la a0, $int$prototype
|
||||
jal ra, alloc
|
||||
lw t0, 0(sp)
|
||||
sw t0, @.__int__(a0)
|
||||
lw ra, 4(sp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makebool
|
||||
makebool:
|
||||
|
||||
slli a0, a0, 4
|
||||
la t0, @bool.False
|
||||
add a0, a0, t0
|
||||
jr ra
|
||||
|
||||
|
||||
.globl noconv
|
||||
noconv:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl initchars
|
||||
initchars:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl error.None
|
||||
error.None:
|
||||
li a0, 4 # Exit code for: Operation on None
|
||||
la a1, const_6 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.Div
|
||||
error.Div:
|
||||
li a0, 2 # Exit code for: Division by zero
|
||||
la a1, const_7 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.OOB
|
||||
error.OOB:
|
||||
li a0, 3 # Exit code for: Index out of bounds
|
||||
la a1, const_8 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.data
|
||||
|
||||
.globl const_0
|
||||
const_0:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_1
|
||||
const_1:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 1 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_7
|
||||
const_7:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Division by zero" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_5
|
||||
const_5:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 8 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 13 # Constant value of attribute: __len__
|
||||
.string "Out of memory" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_8
|
||||
const_8:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 19 # Constant value of attribute: __len__
|
||||
.string "Index out of bounds" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_3
|
||||
const_3:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 4 # Constant value of attribute: __len__
|
||||
.string "True" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_6
|
||||
const_6:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 17 # Constant value of attribute: __len__
|
||||
.string "Operation on None" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_2
|
||||
const_2:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Invalid argument" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_4
|
||||
const_4:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "False" # Constant value of attribute: __str__
|
||||
.align 2
|
@ -0,0 +1,670 @@
|
||||
.equiv @sbrk, 9
|
||||
.equiv @print_string, 4
|
||||
.equiv @print_char, 11
|
||||
.equiv @print_int, 1
|
||||
.equiv @exit2, 17
|
||||
.equiv @read_string, 8
|
||||
.equiv @fill_line_buffer, 18
|
||||
.equiv @.__obj_size__, 4
|
||||
.equiv @.__len__, 12
|
||||
.equiv @.__int__, 12
|
||||
.equiv @.__bool__, 12
|
||||
.equiv @.__str__, 16
|
||||
.equiv @.__elts__, 16
|
||||
.equiv @error_div_zero, 2
|
||||
.equiv @error_arg, 1
|
||||
.equiv @error_oob, 3
|
||||
.equiv @error_none, 4
|
||||
.equiv @error_oom, 5
|
||||
.equiv @error_nyi, 6
|
||||
.equiv @listHeaderWords, 4
|
||||
.equiv @strHeaderWords, 4
|
||||
.equiv @bool.True, const_1
|
||||
.equiv @bool.False, const_0
|
||||
|
||||
.data
|
||||
|
||||
.globl $object$prototype
|
||||
$object$prototype:
|
||||
.word 0 # Type tag for class: object
|
||||
.word 3 # Object size
|
||||
.word $object$dispatchTable # Pointer to dispatch table
|
||||
.align 2
|
||||
|
||||
.globl $int$prototype
|
||||
$int$prototype:
|
||||
.word 1 # Type tag for class: int
|
||||
.word 4 # Object size
|
||||
.word $int$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __int__
|
||||
.align 2
|
||||
|
||||
.globl $bool$prototype
|
||||
$bool$prototype:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl $str$prototype
|
||||
$str$prototype:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 5 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.word 0 # Initial value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl $.list$prototype
|
||||
$.list$prototype:
|
||||
.word -1 # Type tag for class: .list
|
||||
.word 4 # Object size
|
||||
.word 0 # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.align 2
|
||||
|
||||
.globl $object$dispatchTable
|
||||
$object$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: object.__init__
|
||||
|
||||
.globl $int$dispatchTable
|
||||
$int$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: int.__init__
|
||||
|
||||
.globl $bool$dispatchTable
|
||||
$bool$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: bool.__init__
|
||||
|
||||
.globl $str$dispatchTable
|
||||
$str$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: str.__init__
|
||||
|
||||
.text
|
||||
|
||||
.globl main
|
||||
main:
|
||||
lui a0, 8192 # Initialize heap size (in multiples of 4KB)
|
||||
add s11, s11, a0 # Save heap size
|
||||
jal heap.init # Call heap.init routine
|
||||
mv gp, a0 # Initialize heap pointer
|
||||
mv s10, gp # Set beginning of heap
|
||||
add s11, s10, s11 # Set end of heap (= start of heap + heap size)
|
||||
mv ra, zero # No normal return from main program.
|
||||
mv fp, zero # No preceding frame.
|
||||
addi sp, sp, -@..main.size # Reserve space for stack frame.
|
||||
sw ra, @..main.size-4(sp) # return address
|
||||
sw fp, @..main.size-8(sp) # control link
|
||||
addi fp, sp, @..main.size # New fp is at old SP.
|
||||
jal initchars # Initialize one-character strings.
|
||||
li a0, 42 # Load integer literal 42
|
||||
sw a0, -20(fp) # Push on stack slot 5
|
||||
li a0, 0 # Load integer literal 0
|
||||
lw t0, -20(fp) # Pop stack slot 5
|
||||
bnez a0, label_1 # Ensure non-zero divisor
|
||||
j error.Div # Go to error handler
|
||||
label_1: # Divisor is non-zero
|
||||
rem t2, t0, a0 # Operator rem
|
||||
beqz t2, label_2 # If no remainder, no adjustment
|
||||
xor t3, t2, a0 # Check for differing signs.
|
||||
bgez t3, label_2 # Don't adjust if signs equal.
|
||||
add a0, t2, a0 # Adjust
|
||||
j label_3
|
||||
label_2: # Store result
|
||||
mv a0, t2
|
||||
label_3: # End of %
|
||||
jal makeint # Box integer
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
.equiv @..main.size, 32
|
||||
label_0: # End of program
|
||||
li a0, 10 # Code for ecall: exit
|
||||
ecall
|
||||
|
||||
.globl $object.__init__
|
||||
$object.__init__:
|
||||
# Init method for type object.
|
||||
mv a0, zero # `None` constant
|
||||
jr ra # Return
|
||||
|
||||
.globl $print
|
||||
$print:
|
||||
# Function print
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, print_6 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 1 # Load type tag of `int`
|
||||
beq t0, t1, print_7 # Go to print(int)
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, print_8 # Go to print(str)
|
||||
li t1, 2 # Load type tag of `bool`
|
||||
beq t0, t1, print_9 # Go to print(bool)
|
||||
print_6: # Invalid argument
|
||||
li a0, 1 # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
# Printing bools
|
||||
print_9: # Print bool object in A0
|
||||
lw a0, @.__bool__(a0) # Load attribute __bool__
|
||||
beq a0, zero, print_10 # Go to: print(False)
|
||||
la a0, const_3 # String representation: True
|
||||
j print_8 # Go to: print(str)
|
||||
print_10: # Print False object in A0
|
||||
la a0, const_4 # String representation: False
|
||||
j print_8 # Go to: print(str)
|
||||
|
||||
# Printing strs.
|
||||
print_8: # Print str object in A0
|
||||
addi a1, a0, @.__str__ # Load address of attribute __str__
|
||||
j print_11 # Print the null-terminated string is now in A1
|
||||
mv a0, zero # Load None
|
||||
j print_5 # Go to return
|
||||
print_11: # Print null-terminated string in A1
|
||||
li a0, @print_string # Code for ecall: print_string
|
||||
ecall # Print string
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
j print_5 # Go to return
|
||||
|
||||
# Printing ints.
|
||||
print_7: # Print int object in A0
|
||||
lw a1, @.__int__(a0) # Load attribute __int__
|
||||
li a0, @print_int # Code for ecall: print_int
|
||||
ecall # Print integer
|
||||
li a1, 10 # Load newline character
|
||||
li a0, 11 # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
|
||||
print_5: # End of function
|
||||
mv a0, zero # Load None
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $len
|
||||
$len:
|
||||
# Function len
|
||||
# We do not save/restore fp/ra for this function
|
||||
# because we know that it does not use the stack or does not
|
||||
# call other functions.
|
||||
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, len_12 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, len_13 # Go to len(str)
|
||||
li t1, -1 # Load type tag for list objects
|
||||
beq t0, t1, len_13 # Go to len(list)
|
||||
len_12: # Invalid argument
|
||||
li a0, @error_arg # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
len_13: # Get length of string
|
||||
lw a0, @.__len__(a0) # Load attribute: __len__
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $input
|
||||
$input:
|
||||
# Function input
|
||||
addi sp, sp, -16 # Reserve stack
|
||||
sw ra, 12(sp) # Save registers
|
||||
sw fp, 8(sp)
|
||||
sw s1, 4(sp)
|
||||
addi fp, sp, 16 # Set fp
|
||||
|
||||
li a0, @fill_line_buffer # Fill the internal line buffer.
|
||||
ecall
|
||||
bgez a0, input_nonempty # More input found
|
||||
la a0, $str$prototype # EOF: Return empty string.
|
||||
j input_done
|
||||
|
||||
input_nonempty:
|
||||
mv s1, a0
|
||||
addi t0, s1, 5 # Compute bytes for string (+NL+NUL),
|
||||
addi t0, t0, @.__str__ # Including header.
|
||||
srli a1, t0, 2 # Convert to words.
|
||||
la a0, $str$prototype # Load address of string prototype.
|
||||
jal ra, alloc2 # Allocate string.
|
||||
sw s1, @.__len__(a0) # Store string length.
|
||||
mv a2, s1 # Pass length.
|
||||
mv s1, a0 # Save string object address.
|
||||
addi a1, a0, @.__str__ # Pass address of string data.
|
||||
li a0, @read_string # ecall to read from internal buffer.
|
||||
ecall
|
||||
addi a0, a0, 1 # Actual length (including NL).
|
||||
sw a0, @.__len__(s1) # Store actual length.
|
||||
add t0, a0, s1
|
||||
li t1, 10 # Store newline and null byte
|
||||
sb t1, @.__str__-1(t0)
|
||||
sb zero, @.__str__(t0) # Store null byte at end.
|
||||
mv a0, s1 # Return string object.
|
||||
|
||||
input_done:
|
||||
lw s1, -12(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 16
|
||||
jr ra
|
||||
|
||||
.globl alloc
|
||||
alloc:
|
||||
# Runtime support function alloc.
|
||||
# Prototype address is in a0.
|
||||
lw a1, 4(a0) # Get size of object in words
|
||||
j alloc2 # Allocate object with exact size
|
||||
|
||||
.globl alloc2
|
||||
alloc2:
|
||||
# Runtime support function alloc2 (realloc).
|
||||
# Prototype address is in a0.
|
||||
# Number of words to allocate is in a1.
|
||||
li a2, 4 # Word size in bytes
|
||||
mul a2, a1, a2 # Calculate number of bytes to allocate
|
||||
add a2, gp, a2 # Estimate where GP will move
|
||||
bgeu a2, s11, alloc2_15 # Go to OOM handler if too large
|
||||
lw t0, @.__obj_size__(a0) # Get size of object in words
|
||||
mv t2, a0 # Initialize src ptr
|
||||
mv t3, gp # Initialize dest ptr
|
||||
alloc2_16: # Copy-loop header
|
||||
lw t1, 0(t2) # Load next word from src
|
||||
sw t1, 0(t3) # Store next word to dest
|
||||
addi t2, t2, 4 # Increment src
|
||||
addi t3, t3, 4 # Increment dest
|
||||
addi t0, t0, -1 # Decrement counter
|
||||
bne t0, zero, alloc2_16 # Loop if more words left to copy
|
||||
mv a0, gp # Save new object's address to return
|
||||
sw a1, @.__obj_size__(a0) # Set size of new object in words
|
||||
# (same as requested size)
|
||||
mv gp, a2 # Set next free slot in the heap
|
||||
jr ra # Return to caller
|
||||
alloc2_15: # OOM handler
|
||||
li a0, @error_oom # Exit code for: Out of memory
|
||||
la a1, const_5 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl abort
|
||||
abort:
|
||||
# Runtime support function abort (does not return).
|
||||
mv t0, a0 # Save exit code in temp
|
||||
li a0, @print_string # Code for print_string ecall
|
||||
ecall # Print error message in a1
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for print_char ecall
|
||||
ecall # Print newline
|
||||
mv a1, t0 # Move exit code to a1
|
||||
li a0, @exit2 # Code for exit2 ecall
|
||||
ecall # Exit with code
|
||||
abort_17: # Infinite loop
|
||||
j abort_17 # Prevent fallthrough
|
||||
|
||||
.globl heap.init
|
||||
heap.init:
|
||||
# Runtime support function heap.init.
|
||||
mv a1, a0 # Move requested size to A1
|
||||
li a0, @sbrk # Code for ecall: sbrk
|
||||
ecall # Request A1 bytes
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl concat
|
||||
concat:
|
||||
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw fp, 24(sp)
|
||||
addi fp, sp, 32
|
||||
sw s1, -12(fp)
|
||||
sw s2, -16(fp)
|
||||
sw s3, -20(fp)
|
||||
sw s4, -24(fp)
|
||||
sw s5, -28(fp)
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
beqz t0, concat_none
|
||||
beqz t1, concat_none
|
||||
lw t0, @.__len__(t0)
|
||||
lw t1, @.__len__(t1)
|
||||
add s5, t0, t1
|
||||
addi a1, s5, @listHeaderWords
|
||||
la a0, $.list$prototype
|
||||
jal alloc2
|
||||
sw s5, @.__len__(a0)
|
||||
mv s5, a0
|
||||
addi s3, s5, @.__elts__
|
||||
lw s1, 4(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 12(fp)
|
||||
concat_1:
|
||||
beqz s2, concat_2
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_1
|
||||
concat_2:
|
||||
lw s1, 0(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 8(fp)
|
||||
concat_3:
|
||||
beqz s2, concat_4
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_3
|
||||
concat_4:
|
||||
mv a0, s5
|
||||
lw s1, -12(fp)
|
||||
lw s2, -16(fp)
|
||||
lw s3, -20(fp)
|
||||
lw s4, -24(fp)
|
||||
lw s5, -28(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 32
|
||||
jr ra
|
||||
concat_none:
|
||||
j error.None
|
||||
|
||||
|
||||
.globl conslist
|
||||
conslist:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 0(fp)
|
||||
la a0, $.list$prototype
|
||||
beqz a1, conslist_done
|
||||
addi a1, a1, @listHeaderWords
|
||||
jal alloc2
|
||||
lw t0, 0(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
slli t1, t0, 2
|
||||
add t1, t1, fp
|
||||
addi t2, a0, @.__elts__
|
||||
conslist_1:
|
||||
lw t3, 0(t1)
|
||||
sw t3, 0(t2)
|
||||
addi t1, t1, -4
|
||||
addi t2, t2, 4
|
||||
addi t0, t0, -1
|
||||
bnez t0, conslist_1
|
||||
conslist_done:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strcat
|
||||
strcat:
|
||||
|
||||
addi sp, sp, -12
|
||||
sw ra, 8(sp)
|
||||
sw fp, 4(sp)
|
||||
addi fp, sp, 12
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
lw t0, @.__len__(t0)
|
||||
beqz t0, strcat_4
|
||||
lw t1, @.__len__(t1)
|
||||
beqz t1, strcat_5
|
||||
add t1, t0, t1
|
||||
sw t1, -12(fp)
|
||||
addi t1, t1, 4
|
||||
srli t1, t1, 2
|
||||
addi a1, t1, @listHeaderWords
|
||||
la a0, $str$prototype
|
||||
jal alloc2
|
||||
lw t0, -12(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
addi t2, a0, 16
|
||||
lw t0, 4(fp)
|
||||
lw t1, @.__len__(t0)
|
||||
addi t0, t0, @.__str__
|
||||
strcat_1:
|
||||
beqz t1, strcat_2
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_1
|
||||
strcat_2:
|
||||
lw t0, 0(fp)
|
||||
lw t1, 12(t0)
|
||||
addi t0, t0, 16
|
||||
strcat_3:
|
||||
beqz t1, strcat_6
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_3
|
||||
strcat_4:
|
||||
lw a0, 0(fp)
|
||||
j strcat_7
|
||||
strcat_5:
|
||||
lw a0, 4(fp)
|
||||
j strcat_7
|
||||
strcat_6:
|
||||
sb zero, 0(t2)
|
||||
strcat_7:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 12
|
||||
jr ra
|
||||
|
||||
|
||||
.globl streql
|
||||
streql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, streql_no
|
||||
streql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, streql_no
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, streql_1
|
||||
li a0, 1
|
||||
j streql_end
|
||||
streql_no:
|
||||
xor a0, a0, a0
|
||||
streql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strneql
|
||||
strneql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, strneql_yes
|
||||
strneql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, strneql_yes
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, strneql_1
|
||||
xor a0, a0, a0
|
||||
j strneql_end
|
||||
strneql_yes:
|
||||
li a0, 1
|
||||
strneql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makeint
|
||||
makeint:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw a0, 0(sp)
|
||||
la a0, $int$prototype
|
||||
jal ra, alloc
|
||||
lw t0, 0(sp)
|
||||
sw t0, @.__int__(a0)
|
||||
lw ra, 4(sp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makebool
|
||||
makebool:
|
||||
|
||||
slli a0, a0, 4
|
||||
la t0, @bool.False
|
||||
add a0, a0, t0
|
||||
jr ra
|
||||
|
||||
|
||||
.globl noconv
|
||||
noconv:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl initchars
|
||||
initchars:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl error.None
|
||||
error.None:
|
||||
li a0, 4 # Exit code for: Operation on None
|
||||
la a1, const_6 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.Div
|
||||
error.Div:
|
||||
li a0, 2 # Exit code for: Division by zero
|
||||
la a1, const_7 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.OOB
|
||||
error.OOB:
|
||||
li a0, 3 # Exit code for: Index out of bounds
|
||||
la a1, const_8 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.data
|
||||
|
||||
.globl const_0
|
||||
const_0:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_1
|
||||
const_1:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 1 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_7
|
||||
const_7:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Division by zero" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_5
|
||||
const_5:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 8 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 13 # Constant value of attribute: __len__
|
||||
.string "Out of memory" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_8
|
||||
const_8:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 19 # Constant value of attribute: __len__
|
||||
.string "Index out of bounds" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_3
|
||||
const_3:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 4 # Constant value of attribute: __len__
|
||||
.string "True" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_6
|
||||
const_6:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 17 # Constant value of attribute: __len__
|
||||
.string "Operation on None" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_2
|
||||
const_2:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Invalid argument" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_4
|
||||
const_4:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 5 # Constant value of attribute: __len__
|
||||
.string "False" # Constant value of attribute: __str__
|
||||
.align 2
|
@ -0,0 +1,674 @@
|
||||
.equiv @sbrk, 9
|
||||
.equiv @print_string, 4
|
||||
.equiv @print_char, 11
|
||||
.equiv @print_int, 1
|
||||
.equiv @exit2, 17
|
||||
.equiv @read_string, 8
|
||||
.equiv @fill_line_buffer, 18
|
||||
.equiv @.__obj_size__, 4
|
||||
.equiv @.__len__, 12
|
||||
.equiv @.__int__, 12
|
||||
.equiv @.__bool__, 12
|
||||
.equiv @.__str__, 16
|
||||
.equiv @.__elts__, 16
|
||||
.equiv @error_div_zero, 2
|
||||
.equiv @error_arg, 1
|
||||
.equiv @error_oob, 3
|
||||
.equiv @error_none, 4
|
||||
.equiv @error_oom, 5
|
||||
.equiv @error_nyi, 6
|
||||
.equiv @listHeaderWords, 4
|
||||
.equiv @strHeaderWords, 4
|
||||
.equiv @bool.True, const_1
|
||||
.equiv @bool.False, const_0
|
||||
|
||||
.data
|
||||
|
||||
.globl $object$prototype
|
||||
$object$prototype:
|
||||
.word 0 # Type tag for class: object
|
||||
.word 3 # Object size
|
||||
.word $object$dispatchTable # Pointer to dispatch table
|
||||
.align 2
|
||||
|
||||
.globl $int$prototype
|
||||
$int$prototype:
|
||||
.word 1 # Type tag for class: int
|
||||
.word 4 # Object size
|
||||
.word $int$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __int__
|
||||
.align 2
|
||||
|
||||
.globl $bool$prototype
|
||||
$bool$prototype:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl $str$prototype
|
||||
$str$prototype:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 5 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.word 0 # Initial value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl $.list$prototype
|
||||
$.list$prototype:
|
||||
.word -1 # Type tag for class: .list
|
||||
.word 4 # Object size
|
||||
.word 0 # Pointer to dispatch table
|
||||
.word 0 # Initial value of attribute: __len__
|
||||
.align 2
|
||||
|
||||
.globl $object$dispatchTable
|
||||
$object$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: object.__init__
|
||||
|
||||
.globl $int$dispatchTable
|
||||
$int$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: int.__init__
|
||||
|
||||
.globl $bool$dispatchTable
|
||||
$bool$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: bool.__init__
|
||||
|
||||
.globl $str$dispatchTable
|
||||
$str$dispatchTable:
|
||||
.word $object.__init__ # Implementation for method: str.__init__
|
||||
|
||||
.text
|
||||
|
||||
.globl main
|
||||
main:
|
||||
lui a0, 8192 # Initialize heap size (in multiples of 4KB)
|
||||
add s11, s11, a0 # Save heap size
|
||||
jal heap.init # Call heap.init routine
|
||||
mv gp, a0 # Initialize heap pointer
|
||||
mv s10, gp # Set beginning of heap
|
||||
add s11, s10, s11 # Set end of heap (= start of heap + heap size)
|
||||
mv ra, zero # No normal return from main program.
|
||||
mv fp, zero # No preceding frame.
|
||||
addi sp, sp, -@..main.size # Reserve space for stack frame.
|
||||
sw ra, @..main.size-4(sp) # return address
|
||||
sw fp, @..main.size-8(sp) # control link
|
||||
addi fp, sp, @..main.size # New fp is at old SP.
|
||||
jal initchars # Initialize one-character strings.
|
||||
li a0, 3 # Load integer literal 3
|
||||
mv a0, a0 # Set result from 'then' expression
|
||||
j label_2
|
||||
label_1: # Else part
|
||||
li a0, 4 # Load integer literal 4
|
||||
mv a0, a0 # Set result from 'else' expression
|
||||
label_2: # End of if-else expression
|
||||
jal makeint # Box integer
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
j label_3 # Branch on false.
|
||||
li a0, 3 # Load integer literal 3
|
||||
mv a0, a0 # Set result from 'then' expression
|
||||
j label_4
|
||||
label_3: # Else part
|
||||
li a0, 4 # Load integer literal 4
|
||||
mv a0, a0 # Set result from 'else' expression
|
||||
label_4: # End of if-else expression
|
||||
jal makeint # Box integer
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
jal $print # Invoke function: print
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
.equiv @..main.size, 16
|
||||
label_0: # End of program
|
||||
li a0, 10 # Code for ecall: exit
|
||||
ecall
|
||||
|
||||
.globl $object.__init__
|
||||
$object.__init__:
|
||||
# Init method for type object.
|
||||
mv a0, zero # `None` constant
|
||||
jr ra # Return
|
||||
|
||||
.globl $print
|
||||
$print:
|
||||
# Function print
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, print_6 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 1 # Load type tag of `int`
|
||||
beq t0, t1, print_7 # Go to print(int)
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, print_8 # Go to print(str)
|
||||
li t1, 2 # Load type tag of `bool`
|
||||
beq t0, t1, print_9 # Go to print(bool)
|
||||
print_6: # Invalid argument
|
||||
li a0, 1 # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
# Printing bools
|
||||
print_9: # Print bool object in A0
|
||||
lw a0, @.__bool__(a0) # Load attribute __bool__
|
||||
beq a0, zero, print_10 # Go to: print(False)
|
||||
la a0, const_3 # String representation: True
|
||||
j print_8 # Go to: print(str)
|
||||
print_10: # Print False object in A0
|
||||
la a0, const_4 # String representation: False
|
||||
j print_8 # Go to: print(str)
|
||||
|
||||
# Printing strs.
|
||||
print_8: # Print str object in A0
|
||||
addi a1, a0, @.__str__ # Load address of attribute __str__
|
||||
j print_11 # Print the null-terminated string is now in A1
|
||||
mv a0, zero # Load None
|
||||
j print_5 # Go to return
|
||||
print_11: # Print null-terminated string in A1
|
||||
li a0, @print_string # Code for ecall: print_string
|
||||
ecall # Print string
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
j print_5 # Go to return
|
||||
|
||||
# Printing ints.
|
||||
print_7: # Print int object in A0
|
||||
lw a1, @.__int__(a0) # Load attribute __int__
|
||||
li a0, @print_int # Code for ecall: print_int
|
||||
ecall # Print integer
|
||||
li a1, 10 # Load newline character
|
||||
li a0, 11 # Code for ecall: print_char
|
||||
ecall # Print character
|
||||
|
||||
print_5: # End of function
|
||||
mv a0, zero # Load None
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $len
|
||||
$len:
|
||||
# Function len
|
||||
# We do not save/restore fp/ra for this function
|
||||
# because we know that it does not use the stack or does not
|
||||
# call other functions.
|
||||
|
||||
lw a0, 0(sp) # Load arg
|
||||
beq a0, zero, len_12 # None is an illegal argument
|
||||
lw t0, 0(a0) # Get type tag of arg
|
||||
li t1, 3 # Load type tag of `str`
|
||||
beq t0, t1, len_13 # Go to len(str)
|
||||
li t1, -1 # Load type tag for list objects
|
||||
beq t0, t1, len_13 # Go to len(list)
|
||||
len_12: # Invalid argument
|
||||
li a0, @error_arg # Exit code for: Invalid argument
|
||||
la a1, const_2 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
len_13: # Get length of string
|
||||
lw a0, @.__len__(a0) # Load attribute: __len__
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl $input
|
||||
$input:
|
||||
# Function input
|
||||
addi sp, sp, -16 # Reserve stack
|
||||
sw ra, 12(sp) # Save registers
|
||||
sw fp, 8(sp)
|
||||
sw s1, 4(sp)
|
||||
addi fp, sp, 16 # Set fp
|
||||
|
||||
li a0, @fill_line_buffer # Fill the internal line buffer.
|
||||
ecall
|
||||
bgez a0, input_nonempty # More input found
|
||||
la a0, $str$prototype # EOF: Return empty string.
|
||||
j input_done
|
||||
|
||||
input_nonempty:
|
||||
mv s1, a0
|
||||
addi t0, s1, 5 # Compute bytes for string (+NL+NUL),
|
||||
addi t0, t0, @.__str__ # Including header.
|
||||
srli a1, t0, 2 # Convert to words.
|
||||
la a0, $str$prototype # Load address of string prototype.
|
||||
jal ra, alloc2 # Allocate string.
|
||||
sw s1, @.__len__(a0) # Store string length.
|
||||
mv a2, s1 # Pass length.
|
||||
mv s1, a0 # Save string object address.
|
||||
addi a1, a0, @.__str__ # Pass address of string data.
|
||||
li a0, @read_string # ecall to read from internal buffer.
|
||||
ecall
|
||||
addi a0, a0, 1 # Actual length (including NL).
|
||||
sw a0, @.__len__(s1) # Store actual length.
|
||||
add t0, a0, s1
|
||||
li t1, 10 # Store newline and null byte
|
||||
sb t1, @.__str__-1(t0)
|
||||
sb zero, @.__str__(t0) # Store null byte at end.
|
||||
mv a0, s1 # Return string object.
|
||||
|
||||
input_done:
|
||||
lw s1, -12(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 16
|
||||
jr ra
|
||||
|
||||
.globl alloc
|
||||
alloc:
|
||||
# Runtime support function alloc.
|
||||
# Prototype address is in a0.
|
||||
lw a1, 4(a0) # Get size of object in words
|
||||
j alloc2 # Allocate object with exact size
|
||||
|
||||
.globl alloc2
|
||||
alloc2:
|
||||
# Runtime support function alloc2 (realloc).
|
||||
# Prototype address is in a0.
|
||||
# Number of words to allocate is in a1.
|
||||
li a2, 4 # Word size in bytes
|
||||
mul a2, a1, a2 # Calculate number of bytes to allocate
|
||||
add a2, gp, a2 # Estimate where GP will move
|
||||
bgeu a2, s11, alloc2_15 # Go to OOM handler if too large
|
||||
lw t0, @.__obj_size__(a0) # Get size of object in words
|
||||
mv t2, a0 # Initialize src ptr
|
||||
mv t3, gp # Initialize dest ptr
|
||||
alloc2_16: # Copy-loop header
|
||||
lw t1, 0(t2) # Load next word from src
|
||||
sw t1, 0(t3) # Store next word to dest
|
||||
addi t2, t2, 4 # Increment src
|
||||
addi t3, t3, 4 # Increment dest
|
||||
addi t0, t0, -1 # Decrement counter
|
||||
bne t0, zero, alloc2_16 # Loop if more words left to copy
|
||||
mv a0, gp # Save new object's address to return
|
||||
sw a1, @.__obj_size__(a0) # Set size of new object in words
|
||||
# (same as requested size)
|
||||
mv gp, a2 # Set next free slot in the heap
|
||||
jr ra # Return to caller
|
||||
alloc2_15: # OOM handler
|
||||
li a0, @error_oom # Exit code for: Out of memory
|
||||
la a1, const_5 # Load error message as str
|
||||
addi a1, a1, @.__str__ # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl abort
|
||||
abort:
|
||||
# Runtime support function abort (does not return).
|
||||
mv t0, a0 # Save exit code in temp
|
||||
li a0, @print_string # Code for print_string ecall
|
||||
ecall # Print error message in a1
|
||||
li a1, 10 # Load newline character
|
||||
li a0, @print_char # Code for print_char ecall
|
||||
ecall # Print newline
|
||||
mv a1, t0 # Move exit code to a1
|
||||
li a0, @exit2 # Code for exit2 ecall
|
||||
ecall # Exit with code
|
||||
abort_17: # Infinite loop
|
||||
j abort_17 # Prevent fallthrough
|
||||
|
||||
.globl heap.init
|
||||
heap.init:
|
||||
# Runtime support function heap.init.
|
||||
mv a1, a0 # Move requested size to A1
|
||||
li a0, @sbrk # Code for ecall: sbrk
|
||||
ecall # Request A1 bytes
|
||||
jr ra # Return to caller
|
||||
|
||||
.globl concat
|
||||
concat:
|
||||
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw fp, 24(sp)
|
||||
addi fp, sp, 32
|
||||
sw s1, -12(fp)
|
||||
sw s2, -16(fp)
|
||||
sw s3, -20(fp)
|
||||
sw s4, -24(fp)
|
||||
sw s5, -28(fp)
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
beqz t0, concat_none
|
||||
beqz t1, concat_none
|
||||
lw t0, @.__len__(t0)
|
||||
lw t1, @.__len__(t1)
|
||||
add s5, t0, t1
|
||||
addi a1, s5, @listHeaderWords
|
||||
la a0, $.list$prototype
|
||||
jal alloc2
|
||||
sw s5, @.__len__(a0)
|
||||
mv s5, a0
|
||||
addi s3, s5, @.__elts__
|
||||
lw s1, 4(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 12(fp)
|
||||
concat_1:
|
||||
beqz s2, concat_2
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_1
|
||||
concat_2:
|
||||
lw s1, 0(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 8(fp)
|
||||
concat_3:
|
||||
beqz s2, concat_4
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_3
|
||||
concat_4:
|
||||
mv a0, s5
|
||||
lw s1, -12(fp)
|
||||
lw s2, -16(fp)
|
||||
lw s3, -20(fp)
|
||||
lw s4, -24(fp)
|
||||
lw s5, -28(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 32
|
||||
jr ra
|
||||
concat_none:
|
||||
j error.None
|
||||
|
||||
|
||||
.globl conslist
|
||||
conslist:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 0(fp)
|
||||
la a0, $.list$prototype
|
||||
beqz a1, conslist_done
|
||||
addi a1, a1, @listHeaderWords
|
||||
jal alloc2
|
||||
lw t0, 0(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
slli t1, t0, 2
|
||||
add t1, t1, fp
|
||||
addi t2, a0, @.__elts__
|
||||
conslist_1:
|
||||
lw t3, 0(t1)
|
||||
sw t3, 0(t2)
|
||||
addi t1, t1, -4
|
||||
addi t2, t2, 4
|
||||
addi t0, t0, -1
|
||||
bnez t0, conslist_1
|
||||
conslist_done:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strcat
|
||||
strcat:
|
||||
|
||||
addi sp, sp, -12
|
||||
sw ra, 8(sp)
|
||||
sw fp, 4(sp)
|
||||
addi fp, sp, 12
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
lw t0, @.__len__(t0)
|
||||
beqz t0, strcat_4
|
||||
lw t1, @.__len__(t1)
|
||||
beqz t1, strcat_5
|
||||
add t1, t0, t1
|
||||
sw t1, -12(fp)
|
||||
addi t1, t1, 4
|
||||
srli t1, t1, 2
|
||||
addi a1, t1, @listHeaderWords
|
||||
la a0, $str$prototype
|
||||
jal alloc2
|
||||
lw t0, -12(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
addi t2, a0, 16
|
||||
lw t0, 4(fp)
|
||||
lw t1, @.__len__(t0)
|
||||
addi t0, t0, @.__str__
|
||||
strcat_1:
|
||||
beqz t1, strcat_2
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_1
|
||||
strcat_2:
|
||||
lw t0, 0(fp)
|
||||
lw t1, 12(t0)
|
||||
addi t0, t0, 16
|
||||
strcat_3:
|
||||
beqz t1, strcat_6
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_3
|
||||
strcat_4:
|
||||
lw a0, 0(fp)
|
||||
j strcat_7
|
||||
strcat_5:
|
||||
lw a0, 4(fp)
|
||||
j strcat_7
|
||||
strcat_6:
|
||||
sb zero, 0(t2)
|
||||
strcat_7:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 12
|
||||
jr ra
|
||||
|
||||
|
||||
.globl streql
|
||||
streql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, streql_no
|
||||
streql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, streql_no
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, streql_1
|
||||
li a0, 1
|
||||
j streql_end
|
||||
streql_no:
|
||||
xor a0, a0, a0
|
||||
streql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl strneql
|
||||
strneql:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, strneql_yes
|
||||
strneql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, strneql_yes
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, strneql_1
|
||||
xor a0, a0, a0
|
||||
j strneql_end
|
||||
strneql_yes:
|
||||
li a0, 1
|
||||
strneql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makeint
|
||||
makeint:
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw a0, 0(sp)
|
||||
la a0, $int$prototype
|
||||
jal ra, alloc
|
||||
lw t0, 0(sp)
|
||||
sw t0, @.__int__(a0)
|
||||
lw ra, 4(sp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
|
||||
|
||||
.globl makebool
|
||||
makebool:
|
||||
|
||||
slli a0, a0, 4
|
||||
la t0, @bool.False
|
||||
add a0, a0, t0
|
||||
jr ra
|
||||
|
||||
|
||||
.globl noconv
|
||||
noconv:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl initchars
|
||||
initchars:
|
||||
|
||||
jr ra
|
||||
|
||||
|
||||
.globl error.None
|
||||
error.None:
|
||||
li a0, 4 # Exit code for: Operation on None
|
||||
la a1, const_6 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.Div
|
||||
error.Div:
|
||||
li a0, 2 # Exit code for: Division by zero
|
||||
la a1, const_7 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.globl error.OOB
|
||||
error.OOB:
|
||||
li a0, 3 # Exit code for: Index out of bounds
|
||||
la a1, const_8 # Load error message as str
|
||||
addi a1, a1, 16 # Load address of attribute __str__
|
||||
j abort # Abort
|
||||
|
||||
.data
|
||||
|
||||
.globl const_0
|
||||
const_0:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 0 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_1
|
||||
const_1:
|
||||
.word 2 # Type tag for class: bool
|
||||
.word 4 # Object size
|
||||
.word $bool$dispatchTable # Pointer to dispatch table
|
||||
.word 1 # Constant value of attribute: __bool__
|
||||
.align 2
|
||||
|
||||
.globl const_7
|
||||
const_7:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 16 # Constant value of attribute: __len__
|
||||
.string "Division by zero" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_5
|
||||
const_5:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 8 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 13 # Constant value of attribute: __len__
|
||||
.string "Out of memory" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_8
|
||||
const_8:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 19 # Constant value of attribute: __len__
|
||||
.string "Index out of bounds" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_3
|
||||
const_3:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 6 # Object size
|
||||
.word $str$dispatchTable # Pointer to dispatch table
|
||||
.word 4 # Constant value of attribute: __len__
|
||||
.string "True" # Constant value of attribute: __str__
|
||||
.align 2
|
||||
|
||||
.globl const_6
|
||||
const_6:
|
||||
.word 3 # Type tag for class: str
|
||||
.word 9 # Object size
|
||||