michael@0: michael@0: // Select C numeric constant michael@0: .radix C michael@0: // for 64 bit mode, use .psr abi64 michael@0: .psr abi32 michael@0: // big endian michael@0: .psr msb michael@0: // Section has executable code michael@0: .section .text, "ax","progbits" michael@0: // procedure named 'NS_InvokeByIndex' michael@0: .proc NS_InvokeByIndex michael@0: // manual bundling michael@0: .explicit michael@0: michael@0: // extern "C" uint32_t michael@0: // invoke_copy_to_stack(uint64_t* d, michael@0: // const uint32_t paramCount, nsXPTCVariant* s) michael@0: .global invoke_copy_to_stack michael@0: // .exclass invoke_copy_to_stack, @fullyvisible michael@0: .type invoke_copy_to_stack,@function michael@0: michael@0: // .exclass NS_InvokeByIndex, @fullyvisible michael@0: .type NS_InvokeByIndex,@function michael@0: michael@0: // NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, michael@0: // uint32_t paramCount, nsXPTCVariant* params); michael@0: NS_InvokeByIndex:: michael@0: .prologue michael@0: .save ar.pfs, r37 michael@0: // allocate 4 input args, 6 local args, and 8 output args michael@0: alloc r37 = ar.pfs, 4, 6, 8, 0 // M michael@0: nop.i 0 ;; // I michael@0: michael@0: // unwind table already knows gp, no need to specify anything michael@0: add r39 = 0, gp // A michael@0: .save rp, r36 michael@0: mov r36 = rp // I michael@0: .vframe r38 michael@0: add r38 = 0, sp ;; // A michael@0: michael@0: // We first calculate the amount of extra memory stack space required michael@0: // for the arguments, and register storage. michael@0: // We then call invoke_copy_to_stack() to write the argument contents michael@0: // to the specified memory regions. michael@0: // We then copy the integer arguments to integer registers, and floating michael@0: // arguments to float registers. michael@0: // Lastly we load the virtual table jump pointer, and call the target michael@0: // subroutine. michael@0: michael@0: // in0 : that michael@0: // in1 : methodIndex michael@0: // in2 : paramCount michael@0: // in3 : params michael@0: michael@0: // stack frame size is 16 + (8 * even(paramCount)) + 64 + 64 michael@0: // 16 byte frame header michael@0: // 8 * even(paramCount) memory argument area michael@0: // 64 bytes integer register area michael@0: // 64 bytes float register area michael@0: // This scheme makes sure stack fram size is a multiple of 16 michael@0: michael@0: .body michael@0: add r10 = 8, r0 // A michael@0: // r41 points to float register area michael@0: add r41 = -64, sp // A michael@0: // r40 points to int register area michael@0: add r40 = -128, sp ;; // A michael@0: michael@0: add out1 = 0, r40 // A michael@0: add out2 = 0, r41 // A michael@0: tbit.z p14,p15 = in2,0 ;; // I michael@0: michael@0: // compute 8 * even(paramCount) michael@0: (p14) shladd r11 = in2, 3, r0 ;; // A michael@0: (p15) shladd r11 = in2, 3, r10 ;; // A michael@0: sub out0 = r40, r11 ;; // A michael@0: michael@0: // advance the stack frame michael@0: add sp = -16, out0 // A michael@0: add out3 = 0, in2 // A michael@0: add out4 = 0, in3 // A michael@0: michael@0: // branch to invoke_copy_to_stack michael@0: br.call.sptk.few rp = invoke_copy_to_stack ;; // B michael@0: michael@0: // restore gp michael@0: add gp = 0, r39 // A michael@0: add out0 = 0, in0 // A michael@0: michael@0: // load the integer and float registers michael@0: ld8 out1 = [r40], 8 // M michael@0: ldfd f8 = [r41], 8 ;; // M michael@0: michael@0: ld8 out2 = [r40], 8 // M michael@0: ldfd f9 = [r41], 8 ;; // M michael@0: michael@0: ld8 out3 = [r40], 8 // M michael@0: ldfd f10 = [r41], 8 ;; // M michael@0: michael@0: ld8 out4 = [r40], 8 // M michael@0: ldfd f11 = [r41], 8 ;; // M michael@0: michael@0: ld8 out5 = [r40], 8 // M michael@0: ldfd f12 = [r41], 8 ;; // M michael@0: // 16 * methodIndex michael@0: shladd r11 = in1, 4, r0 // A michael@0: michael@0: ld8 out6 = [r40], 8 // M michael@0: ldfd f13 = [r41], 8 ;; // M michael@0: michael@0: ld8 out7 = [r40], 8 // M michael@0: ldfd f14 = [r41], 8 // M michael@0: addp4 r8 = 0, in0 ;; // A michael@0: michael@0: // look up virtual base table and dispatch to target subroutine michael@0: // This section assumes 32 bit pointer mode, and virtual base table michael@0: // layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html michael@0: michael@0: // load base table michael@0: ld4 r8 = [r8] ;; // M michael@0: addp4 r8 = r11, r8 ;; // A michael@0: michael@0: // first entry is jump pointer, second entry is gp michael@0: addp4 r9 = 8, r8 ;; // A michael@0: // load jump pointer michael@0: ld8 r8 = [r8] michael@0: michael@0: // load gp michael@0: ld8 gp = [r9] ;; // M michael@0: mov b6 = r8 ;; // I michael@0: michael@0: // branch to target virtual function michael@0: br.call.sptk.few rp = b6 ;; // B michael@0: michael@0: // epilog michael@0: mov ar.pfs = r37 // I michael@0: mov rp = r36 ;; // I michael@0: michael@0: add sp = 0, r38 // A michael@0: add gp = 0, r39 // A michael@0: br.ret.sptk.few rp ;; // B michael@0: michael@0: .endp michael@0: michael@0: