|
Post by komaspieler on Jun 24, 2013 20:40:08 GMT -5
Sorry for starting nerdy.. Game of Life in MIPS assembler (haven't optimized it yet and yes, this is my own work). It will simulate a pre-defined pattern entered at init-'function' on the memory of the processor. Can be visualized in the MARS Simulator ( courses.missouristate.edu/kenvollmar/mars/ ) with the help of the Bitmap tool. Tried to keep all code comments in English. Quick translation: spielfeld -> playfield/playground, kopiefeld -> copy of playground The size of the game field can be adjusted for quadratic fields by reserving more memory and changing value of $a0 in _infini method Code will clean itself up if you copy it to an editor with tab size 8... .data spielfeld: .space 256 # one cell = 4 Byte, 8x8x4 = 256 kopiefeld: .space 256 .text .globl main
main: li $a0, 8 # side length of playfield jal init # define start pattern _infini: addi $a0, $zero, 8 jal copyGeneration addi $a0, $zero, 8 jal nextGeneration j _infini li $v0, 10 # terminate syscall markCell: # a0: x, a1: y, a2: content // x,y in [0..7] la $t0, spielfeld mul $t1, $a0, 0x4 # x-offset mul $t2, $a1, 0x20 # y-offset add $t0, $t0, $t1 # jump to column add $t0, $t0, $t2 # jump to row sw $a2, 0($t0) jr $ra init: addi $sp, $sp, -4 sw $ra, 0($sp) addi $a0, $zero, 4 addi $a1, $zero, 3 addi $a2, $zero, 0xFFFFFFFF jal markCell addi $a0, $zero, 5 addi $a1, $zero, 3 addi $a2, $zero, 0xFFFFFFFF jal markCell addi $a0, $zero, 6 addi $a1, $zero, 3 addi $a2, $zero, 0xFFFFFFFF jal markCell lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra
copyGeneration: add $t0, $zero, $a0 # x = a0 add $t1, $zero, $a0 # y = a0 la $t2, spielfeld la $t3, kopiefeld copyLoopy: addi $t1, $t1, -1 add $t0, $zero, $a0 copyLoopx: addi $t0, $t0, -1 mul $t4, $t0, 0x4 # x-offset mul $t5, $t1, 0x20 # y-offset add $t2, $t2, $t4 add $t2, $t2, $t5 add $t3, $t3, $t4 add $t3, $t3, $t5 lw $t6, 0($t2) sw $t6, 0($t3) sub $t2, $t2, $t4 sub $t2, $t2, $t5 sub $t3, $t3, $t4 sub $t3, $t3, $t5 beqz $t1, copyExit beqz $t0, copyLoopy j copyLoopx copyExit: jr $ra nextGeneration: addi $sp, $sp, -24 sw $ra, 0($sp) sw $s0, 4($sp) sw $s1, 8($sp) sw $s2, 12($sp) sw $s3, 16($sp) sw $s4, 20($sp) add $s0, $zero, $a0 add $s1, $zero, $s0 # x = a0 add $s2, $zero, $s0 # y = a0 la $s3, spielfeld la $s4, kopiefeld nextLoopy: addi $s2, $s2, -1 add $s1, $zero, $s0 nextLoopx: addi $s1, $s1, -1
add $a0, $zero, $s3 add $a1, $zero, $s4 add $a2, $zero, $s1 add $a3, $zero, $s2 jal _countNeighbours blt $v0, 2, killCell # cell has less than 2 neighbours -> dies bgt $v0, 3, killCell # cell has more than 3 neighbours -> dies beq $v0, 3, awakeCell # cell has exactly 3 neighbours -> awakes beq $v0, 2, resume # exactly 2 neighbours - do nothing killCell: add $a0, $zero, $s1 add $a1, $zero, $s2 add $a2, $zero, 0x00000000 jal markCell j resume awakeCell: add $a0, $zero, $s1 add $a1, $zero, $s2 add $a2, $zero, 0xFFFFFFFF jal markCell resume: beqz $s2, nextExit beqz $s1, nextLoopy j nextLoopx nextExit: lw $ra, 0($sp) lw $s0, 4($sp) lw $s1, 8($sp) lw $s2, 12($sp) lw $s3, 16($sp) lw $s4, 20($sp) addi $sp, $sp, 24 jr $ra _countNeighbours: #start prologue addi $sp, $sp, -24 sw $a0, 0($sp) # start spielfeld sw $a1, 4($sp) # start kopiefeld sw $a2, 8($sp) # x sw $a3, 12($sp) # y sw $s0, 16($sp) # later: cell adress copy sw $s1, 20($sp) # later: cell adress live field # end prologue mul $t0, $a2, 0x4 # x-offset mul $t3, $a3, 0x20 # y-offset add $s0, $a1, $t0 add $s0, $s0, $t3 # final cell adress in copy sub $t0, $t0, $t0 # counter reset, needed to get neighbour count lw $t1, 4($sp) # restore kopiefeld base add $t2, $t1, 0xFC # last cell in copy field add $t1, $t1, $t3 # start adress row (needed for boundary comparison) add $s0, $s0, -0x4 # one to the left blt $s0, $t1, _noLeft # noch im feld? lw $t3, 0($s0) # value of left cell andi $t3, $t3, 0x1 # will return 1, if cell alive (= 0xFFFFFFFF) add $t0, $t0, $t3 # increase counter _noLeft: add $s0, $s0, 0x8 # two to the right add $t1, $t1, 0x1C # last cell in row bgt $s0, $t1, _noRight # noch im feld? lw $t3, 0($s0) # value of right cell andi $t3, $t3, 0x1 # will return 1, if cell alive (= 0xFFFFFFF) add $t0, $t0, $t3 # increase counter _noRight: add $s0, $s0, 0x1C # original cell, one row down bgt $s0, $t2, _noBelow add $t1, $t1, 0x20 # one row down add $s0, $s0, 0x4 # lower right cell bgt $s0, $t1, _noLR lw $t3, 0($s0) # value of lower right cell andi $t3, $t3, 0x1 # will return 1, if cell alive (= 0xFFFFFFF) add $t0, $t0, $t3 # increase counter _noLR: add $s0, $s0, -0x8 # lower left cell add $t1, $t1, -0x1C # start of row blt $s0, $t1, _noLL # noch im feld? add $t1, $t1, 0x1C # end of row again lw $t3, 0($s0) # value of lower left cell andi $t3, $t3, 0x1 # will return 1, if cell alive (= 0xFFFFFFF) add $t0, $t0, $t3 # increase counter _noLL: add $s0, $s0, 0x4 # below cell lw $t3, 0($s0) # value of lower cell andi $t3, $t3, 0x1 # will return 1, if cell alive (= 0xFFFFFFF) add $t0, $t0, $t3 # increase counter _noBelow: add $s0, $s0, -0x40 # cell above blt $s0, $a0, _noAbove # noch im feld? add $t1, $t1, -0x40 # end row above original add $s0, $s0, 0x4 # upper right cell bgt $s0, $t1, _noUR # noch im feld? lw $t3, 0($s0) # value of upper right cell andi $t3, $t3, 0x1 # will return 1, if cell alive (= 0xFFFFFFF) add $t0, $t0, $t3 # increase counter _noUR: add $s0, $s0, -0x8 # move to upper left cell add $t1, $t1, -0x1C # start of row above blt $s0, $t1, _noUL # noch im feld? lw $t3, 0($s0) # value of upper left cell andi $t3, $t3, 0x1 # will return 1, if cell alive (= 0xFFFFFFF) add $t0, $t0, $t3 # increase counter _noUL: add $s0, $s0, 0x4 # cell above lw $t3, 0($s0) # value of upper cell andi $t3, $t3, 0x1 # will return 1, if cell alive (= 0xFFFFFFF) add $t0, $t0, $t3 # increase counter
_noAbove: # start epilogue lw $a0, 0($sp) lw $a1, 4($sp) lw $a2, 8($sp) lw $a3, 12($sp) lw $s0, 16($sp) lw $s1, 20($sp) addi $v0, $t0, 0 # return value (neighbour count) addi $sp, $sp, 24 # end epilogue jr $ra # my work here is done
|
|