size_t MADIMPENTRY( RegSpecialName )( mad_special_reg sr, const mad_registers *mr, mad_address_format af, char *buff, size_t buff_size ) { unsigned idx; size_t len; const char *p; af = af; idx = 0; switch( sr ) { case MSR_IP: switch( mr->axp.active_pal ) { case PAL_nt: idx = IDX_nt_fir; break; case PAL_unix: case PAL_vms: //NYI: later //break; default: /* 'cause we gotta have one */ idx = IDX_nt_fir; break; } break; case MSR_SP: idx = IDX_sp; break; case MSR_FP: if( VariableFrame( mr->axp.pal.nt.fir.u._32[0] ) ) { idx = IDX_fp; } else { idx = IDX_sp; } break; } p = RegList[idx].info.name; len = strlen( p ); if( buff_size > 0 ) { --buff_size; if( buff_size > len ) buff_size = len; memcpy( buff, p, buff_size ); buff[buff_size] = '\0'; } return( len ); }
void MADIMPENTRY( RegSpecialSet )( mad_special_reg sr, mad_registers *mr, const addr_ptr *ma ) { switch( sr ) { case MSR_IP: /* doesn't matter what PAL is in control since always first field */ mr->axp.pal.nt.fir.u._32[0] = ma->offset; break; case MSR_SP: mr->axp.u30.sp.u64.u._32[0] = ma->offset; break; case MSR_FP: if( VariableFrame( mr->axp.pal.nt.fir.u._32[0] ) ) { mr->axp.u15.fp.u64.u._32[0] = ma->offset; } else { mr->axp.u30.sp.u64.u._32[0] = ma->offset; } break; } }
mad_status DIGENTRY MICallUpStackLevel( mad_call_up_data *cud, const address *start, unsigned rtn_characteristics, long return_disp, const mad_registers *in, address *execution, address *frame, address *stack, mad_registers **out ) { axp_pdata pdata; mad_disasm_data dd; mad_status ms; address curr; addr_off prev_ra_off; addr_off prev_sp_off; addr_off prev_fp_off; addr_off frame_size; addr_off frame_start; return_disp = return_disp; start = start; rtn_characteristics = rtn_characteristics; in = in; *out = NULL; if( cud->ra == 0 ) return( MS_FAIL ); if( cud->sp == 0 ) return( MS_FAIL ); ms = GetPData( execution->mach.offset, &pdata ); if( ms != MS_OK ) return( ms ); frame_size = 0; frame_start = cud->sp; prev_ra_off = NO_OFF; prev_sp_off = NO_OFF; prev_fp_off = NO_OFF; curr = *execution; curr.mach.offset = pdata.beg_addr.u._32[0]; if( curr.mach.offset == 0 ) return( MS_FAIL ); for( ;; ) { if( curr.mach.offset >= execution->mach.offset ) break; if( curr.mach.offset >= pdata.pro_end_addr.u._32[0] ) break; ms = DisasmOne( &dd, &curr, 0 ); if( ms != MS_OK ) return( ms ); if( curr.mach.offset == (pdata.beg_addr.u._32[0] + sizeof( unsigned_32 )) ) { if( dd.ins.type != DI_AXP_LDA ) return( MS_FAIL ); frame_size = -dd.ins.op[1].value; } switch( dd.ins.type ) { case DI_AXP_STQ: switch( dd.ins.op[0].base ) { case DR_AXP_ra: case DR_AXP_r26: prev_ra_off = dd.ins.op[1].value; break; case DR_AXP_sp: case DR_AXP_r30: prev_sp_off = dd.ins.op[1].value; break; case DR_AXP_fp: case DR_AXP_r15: prev_fp_off = dd.ins.op[1].value; break; } break; case DI_AXP_BIS: if( dd.ins.op[0].type == DO_REG && dd.ins.op[1].type == DO_REG && dd.ins.op[2].type == DO_REG && dd.ins.op[0].base == DR_AXP_r31 /* zero */ && dd.ins.op[1].base == DR_AXP_r30 /* sp */ && dd.ins.op[2].base == DR_AXP_r15 /* fp */ ) { /* variable frame routine, and we've done all the prolog */ frame_start = cud->fp; } break; } } if( frame_start == 0 ) return( MS_FAIL ); if( prev_sp_off != NO_OFF ) { if( !GetAnOffset( frame_start + prev_sp_off, &cud->sp ) ) return( MS_FAIL ); } else { cud->sp = frame_start + frame_size; } if( prev_fp_off != NO_OFF ) { if( !GetAnOffset( frame_start + prev_fp_off, &cud->fp ) ) return( MS_FAIL ); } if( prev_ra_off != NO_OFF ) { if( !GetAnOffset( frame_start + prev_ra_off, &cud->ra ) ) return( MS_FAIL ); } stack->mach.offset = cud->sp; execution->mach.offset = cud->ra; if( VariableFrame( execution->mach.offset ) ) { frame->mach.offset = cud->fp; } else { frame->mach.offset = cud->sp; } return( MS_OK ); }