Greg Price ??:
> Brian Xu - Sun Microsystems - Beijing China wrote:
>   
>> 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
>>     
> Yes
>   
>> 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.
>>     
> No. We save the locals and input registers. Remember that on SPARC the 
> output registers from one frame are the input registers to the next 
> frame (i.e. they are an alias)
>   
I know the caller's %o will be the callee's %i after the 'save', but I 
don't think they are saved on the stack when the 'call' or 'save' 
executes. Just as what I mean, these acres are just reserved for traps, 
those registers are saved by the trap handler or the resume().
>> 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.
>>     
> We have a minimum stack frame which is large enough to hold the 
> registers + the frame is extended to hold the local variables. The bias 
> isn't an area, think of it like calibrating the steering on a car or 
> remote control boat. i.e. the default position is always offset by a 
> particular amount.
>   
I know the answer. From the doc you sent to me, I got:

/The SPARC V9 ABI defines the stack pointer to have bias subtracted. 
This means that stack pointer for 64-bit program normally contains an 
misaligned value,but load and store instructions generated by the com- 
piler subtract the required bias to generate the correct address.

/so it is just a definition of the %sp, nothing else.
>> I still have the question that who produces those 'bias area' and when?
>>     
> Like I was saying, it's not an area... the stack frame is the same size, 
> but the stack/frame pointer is offset by a particular amount, then when 
> we go to access something with it, we need to add/subtract the offset 
> back in.
>
> The best thing to do is plug some fictional values in, then see how it 
> works.
>
> I'll send you a copy of the SPARC class I used to teach... It's a little 
> dated, but all this stuff is the same.
>   
>> 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.
>>     
> The save and restore instructions are like regular add and subtract, 
> i.e. they add or subtract the size of the stack frame from the 
> stack/frame pointer, but they also do a register window move. For a save 
> (i.e. calling a function) this means all the %o's (output regs) become 
> the %i's of the called function. The return address is %i7/%o7 and the 
> frame / stack pointer is %i6/%o6, hence when you do a function call, the 
> frame pointer for the called function *IS* the stack pointer from the 
> calling function.
>   
I know this.

Thanks,
Brian
> Cheers,
> Greg
>
>   
>> Thanks,
>> Brian
>>     
>>> Cheers,
>>> Greg
>>>
>>>       
> _______________________________________________
> mdb-discuss mailing list
> mdb-discuss at opensolaris.org
>   


Reply via email to