Hi there,
At the moment, the behavior of opening files using syscall 13 is specific to your OS's C runtime. Because the flags specified in $a1 and $a2 are passed directly to open(), some flags that work on one machine will not work on another. This is a consequence of inconsistent constant values for the C open() flags across different libraries. For example: MacOS's Xcode library uses O_CREAT = 0x200, but linux uses O_CREAT = 0x100.
Usually this isn't a problem if you're writing C since you can just use the constants themselves, but spim expects raw values. Therefore, a program that creates a new file on MacOS successfully will not work if you run the same program using spim on linux.
Here is a full table showing the inconsistent flags:

I see a few options:
1: Use MARS's flags, 1, 9 and 0 for write, append and read respectively, and pass in predefined values. For example, if $a1 is 1, pass O_CREAT | O_WRONLY (or similar) into open(). Then the C runtime on the host machine can find the right raw values. Even though many MIPS programs will break due to this, I think it doesn't really make sense in the first place to be able to make a Unix system call on a MIPS simulator, and those programs likely were already broken when run on a platform that wasn't used to develop them. Additionally, it will provide more consistency between spim and MARS, which will consolidate a lot of info online about which flags to use. I've seen many people in forums being told that they should pass MARS's expected flags to spim when asking for help.
2: Assume the MIPS machine that spim is simulating is running linux, and convert the raw values into OS specific values. For example, if I syscall 13 with $a1 = 0x41, spim converts these values into their equivalents on my host machine. So on a mac, it would convert 0x41 to 0x201, but wouldn't do anything on linux. I don't like this solution since there are numerous inconsistencies across the different POSIX OS's, and as a result the conversion will be non-trivial to implement.
.data
o_create: .create_file_flag # loads 0x200 or 0x100 into o_create's address
# depending on your system
path: .asciiz "/path/to/file"
.text
main:
li $v0 13
la $a0 path
lw $a1 o_create # $a1 = 0x200 if spim is running on mac, but
# $a1 = 0x100 if spim is running on linux
li $a2 0x1ff # perms
syscall
I worry though that this will be hard to find for beginners, and wouldn't really fix the problem since you're still free to load whatever into $a1.
I'd be happy to help with whatever fix you decide on if you want. And I can provide example programs that illustrate the bug properly if needed.
More info on the inconsistent open() flags here: article
Thanks
Anonymous