# Game of life # MIPS32 assembler for SPIM simulator # Grzegorz Niemirowski # www.grzegorz.net .data universe1: .byte 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 .byte 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 .byte 0, 1, 0, 0, 0, 0, 0, 0, 1, 1 .byte 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 universe2: .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 dead: .asciiz " " live: .asciiz "O" line_break: .asciiz "|\n|" upper_line: .asciiz "|----------|\n|" bottom_line: .asciiz "----------|\n" .text .globl main main: la $s0, universe1 la $s4, universe2 jal print_universe jal process_universe li $v0, 5 syscall la $s0, universe2 la $s4, universe1 jal print_universe jal process_universe li $v0, 5 syscall j main ######################################### # transform a universe # $s0 - address of primary universe # $s4 - address of secondary universe # $s1 - state of primary cell # $s2 - state of secondary cell # $s5 - cell counter # $s6 - return address # $s7 - const address of primary universe ######################################### process_universe: li $s5, 0 move $s6, $ra move $s7, $s0 process_loop: jal count_neighbours lb $s1, ($s0) jal make_decision sb $s2, ($s4) addi $s0, $s0, 1 addi $s4, $s4, 1 addi $s5, $s5, 1 blt $s5, 100, process_loop move $ra, $s6 jr $ra ################################## # print a universe # $s0 - address of start universe # $t0 - current cell in universe # $t1 - state of cell # $t2 - cell number ################################## print_universe: la $a0, upper_line li $v0, 4 syscall li $t2, 0 la $t0, ($s0) check_cell: lb $t1, ($t0) beqz $t1, print_dead la $a0, live li $v0, 4 syscall j next_cell print_dead: la $a0, dead li $v0, 4 syscall next_cell: addi $t0, 1 addi $t2, 1 rem $t1, $t2, 10 bnez $t1, next la $a0, line_break li $v0, 4 syscall next: blt $t2, 100, check_cell la $a0, bottom_line li $v0, 4 syscall jr $ra ################################# # count neighbours of a cell # $s0 - address of cell # $s3 - number of neighbours # $s7 - address of universe ################################# count_neighbours: li $s3, 0 # reset number of neighbours li $t4, 10 sub $t5, $s0, $s7 # get offset div $t5, $t4 mflo $t6 # get row mfhi $t7 # get column # upper left beq $t6, 0, left # if we are at top most row don't look above beq $t7, 0, upper # if we are at left most column don't look left addi $t1, $s0, -11 lb $t0, ($t1) beqz $t0, upper addi $s3, $s3, 1 upper: addi $t1, $s0, -10 lb $t0, ($t1) beqz $t0, upper_right addi $s3, $s3, 1 upper_right: beq $t7, 9, left # if we are at right most column don't look right addi $t1, $s0, -9 lb $t0, ($t1) beqz $t0, left addi $s3, $s3, 1 left: beq $t7, 0, right # if we are at left most column don't look left addi $t1, $s0, -1 lb $t0, ($t1) beqz $t0, right addi $s3, $s3, 1 right: beq $t7, 9, lower_left # if we are at right most column don't look right addi $t1, $s0, 1 lb $t0, ($t1) beqz $t0, lower_left addi $s3, $s3, 1 lower_left: beq $t6, 9, check_end # if we are at bottom most row don't look below beq $t7, 0, lower # if we are at left most column don't look left addi $t1, $s0, 9 lb $t0, ($t1) beqz $t0, lower addi $s3, $s3, 1 lower: addi $t1, $s0, 10 lb $t0, ($t1) beqz $t0, lower_right addi $s3, $s3, 1 lower_right: beq $t7, 9, check_end # if we are at right most column don't look right addi $t1, $s0, 11 lb $t0, ($t1) beqz $t0, check_end addi $s3, $s3, 1 check_end: jr $ra #################################### # apply rules for a cell # $s1 - state of cell # $s2 - new state of cell # $s3 - number of neighbours #################################### make_decision: move $s2, $s1 beqz $s1, currently_dead blt $s3, 2, death_sentence bgt $s3, 3, death_sentence j decision_end currently_dead: beq $s3, 3, life_sentence j decision_end death_sentence: li $s2, 0 j decision_end life_sentence: li $s2, 1 decision_end: jr $ra