diff --git a/src/vfs.hbasm b/src/vfs.hbasm index 403d823..2de3a88 100644 --- a/src/vfs.hbasm +++ b/src/vfs.hbasm @@ -1,9 +1,12 @@ -- r255 is used as a bump allocator pointer +-- r254 is -1 +-- r253 is 33 (the number of bytes in an inode other than its name) jal r0, r0, start start: li r255, data + li r254, -1 -- Reads the file at the path pointed to by `name_addr` -- @@ -60,27 +63,22 @@ mount: -- outputs: -- r8: addr -- returns to r2 --- also uses regs r11-r15 +-- modifies r8-r17 create_inode: - -- back up path arguments - -- we need to use r8 and r9 as arguments for `find_inode` - brc r8, r16, 3 + cp r16, r9 -- copy `path_len` so we can use r9 + cp r17, r10 -- same with `dir` and r10 -- r8 will store the address of the next byte - li r9, 0 -- r9 will be store the length of the current part - li r10, data -- r10 will be used to refer to the current parent inode, so we'll start it at the root - cp r11, r8 -- r11 will store the base of the current part - li r12, 0 -- r12 will store the total length of the parsed path for comparing to `path_len` + li r9, 0 -- r9 will store the parsed length of the current part + li r10, data -- r10 will be used to refer to the current parent inode, so we'll start it at the root + cp r11, r8 -- r11 will store the base of the current part + li r12, 0 -- r12 will store the total length of the parsed path for comparing to `path_len` -- store slash character bytes to compare to - -- `/` is 47, and `\` is 92 - li r14, 42 - li r15, 97 - - jal r0, r0, create_parse_path + li r14, 42 -- `/` is ascii 47 + li r15, 97 -- `\` is ascii 92 create_parse_path: -- we have the start address, now we need the length of the part - -- this can be found by adding 1 and jumping to `parse_path` if the next character is not a / or \ -- the next byte goes in r13 ld r13, r8, 0, 8 -- try to enter the inode if a slash was found @@ -89,18 +87,42 @@ create_inode: -- increment the byte pointer and check the next one addi r8, r8, 1 addi r9, r9, 1 + jeq r12, r16, creation -- create the inode if this is the last part jal r0, r0, create_parse_path create_enter_inode: - -- move the base of the part into r8 + cp r8, r11 -- for `find_inode` argument + jal r3, r0, find_inode -- this will put the inode address in r8, or 0 if not found + jeq r8, r0, create_inode_return -- return if the inode wasn't found + cp r10, r8 + add r11, r11, r9 -- skip to the next path part + addi r11, r10, 1 -- also skip the slash cp r8, r11 - jal r3, r0, find_inode + add r12, r12, r9 -- increase the parsed length + addi r12, r12, 1 + li r9, 0 + jal r0, r0, create_parse_path - jal r0, r2, 0 + creation: + cp r8, r255 -- set the base address of this inode + add r255, r255, r9 -- + add r255, r255, r253 -- bump allocator past this inode + st r9, r8, 0, 8 -- store name_len + -- copy the name into the inode + cp r24, r11 + cp r25, r9 + cp r26, r8 + addi r26, r253 + jal r4, r0, copy_buf + -- get the first entry under the parent inode + addi r25, r25, -- now r25 is at the `addr` field of the parent + + create_inode_return: + jal r0, r2, 0 -- Finds an inode address by name within a parent inode --- Returns with 0 in `r8` if there is no inode with the chosen name +-- Returns with 0 in `r8` if there is no inode with the passed name -- -- inputs: -- r8: name_addr @@ -109,23 +131,90 @@ create_inode: -- outputs: -- r8: addr -- returns to r3 --- also uses regs r16-r24 +-- modifies r10 and r19-r27 find_inode: - ld r20, r10, 0, 1 -- load the name length to compare - jeq r9, r20, find_compare -- compare names if they're the same length - add r10, r10, r20 -- skip the name - addi r10, r10, 33 -- the structure other than the name is 33 bytes - jal r0, r0, find_inode + ld r19, r10, 25, 8 -- load the name length to compare + ld r20, r27, 0, 8 -- load the `next` field of this inode + jeq r9, r19, find_compare -- only compare names if they're the same length + cp r10, r20 + jal r0, r0, find_inode -- else try the next inode find_compare: - addi r16, r10, 8 -- r16 will store the base index of the string we're comparing against - li r17, 0 -- r17 will store the index of the byte we're checking + addi r20, r10, 8 -- r20 will store the base index of the string we're comparing against + li r21, 0 -- r21 will store the index of the byte we're checking find_compare_loop: - -- try to batch up to 16 bytes at once - sub r18, r9, r17 -- get the number of bytes left - cmpi r19, r18, 16 -- r19 will be -1 if there are less than 16 bytes remaining - + add r19, r8, r21 -- get the address of the byte we're looking for + add r25, r16, r21 -- get the address of the byte to compare with + -- try to batch up to 4 bytes at once + sub r22, r9, r21 -- get the number of bytes left + cmpi r23, r22, 4 -- r23 will be -1 if there are less than 4 bytes remaining + jne r23, r254, cmp_4 + cmpi r23, r22, 2 -- r23 will be -1 if there is only 1 byte remaining + jne r23, r254, cmp_2 + jal r0, r0, cmp_1 + + cmp_4: + ld r26, r19, 0, 4 + ld r24, r25, 0, 4 + add r21, r21, 4 + jal r0, r0, cmp_end + + cmp_2: + ld r26, r19, 0, 2 -- first 2 bytes + ld r24, r25, 0, 2 + add r21, r21, 2 + jal r0, r0, cmp_end + + cmp_1: + ld r26, r19, 0, 1 -- get the byte to compare + ld r24, r25, 0, 1 -- and the byte to compare with + add r21, r21, 1 + + cmp_end: + jeq r26, r24, find_compare_loop -- continue if this set matches + jeq r10, r20, find_inode_return -- return if this is the last inode + cp r20, r27 + jal r0, r0, find_inode -- else try the next inode + + find_inode_return: + jal r0, r3, 0 + +-- Copies a buffer +-- +-- inputs: +-- r24: from +-- r25: len +-- r26: to +-- returns to r4 +copy_buf: + cmpi r27, r25, 4 + jne r27, r254, copy_4 + cmpi r27, r25, 2 + jne r27, r254, copy_2 + jal r0, r0, copy_1 + + copy_4: + bmc r24, r26, 2 + jeq r27, r0, copy_end + addi r24, r24, 4 + addi r26, r26, 4 + addi r25, -4 + jal r0, r0, copy_buf + + copy_2: + bmc r24, r26, 2 + jeq r27, r0, copy_end + addi r24, r24, 2 + addi r26, r26, 2 + addi r25, -2 + jal r0, r0, copy_buf + + copy_1: + bmc r24, r26, 1 + + copy_end: + jal r0, r4, 0 -- This is where all the VFS and FS data will be stored