// Original code (C) Rolf-Dieter Klein, 1991 V 2.0 // "Mandelbrotmenge ohne Transputer-Links" (Mandelbrot w/o Transputer-Links) // Modified for DSM860-16 usage and commented by Axel Muhr, 2012 // Visit http://www.geekdot.com/index.php?page=putting-it-to-use to learn more // about this code and the hardware it's been written for. resxdir = 640 // also change float const at end resydir = 480 // also change float const at end ledport = 0xdffffff8 // LEDs Bit 0..3, + Bit 7 = Boot dualport = 0xd0040000 // Dualport-Ram shared with ISA slot dummyaddr = 0xc0000080 // Dummy // org 0x10000 // Start Bootprogramm mainprog: nop mov dummyaddr,r30 // Dummy-move to cope w/ some buggy i860 masks mov ledport,r9 // Store LED-Address into r9 mov dualport,r10 // Store DP-Address into r10 or 0x8b,r0,r8 // LED mask into r8 st.b r8,0(r9) // and write it (OFF,ON,OFF,OFF) mov 0xaa,r8 // 'AA' is the status send to the Host = "I'm here!" st.b r8,0x940(r10) // write it to DP-RAM with an offset of 0x940 // PC = DC00:118 / i860 d00408c0 mov cymax,r29 // Some init stuff... fld.d r29(r0),f24 mov cymin,r29 fld.d r29(r0),f26 mov cxmax,r29 fld.d r29(r0),f28 mov cxmin,r29 fld.d r29(r0),f30 wait: // The command-loop ld.b 0x940(r10),r5 // Reading DC00:118 for a command from Host xor 2,r5,r0 // If command = 2, read parameters bc paramnew // read cx....cy xor 1,r5,r0 // If command = 1, run! bnc wait // Éelse loop forever or 0x83,r0,r8 // Write a new LED setting, showing that we're running now st.b r8,0(r9) // = ON,ON,OFF,OFF ld.s 0x948(r10),r17 // read 2 bytes in one go from DC00:252 ld.s 0x950(r10),r21 // Again a single word (16bit), this time from DC00:254 // convert integer to float - that's from the i860 Prog. Ref. Manual: xorh 0x8000,r17,r17 ixfr r17,f14 // low half mov conv,r29 fld.d 0(r29),f2 // Trick BC+BN fmov.ss f3,f15 fsub.dd f14,f2,f14 // Result Double in F14 mov xres,r29 fld.d r0(r29),f2 fmul.dd f14,f2,f2 fsub.dd f28,f30,f14 fmul.dd f14,f2,f14 fadd.dd f30,f14,f4 // cx mov yres,r29 fld.d r0(r29),f2 fsub.dd f24,f26,f14 fmul.dd f14,f2,f2 // Delta cy fadd.dd f26,f0,f6 // cy mov r10,r6 // Copy DP-RAM Addr. mov r0,r7 // Copy counter for result mainloop: call iter nop nop nop fadd.dd f6,f2,f6 // r20 = Result of iteration // Now (byte-wise) write one 'result-column' into DP-RAM until r7 == ResYdir // Because we have 512KB below the monitor DP-RAM, we can comfortably write // the 480 Y-resolution pixels there. // If you'd like to reduce colors, this would be a good place for that e.g. // and 0xf, r20, r20 // 16 Colors st.b r20,0(r6) // to DP-RAM (r6) and 1, r6, r0 // even address? (Carry=0) // This check is for 16-bit Cards only! // WILL NOT work on EISA or 8-bit cards!! bc adr_even // No carry set -> jump adr_even addu 6,r6,r6 // else add 6 to addr. adr_even: addu 1,r6,r6 //[and] add 1 addu 1,r7,r7 // counter++ xor resydir,r7,r0 // counter = resydir? bnc mainloop // no, then loop next in st.b r0,0x940(r10) // Write a '0' to 0xDC00:118 = Done or 0x8b,r0,r8 // Set LEDs to: st.b r8,0(r9) // OFF,ON,OFF,OFF st.b r0,0(r30) // another Dummystore br wait // and back into the command-loop nop paramnew: // read new Parameters mov r10,r15 // Dual-Port read-address mov cxmax,r29 // temp load address target basis mov 2*8,r4 // amount of Shorts (was Bytes) for transport // mov 8,r4 // 8 x longs (32bit) // Debug - all LEDs on: or 0x80,r0,r8 st.b r8,0(r9) // ON,ON,ON,ON paralp: ld.s 0(r15),r14 // load from Dual-Port-RAM (16 instead 8 bit) st.s r14,0(r29) // into RAM (16 instead 8 bit) addu 8,r15,r15 // increase DP-RAM pointer 8 bytes addu 2,r29,r29 // increase Mem-Pointer 2 instead 1 (short <> byte) addu -1,r4,r4 xor r0,r4,r0 // Test counter for Zero bnc paralp // Debug - all LEDs off: or 0x8F,r0,r8 st.b r8,0(r9) // OFF,OFF,OFF,OFF st.b r0,0x940(r10) // Write '0' (OK) to 0xDC00:118 mov cymax,r29 // move the previously read stuff into fld.d r29(r0),f24 // FP registers mov cymin,r29 fld.d r29(r0),f26 mov cxmax,r29 fld.d r29(r0),f28 mov cxmin,r29 fld.d r29(r0),f30 br wait nop iter: // This is where the magic happens! fmov.dd f0,f8 fmov.dd f0,f10 fmov.dd f0,f18 fmov.dd f0,f20 mov r0,r20 mov rmax,r29 fld.d r29(r0),f22 br iterlp nop ds.q 0 // Align for dual instr. iterlp: d.pfsub.dd f18,f20,f0 // m m f18-20 x x result nop d.pfadd.dd f0,f0,f0 // f8*10 m 0 f18-20 x result nop d.mm12mpm.dd f8,f10,f0 // 0 x f18-20 result nop d.r2ap1.dd f4,f0,f0 addu 1,r20,r20 d.mm12mpm.dd f0,f0,f0 nop d.m12apm.dd f0,f0,f0 nop d.m12apm.dd f0,f0,f8 subu r21,r20,r0 d.i2ap1.dd f6,f0,f0 nop d.mm12mpm.dd f0,f0,f0 nop d.mm12mpm.dd f8,f8,f0 nop d.m12apm.dd f0,f0,f10 nop d.pfmul.dd f10,f10,f18 // result x*x bnc iterend d.pfmul.dd f0,f0,f0 nop d.pfmul.dd f0,f0,f20 nop d.fadd.dd f18,f20,f12 nop d.pfgt.dd f12,f22,f0 nop d.fnop bnc iterlp iterend: d.fnop nop fnop nop fnop nop bri r1 nop ds.d 0 cxmax: dc.dd -0.745429-0.00000000000505 cxmin: dc.dd -0.745429-0.0000000000051 cymax: dc.dd 0.113008+0.00000000000331 cymin: dc.dd 0.113008+0.00000000000329 xres: dc.dd 1.0/640.0 yres: dc.dd 1.0/480.0 rmax: dc.dd 100.0 conv: dc.l 0x80000000,0x43300000 temp: dc.d 0 end