Greg Price ??: > >> Here is an example. >> >> #*if* *defined*(__sparcv9 >> <http://src.opensolaris.org/source/s?defs=__sparcv9>) >> 79 /* >> 80 * The 64-bit C ABI uses a stack frame that looks like: >> 81 * >> 82 * | | >> 83 * |-------------------------------| >> 84 * | Locals, temps, saved floats | >> 85 * |-------------------------------| >> 86 * | outgoing parameters past 6 | >> 87 * |-------------------------------|-\ >> 88 * | outgoing parameters thru 6 | | >> 89 * |-------------------------------| > minimum stack frame >> 90 * | 16 xwords to save IN and | | >> 91 * | LOCAL register on overflow | | >> 92 * |-------------------------------|-/-\ >> 93 * | | | >> 94 * | | > v9 abi bias >> 95 * | | | >> 96 * %sp->|-------------------------------|---/ >> 97 */ >> >> [0]> ddi_regs_map_setup::dis >> ddi_regs_map_setup: save %sp, -0xe0, %sp >> ddi_regs_map_setup+4: ldx [%fp + 0x8af], %l0 >>>>> 0x8af = 0x7ff + >> 0xb0, access the Locals here. >> ddi_regs_map_setup+8: clr %o0 >> ddi_regs_map_setup+0xc: mov 0x1, %l1 >> ddi_regs_map_setup+0x10: call -0x2400cc <impl_acc_hdl_alloc> >> ddi_regs_map_setup+0x14: clr %o1 >> ddi_regs_map_setup+0x18: call -0x2400dc <impl_acc_hdl_get> >> ddi_regs_map_setup+0x1c: stx %o0, [%l0] >> ddi_regs_map_setup+0x20: st %l1, [%o0] >> ddi_regs_map_setup+0x24: mov 0x3, %l5 >> ddi_regs_map_setup+0x28: mov 0x2, %l4 >> ddi_regs_map_setup+0x2c: stx %i0, [%o0 + 0x18] >> ddi_regs_map_setup+0x30: mov %o0, %l2 >> ddi_regs_map_setup+0x34: add %fp, 0x7cf, %o1 >> ... >> >> My questions: >> >> 1. when the bias 0x7ff is subtracted from %sp? implicitly by the 'save'? >> >> 2. the bias area can also be used as Locals, temps, then when it is >> used? and when the explicitly allocated area is used? >> >> Thanks, >> Brian >> >> > Hi, > > The bias is only used in 64 bit mode, and it's part of the ABI (which > Max had said). > > The bias is applied to the loads and stores that reference the stack > and frame pointers, but not the instructions that adjust the > stack/frame pointer (i.e. you won't see the bias in save or restore > instructions). > > It's a not a bias area, but it's biasing the frame pointer to give you > greater reach on one side. SPARC has fixed size instructions, and the > offsets for the loads & stores are fixed at 13 bits (i.e. an 8K span). > The stack/frame pointer is used to access the incoming args, local > variables and outgoing args. If a bias were not used, the amount of > memory that could be "reached" above or below the pointer would be > equal (4KB each side). While the space available for incoming and > outgoing args should be the same, local variables are kept in the > stack frame, and are only ever accessed by the owning function itself. > When we are going to pass args to a function, we store them in the > callers frame, then after the function call happens, then callee > accesses them from the callers frame. > > Because we only ever need to get arguments from the callers frame, we > don't need to be able to reach very far on that side of the pointer, > so to give us more space for local variables (which are in our own > frame), we apply the bias (2KB) to all the loads and stores that > access incoming args, outgoing args and local variables. This means > we're limited to 2KB of incoming args, but about 6KB of outgoing args > AND local variables. > > Make sense? Yes. Instructive.
I didn't look carefully at the example I took. [0]> ddi_regs_map_setup::dis ddi_regs_map_setup: save %sp, -0xe0, %sp ddi_regs_map_setup+4: ldx [%fp + 0x8af], %l0 >>>>> 0x8af = 0x7ff + 0xb0, Here, we get the 7th arg that is saved on the caller's frame. Then we can also see the caller put the 7th arg on its frame: mpt_attach+0x3ec: add %l2, 0x78, %i4 <<<<<< get the mpt->m_datap mpt_attach+0x3f0: srl %i1, 0x0, %o1 mpt_attach+0x3f4: add %l2, 0x80, %o2 mpt_attach+0x3f8: stx %i4, [%sp + 0x8af] <<<<<<<save it on its frame mpt_attach+0x3fc: add %l2, 0x228, %o5 mpt_attach+0x400: mov %i0, %o0 mpt_attach+0x404: clr %o3 mpt_attach+0x408: call -0x79fdaa68 <ddi_regs_map_setup> ... > ::offsetof mpt_t m_datap offsetof (mpt_t, m_datap) = 0x78 Here is the C code: { if (ddi_regs_map_setup(dip, mem_bar, (caddr_t *)&mpt->m_reg, 0, 0, &mpt->m_dev_acc_attr, /&mpt->m_datap/) != DDI_SUCCESS) { mpt_log(mpt, CE_WARN, "map setup failed"); cmn_err(CE_WARN, "!ID[SUNWpd.mpt.attach.4005]"); goto fail; } } In general: 1. the caller save the args past 6 on its frame 2. each function reserve save areas for the l0-l7, i0-i7 and o0-o5 (16*8 = 0xb0), when spill trap occurs or thread switch occurs, those register values are saved on the stack. 3. the callee reserve area for the Locals and temps and outgoing args past 6. together with the caller's bias area(I don't know how to express this area, so just name as is), can be accessed by the callee for its private use. I still have the question that who produces those 'bias area' and when? still take the example: [0]> ddi_regs_map_setup::dis ddi_regs_map_setup: save %sp, -0xe0, %sp <<<<< the %o6(%sp) of the caller -0xe0 = %o6 of the callee; %i6(%fp) of the callee = %o6 of the caller. ddi_regs_map_setup+4: ldx [%fp + 0x8af], %l0 >>>>> 0x8af = 0x7ff + 0xb0, access the 7th of the arg which is saved on the caller's frame. ddi_regs_map_setup+8: clr %o0 ddi_regs_map_setup+0xc: mov 0x1, %l1 ddi_regs_map_setup+0x10: call -0x2400cc <impl_acc_hdl_alloc> ddi_regs_map_setup+0x14: clr %o1 ddi_regs_map_setup+0x18: call -0x2400dc <impl_acc_hdl_get> ... [0]> impl_acc_hdl_alloc::dis impl_acc_hdl_alloc: save %sp, -0xb0, %sp impl_acc_hdl_alloc+4: clr %o1 impl_acc_hdl_alloc+8: movrne %i0, 0x1, %o1 impl_acc_hdl_alloc+0xc: mov %o1, %i2 impl_acc_hdl_alloc+0x10: call +0x189d14 <kmem_zalloc> It is obvious that before or just after the 'save' instruction, the %sp has been moved to the bottom of the bias. so it must be the 'call' or the 'save' instruction that does it. I want to know. Thanks, Brian > > Cheers, > Greg >