diff options
author | Ananth N Mavinakayanahalli <ananth@in.ibm.com> | 2008-05-22 10:42:35 +0530 |
---|---|---|
committer | Ananth N Mavinakayanahalli <ananth@in.ibm.com> | 2008-05-22 10:42:35 +0530 |
commit | dbb280c79ba5b82f125153f067cbe6fa24aaae0c (patch) | |
tree | 655cc1c6bbd8992a35bbbb66f65c6bd655bd8185 /tapset | |
parent | aa8a3b1797da54a14d04cd57758a65064056376e (diff) | |
download | systemtap-steved-dbb280c79ba5b82f125153f067cbe6fa24aaae0c.tar.gz systemtap-steved-dbb280c79ba5b82f125153f067cbe6fa24aaae0c.tar.xz systemtap-steved-dbb280c79ba5b82f125153f067cbe6fa24aaae0c.zip |
powerpc register+arg access
Diffstat (limited to 'tapset')
-rw-r--r-- | tapset/ppc64/registers.stp | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/tapset/ppc64/registers.stp b/tapset/ppc64/registers.stp new file mode 100644 index 00000000..d3605c05 --- /dev/null +++ b/tapset/ppc64/registers.stp @@ -0,0 +1,239 @@ +/* Dwarfless register access for powerpc */ + +global _reg_offsets, _stp_regs_registered + +function _stp_register_regs() { + /* Same order as pt_regs */ + _reg_offsets["r0"] = 0 + _reg_offsets["r1"] = 8 + _reg_offsets["r2"] = 16 + _reg_offsets["r3"] = 24 + _reg_offsets["r4"] = 32 + _reg_offsets["r5"] = 40 + _reg_offsets["r6"] = 48 + _reg_offsets["r7"] = 56 + _reg_offsets["r8"] = 64 + _reg_offsets["r9"] = 72 + _reg_offsets["r10"] = 80 + _reg_offsets["r11"] = 88 + _reg_offsets["r12"] = 96 + _reg_offsets["r13"] = 104 + _reg_offsets["r14"] = 112 + _reg_offsets["r15"] = 120 + _reg_offsets["r16"] = 128 + _reg_offsets["r17"] = 136 + _reg_offsets["r18"] = 144 + _reg_offsets["r19"] = 152 + _reg_offsets["r20"] = 160 + _reg_offsets["r21"] = 168 + _reg_offsets["r22"] = 176 + _reg_offsets["r23"] = 184 + _reg_offsets["r24"] = 192 + _reg_offsets["r25"] = 200 + _reg_offsets["r26"] = 208 + _reg_offsets["r27"] = 216 + _reg_offsets["r28"] = 224 + _reg_offsets["r29"] = 232 + _reg_offsets["r30"] = 240 + _reg_offsets["r31"] = 248 + _reg_offsets["nip"] = 256 + _reg_offsets["msr"] = 264 + _reg_offsets["orig_gpr3"] = 272 + _reg_offsets["ctr"] = 280 + _reg_offsets["link"] = 288 + _reg_offsets["xer"] = 296 + _reg_offsets["ccr"] = 304 + _reg_offsets["softe"] = 312 + _reg_offsets["trap"] = 320 + _reg_offsets["dar"] = 328 + _reg_offsets["dsisr"] = 336 + _reg_offsets["result"] = 344 + + /* + * If we ever need to support 32bit powerpc, we can + * get to the register offsets by using just a + * reg32_offset = _reg_offsets["reg"]/2 + * or somesuch + */ + _stp_regs_registered = 1 +} + +function _stp_get_register_by_offset:long (offset:long) %{ + long value; + memcpy(&value, ((char *)CONTEXT->regs) + THIS->offset, sizeof(value)); + THIS->__retvalue = value; +%} + +function _stp_sign_extend32:long (value:long) { + if (value & 0x80000000) + value |= (0xffffffff << 32) + return value +} + +function _stp_probing_32bit_app() %{ + if (!(CONTEXT->regs)) + return 0; + return (user_mode(CONTEXT->regs) && + test_tsk_thread_flag(current, TIF_32BIT)); +%} + +function _stp_register:long (name:string, sign_extend:long) { + if (!_stp_regs_registered) + _stp_register_regs() + offset = _reg_offsets[name] + if (offset == 0 && !(name in _reg_offsets)) { + error("Unknown register: " . name) + return 0 + } + value = _stp_get_register_by_offset(offset) + if (_stp_probing_32bit_app()) { + if (sign_extend) + value = _stp_sign_extend32(value) + else + value &= 0xffffffff + } + return value +} + +/* Return the named register value as a signed value. */ +function register:long (name:string) { + return _stp_register(name, 1) +} + +/* + * Return the named register value as an unsigned value. Specifically, + * don't sign-extend the register value when promoting it to 64 bits. + */ +function u_register:long (name:string) { + return _stp_register(name, 0) +} + +/* + * Return the value of function arg #argnum (1=first arg). + * If truncate=1, mask off the top 32 bits. + * If sign_extend=1 and (truncate=1 or the probepoint we've hit is in a + * 32-bit app), sign-extend the 32-bit value. + */ +function _stp_arg:long (argnum:long, sign_extend:long, truncate:long) %{ + long val; + int n; + size_t argsz = sizeof(long); + + THIS->__retvalue = 0; + if (!CONTEXT->regs) { + snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), + "cannot access function args in this context"); + CONTEXT->last_error = CONTEXT->error_buffer; + return; + } + if (THIS->argnum < 1) + goto bad_argnum; + n = (int) THIS->argnum; + + switch (n) { + case 1: + val = u_register("r3"); + break; + case 2: + val = u_register("r4"); + break; + case 3: + val = u_register("r5"); + break; + case 4: + val = u_register("r6"); + break; + case 5: + val = u_register("r7"); + break; + case 6: + val = u_register("r8"); + break; + case 7: + val = u_register("r9"); + break; + case 8: + val = u_register("r10"); + break; + default: + goto bad_argnum; + } + if (THIS->truncate || argsz == sizeof(int)) { + if (THIS->sign_extend) + THIS->__retvalue = (int64_t) _stp_sign_extend32(val); + else + /* High bits may be garbage. */ + THIS->__retvalue = (int64_t) (val & 0xffffffff); + } else + THIS->__retvalue = (int64_t) val; + return; + +bad_argnum: + snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), + "cannot access arg(%lld)", THIS->argnum); + CONTEXT->last_error = CONTEXT->error_buffer; + return; +%} + +/* Return the value of function arg #argnum (1=first arg) as a signed int. */ +function int_arg:long (argnum:long) { + return _stp_arg(argnum, 1, 1) +} + +/* Return the value of function arg #argnum (1=first arg) as an unsigned int. */ +function uint_arg:long (argnum:long) { + return _stp_arg(argnum, 0, 1) +} + +function long_arg:long (argnum:long) { + return _stp_arg(argnum, 1, 0) +} + +function ulong_arg:long (argnum:long) { + return _stp_arg(argnum, 0, 0) +} + +function longlong_arg:long (argnum:long) { + if (_stp_probing_32bit_app()) { + lowbits = _stp_arg(argnum, 0, 1) + highbits = _stp_arg(argnum+1, 0, 1) + return ((highbits << 32) | lowbits) + } else + return _stp_arg(argnum, 0, 0) +} + +function ulonglong_arg:long (argnum:long) { + return longlong_arg(argnum) +} + +function pointer_arg:long (argnum:long) { + return _stp_arg(argnum, 0, 0) +} + +function s32_arg:long (argnum:long) { + return int_arg(argnum) +} + +function u32_arg:long (argnum:long) { + return uint_arg(argnum) +} + +function s64_arg:long (argnum:long) { + return longlong_arg(argnum) +} + +function u64_arg:long (argnum:long) { + return ulonglong_arg(argnum) +} + +function asmlinkage() { +} + +function fastcall() { +} + +function regparm() %{ + snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), + "regparm is invalid on powerpc."); + CONTEXT->last_error = CONTEXT->error_buffer; +%} |