Files
uiuc-ece391-mp3/fish/blink.S
ece391staff 7fc79b62ed MP3 Release
2018-10-15 13:22:04 -05:00

382 lines
7.9 KiB
ArmAsm

.data # section declaration
# Useful offset constants for accessing members of a
# struct mp1_blink_struct structure
LOCATION = 0
ON_CHAR = 2
OFF_CHAR = 3
ON_LENGTH = 4
OFF_LENGTH = 6
COUNTDOWN = 8
STATUS = 10
NEXT = 12
STRUCT_SIZE = 16
# Pointer to head of list (initialized to NULL)
mp1_list_head:
.long 0
call_table:
.long mp1_ioctl_add
.long mp1_ioctl_remove
.long mp1_ioctl_find
.long mp1_ioctl_sync
.text # section declaration
# Export the function symbol names
.global mp1_rtc_tasklet
.global mp1_ioctl
# void mp1_poke(void);
#
# Interface: Register-based arguments (not C-style)
# Inputs: %cl - The byte you wish to write
# %eax - Offset from the start of video memory that you wish
# to write to
# Outputs: Text-mode video screen is written to at location %eax with
# the byte in %cl
# Registers: Clobbers EDX
mp1_poke:
movl vmem_base_addr(,1),%edx
movb %cl,(%edx,%eax,1)
ret
mp1_rtc_tasklet:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %edi
pushl %ebx
movl mp1_list_head, %ebx
tasklet_loop:
cmpl $0, %ebx
je tasklet_end
decw COUNTDOWN(%ebx)
cmpw $0,COUNTDOWN(%ebx)
jg next_loop
movzwl LOCATION(%ebx), %eax #blink location is now in eax
shl $1,%eax
testw $0x1,STATUS(%ebx)
jz currently_off
movb OFF_CHAR(%ebx), %cl
call mp1_poke
movw OFF_LENGTH(%ebx),%dx
jmp end_blink
currently_off:
movb ON_CHAR(%ebx), %cl
call mp1_poke
movw ON_LENGTH(%ebx),%dx
end_blink:
movw %dx, COUNTDOWN(%ebx)
xorw $0x1, STATUS(%ebx)
next_loop:
movl NEXT(%ebx), %ebx
jmp tasklet_loop
tasklet_end:
popl %ebx
popl %edi
popl %esi
popl %ebp
ret
mp1_ioctl:
movl 8(%esp), %eax
jmp *call_table(,%eax,4)
mp1_ioctl_add:
pushl %ebp
movl %esp, %ebp
# Allocate temp structure on the stack
subl $STRUCT_SIZE, %esp
# Preserve registers
pushl %esi
pushl %edi
pushl %ebx
# Get pointer to temp structure
leal -STRUCT_SIZE(%ebp), %ebx
# Copy user data onto the stack
pushl $STRUCT_SIZE
pushl 8(%ebp)
pushl %ebx
call ece391_memcpy
addl $12,%esp
# Check that the copy succeeded
cmpl $0,%eax
jne add_fail_return
# Check that the location is valid
cmpw $80*25,LOCATION(%ebx)
jae add_fail_return
# Mark this structure as valid
movw $0x1,STATUS(%ebx) # Mark it as on
movw ON_LENGTH(%ebx),%dx
movw %dx,COUNTDOWN(%ebx)
# Allocate some memory, pointer returned in EAX
pushl $STRUCT_SIZE
call mp1_malloc
add $4, %esp
cmpl $0, %eax
je add_fail_return
# Save EAX
pushl %eax
pushl $STRUCT_SIZE
pushl %ebx
pushl %eax
call ece391_memcpy
addl $12, %esp
# Restore the value from EAX into EDX
popl %edx
# Insert this new item at the front of the list
movl mp1_list_head, %eax
movl %eax, NEXT(%edx)
movl %edx, mp1_list_head
display:
# Display the character
movzwl LOCATION(%edx),%eax
shll $1,%eax
movb ON_CHAR(%edx),%cl
call mp1_poke
jmp add_success_return
add_fail_return:
movl $-1,%eax
jmp add_leave
add_success_return:
movl $0, %eax
add_leave:
popl %ebx
popl %edi
popl %esi
leave
ret
mp1_ioctl_remove:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %edi
pushl %ebx
pushl 8(%ebp)
call mp1_find_helper
addl $4, %esp
cmpl $0, %eax
je remove_fail_return
# Found the right element. Now find the
# previous pointer in the list, and remove it
# We should not fail here, because mp1_find_helper
# returned a valid list element
leal mp1_list_head, %edx
remove_find_prev:
cmp %eax, (%edx)
je found_prev
movl (%edx), %edx
leal NEXT(%edx), %edx
jmp remove_find_prev
found_prev:
# Perform the removal
movl NEXT(%eax), %ecx
movl %ecx, (%edx)
free_mem:
pushl %eax
call mp1_free
addl $4, %esp
jmp remove_success_return
remove_fail_return:
movl $-1,%eax
jmp remove_leave
remove_success_return:
movl $0, %eax
remove_leave:
popl %ebx
popl %edi
popl %esi
leave
ret
mp1_ioctl_sync:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %edi
pushl %ebx
sync_find_first:
movl 8(%ebp), %eax
shr $16, %eax
pushl %eax
call mp1_find_helper
addl $4, %esp
cmpl $0, %eax
je sync_fail_return
movl %eax, %esi
movl 8(%ebp), %eax
andl $0xFFFF, %eax
pushl %eax
call mp1_find_helper
addl $4, %esp
cmpl $0, %eax
je sync_fail_return
movl %eax, %edi
sync_copy_loop:
movw ON_LENGTH(%esi), %ax
movw %ax, ON_LENGTH(%edi)
movw OFF_LENGTH(%esi), %ax
movw %ax, OFF_LENGTH(%edi)
movw COUNTDOWN(%esi), %ax
movw %ax, COUNTDOWN(%edi)
movw STATUS(%esi), %ax
movw %ax, STATUS(%edi)
movzwl LOCATION(%edi), %eax
shll $1,%eax
movzbl OFF_CHAR(%edi),%ecx
movzbl ON_CHAR(%edi),%ebx
testb $0x1,STATUS(%edi)
cmovl %ebx, %ecx
sync_display:
call mp1_poke
jmp sync_success_return
sync_fail_return:
movl $-1,%eax
jmp sync_leave
sync_success_return:
movl $0, %eax
sync_leave:
popl %ebx
popl %edi
popl %esi
leave
ret
mp1_ioctl_find:
pushl %ebp
movl %esp, %ebp
subl $2,%esp
pushl %esi
pushl %edi
pushl %ebx
pushl $2
pushl 8(%ebp)
leal -2(%ebp),%edi
pushl %edi
call ece391_memcpy
addl $12,%esp
cmp $0,%eax
jne find_fail_return
movzwl -2(%ebp),%eax
pushl %eax
call mp1_find_helper
addl $4, %esp
cmpl $0, %eax
je find_fail_return
pushl $STRUCT_SIZE
pushl %eax
pushl 8(%ebp)
call ece391_memcpy
addl $12,%esp
cmp $0,%eax
je find_success_return
find_fail_return:
movl $-1,%eax
jmp find_leave
find_success_return:
movl $0, %eax
find_leave:
popl %ebx
popl %edi
popl %esi
leave
ret
mp1_find_helper:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movw 8(%ebp), %ax
movl mp1_list_head, %ebx
loop:
cmpl $0, %ebx
je helper_fail_return
cmpw %ax, LOCATION(%ebx)
je helper_success_return
movl NEXT(%ebx), %ebx
jmp loop
helper_fail_return:
xorl %eax, %eax
jmp helper_leave
helper_success_return:
movl %ebx, %eax
helper_leave:
popl %ebx
leave
ret
.end