For fun, I attempted to analyze a function with a friend who's a total Pokemon geek and came up with the following, which I figure I'll post here (no guarantee on accuracy):
; after using a move, decrement pp in battle and (if not transformed?) in party
ld a,[de] ; load some variable?
cp a,STRUGGLE ; Check to see if the move we used was "struggle".
ret z ; If the pokemon is using "struggle", there's nothing to do, so return,
; since we don't decrement PP for "struggle".
ld a,[hli] ; load the D062 Pokemon status flags and increment hl to load the
; D063 status flags later.
and a,7 ; check to see if bits 0, 1, or 2 are set.
ret nz ; If any of these statuses are true, don't decrement PP.
bit 6,[hl] ; check bit 6 of the D063 status flags too.
ret nz ; And return if it's set.
; bit 2 of D062: multiple-hit moves, like Wrap?
; bit 1 of D062: Thrashing about, I think?
; bit 0 of D062: paralyzed?
; bit 6 of D063: ?
ld hl,$D02D ; load the address of the first move of the current pokemon
call .DecrementPP\@ ; call the function (below) to actually decrement the PP
ld a,[$D064] ; load Pokemon status bits?
bit 3,a ; Is the pokemon transformed?
ret nz ; If it is, return. Pokemon Red stores the "current pokemon's" PP
; separately from the "Pokemon in your party's" PP. This is
; duplication -- in all cases *other* than Pokemon with Transform.
; Normally, this means we have to go on and make the same
; modification to the "party's pokemon" PP that we made to the
; "current pokemon's" PP. But, if we're dealing with a Transformed
; Pokemon, it has separate PP for the move set that it copied from
; its opponent, which is *not* the same as its real PP as part of your
; party. So we return, and don't do that part.
ld hl,$D188 ; load the address of the first move of the first pokemon in the party
ld a,[$CC2F] ; which pokemon in party is active
ld bc,$2C ; $2C is the size of one Pokemon's data structure, I assume?
call AddNTimes ; calculate the address of the mon to modify
; fall through into DecrementPP\@, to avoid calling it again.
ld a,[$CC2E] ; which move (0, 1, 2, 3) did we use?
add hl,bc ; calculate the address in memory of the PP we need to decrement,
; based on the move chosen.
dec [hl] ; Decrement PP