| #!/usr/bin/env python | |
| import sys | |
| if len(sys.argv) < 2: | |
| print "Provide the integer size in 32-bit words" | |
| sys.exit(1) | |
| size = int(sys.argv[1]) | |
| full_rows = size // 3 | |
| init_size = size % 3 | |
| if init_size == 0: | |
| full_rows = full_rows - 1 | |
| init_size = 3 | |
| def emit(line, *args): | |
| s = '"' + line + r' \n\t"' | |
| print s % args | |
| rx = [3, 4, 5] | |
| ry = [6, 7, 8] | |
| #### set up registers | |
| emit("add r0, %s", (size - init_size) * 4) # move z | |
| emit("add r2, %s", (size - init_size) * 4) # move y | |
| emit("ldmia r1!, {%s}", ", ".join(["r%s" % (rx[i]) for i in xrange(init_size)])) | |
| emit("ldmia r2!, {%s}", ", ".join(["r%s" % (ry[i]) for i in xrange(init_size)])) | |
| print "" | |
| if init_size == 1: | |
| emit("umull r9, r10, r3, r6") | |
| emit("stmia r0!, {r9, r10}") | |
| else: | |
| #### first two multiplications of initial block | |
| emit("umull r11, r12, r3, r6") | |
| emit("stmia r0!, {r11}") | |
| print "" | |
| emit("mov r10, #0") | |
| emit("umull r11, r9, r3, r7") | |
| emit("adds r12, r12, r11") | |
| emit("adc r9, r9, #0") | |
| emit("umull r11, r14, r4, r6") | |
| emit("adds r12, r12, r11") | |
| emit("adcs r9, r9, r14") | |
| emit("adc r10, r10, #0") | |
| emit("stmia r0!, {r12}") | |
| print "" | |
| #### rest of initial block, with moving accumulator registers | |
| acc = [9, 10, 11, 12, 14] | |
| if init_size == 3: | |
| emit("mov r%s, #0", acc[2]) | |
| for i in xrange(0, 3): | |
| emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i], ry[2 - i]) | |
| emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) | |
| emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) | |
| emit("adc r%s, r%s, #0", acc[2], acc[2]) | |
| emit("stmia r0!, {r%s}", acc[0]) | |
| print "" | |
| acc = acc[1:] + acc[:1] | |
| emit("mov r%s, #0", acc[2]) | |
| for i in xrange(0, 2): | |
| emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i + 1], ry[2 - i]) | |
| emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) | |
| emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) | |
| emit("adc r%s, r%s, #0", acc[2], acc[2]) | |
| emit("stmia r0!, {r%s}", acc[0]) | |
| print "" | |
| acc = acc[1:] + acc[:1] | |
| emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[init_size-1], ry[init_size-1]) | |
| emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) | |
| emit("adc r%s, r%s, r%s", acc[1], acc[1], acc[4]) | |
| emit("stmia r0!, {r%s}", acc[0]) | |
| emit("stmia r0!, {r%s}", acc[1]) | |
| print "" | |
| #### reset y and z pointers | |
| emit("sub r0, %s", (2 * init_size + 3) * 4) | |
| emit("sub r2, %s", (init_size + 3) * 4) | |
| #### load y registers | |
| emit("ldmia r2!, {%s}", ", ".join(["r%s" % (ry[i]) for i in xrange(3)])) | |
| #### load additional x registers | |
| if init_size != 3: | |
| emit("ldmia r1!, {%s}", ", ".join(["r%s" % (rx[i]) for i in xrange(init_size, 3)])) | |
| print "" | |
| prev_size = init_size | |
| for row in xrange(full_rows): | |
| emit("umull r11, r12, r3, r6") | |
| emit("stmia r0!, {r11}") | |
| print "" | |
| emit("mov r10, #0") | |
| emit("umull r11, r9, r3, r7") | |
| emit("adds r12, r12, r11") | |
| emit("adc r9, r9, #0") | |
| emit("umull r11, r14, r4, r6") | |
| emit("adds r12, r12, r11") | |
| emit("adcs r9, r9, r14") | |
| emit("adc r10, r10, #0") | |
| emit("stmia r0!, {r12}") | |
| print "" | |
| acc = [9, 10, 11, 12, 14] | |
| emit("mov r%s, #0", acc[2]) | |
| for i in xrange(0, 3): | |
| emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i], ry[2 - i]) | |
| emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) | |
| emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) | |
| emit("adc r%s, r%s, #0", acc[2], acc[2]) | |
| emit("stmia r0!, {r%s}", acc[0]) | |
| print "" | |
| acc = acc[1:] + acc[:1] | |
| #### now we need to start shifting x and loading from z | |
| x_regs = [3, 4, 5] | |
| for r in xrange(0, prev_size): | |
| x_regs = x_regs[1:] + x_regs[:1] | |
| emit("ldmia r1!, {r%s}", x_regs[2]) | |
| emit("mov r%s, #0", acc[2]) | |
| for i in xrange(0, 3): | |
| emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i], ry[2 - i]) | |
| emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) | |
| emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) | |
| emit("adc r%s, r%s, #0", acc[2], acc[2]) | |
| emit("ldr r%s, [r0]", acc[3]) # load stored value from initial block, and add to accumulator | |
| emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) | |
| emit("adcs r%s, r%s, #0", acc[1], acc[1]) | |
| emit("adc r%s, r%s, #0", acc[2], acc[2]) | |
| emit("stmia r0!, {r%s}", acc[0]) | |
| print "" | |
| acc = acc[1:] + acc[:1] | |
| # done shifting x, start shifting y | |
| y_regs = [6, 7, 8] | |
| for r in xrange(0, prev_size): | |
| y_regs = y_regs[1:] + y_regs[:1] | |
| emit("ldmia r2!, {r%s}", y_regs[2]) | |
| emit("mov r%s, #0", acc[2]) | |
| for i in xrange(0, 3): | |
| emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i], y_regs[2 - i]) | |
| emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) | |
| emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) | |
| emit("adc r%s, r%s, #0", acc[2], acc[2]) | |
| emit("ldr r%s, [r0]", acc[3]) # load stored value from initial block, and add to accumulator | |
| emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) | |
| emit("adcs r%s, r%s, #0", acc[1], acc[1]) | |
| emit("adc r%s, r%s, #0", acc[2], acc[2]) | |
| emit("stmia r0!, {r%s}", acc[0]) | |
| print "" | |
| acc = acc[1:] + acc[:1] | |
| # done both shifts, do remaining corner | |
| emit("mov r%s, #0", acc[2]) | |
| for i in xrange(0, 2): | |
| emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i + 1], y_regs[2 - i]) | |
| emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) | |
| emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) | |
| emit("adc r%s, r%s, #0", acc[2], acc[2]) | |
| emit("stmia r0!, {r%s}", acc[0]) | |
| print "" | |
| acc = acc[1:] + acc[:1] | |
| emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[2], y_regs[2]) | |
| emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) | |
| emit("adc r%s, r%s, r%s", acc[1], acc[1], acc[4]) | |
| emit("stmia r0!, {r%s}", acc[0]) | |
| emit("stmia r0!, {r%s}", acc[1]) | |
| print "" | |
| prev_size = prev_size + 3 | |
| if row < full_rows - 1: | |
| #### reset x, y and z pointers | |
| emit("sub r0, %s", (2 * prev_size + 3) * 4) | |
| emit("sub r1, %s", prev_size * 4) | |
| emit("sub r2, %s", (prev_size + 3) * 4) | |
| #### load x and y registers | |
| emit("ldmia r1!, {%s}", ",".join(["r%s" % (rx[i]) for i in xrange(3)])) | |
| emit("ldmia r2!, {%s}", ",".join(["r%s" % (ry[i]) for i in xrange(3)])) | |
| print "" |