123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- | This routine returns the HANDLE of the block containing the address
- | where the given pointer points to, or H_NULL if there's no such block.
- |
- | This routine is NOT a duplicate of HeapPtrToHandle: unlike HeapPtrToHandle,
- | PtrToHandle can meaningfully handle pointers that do not point to the
- | beginning of the block.
- | Kernels have provided PtrToHandle for years as "Ptr2Hd".
- |
- | Copyright (C) Lionel Debroux 2003 (contribution to TIGCC)
- | Copyright (C) Lionel Debroux 2009 (rename, modifications & integration to GCC4TI).
- |
- | Equivalent C code:
- /*
- HANDLE PtrToHandle(void *ptr asm("d0"))
- {
- HANDLE h = H_NULL;
- void *ptr2;
- while (h < 2000)
- {
- h++;
- ptr2 = HeapDeref(h);
- if (ptr >= ptr2 && (unsigned char *)ptr < (unsigned char *)ptr2 + HeapSize(h)) return h;
- }
- return H_NULL;
- }
- */
- .text
- .even
- .globl PtrToHandle
- PtrToHandle:
- movem.l %d3-%d4/%a2-%a4,-(%sp)
- | Save the pointer into non-call-clobbered a2.
- movea.l %a0,%a2
- | Put the addresses of HeapDeref and HeapSize in the registers.
- movea.l 0xC8.w,%a4
- movea.l 0x96*4(%a4),%a3 | HeapDeref.
- movea.l 0x9E*4(%a4),%a4 | HeapSize.
-
- | We'll check handles 1-1999 in ascending order, because:
- | * HeapSize(H_NULL) crashes the calculator;
- | * since handles are allocated in ascending order, pointers pointing to an
- | allocated memory area will be found more quickly.
- | Checking the handles in ascending order yields a larger routine, though.
- clr.w -(%sp)
- move.w #2000,%d3
- .L__PtrToHandle_loop:
- | In theory, we should re-create the argument each time HeapDeref is called and each time HeapSize is called.
- | This is because callees, among which AMS functions, _can_ destroy their stack arguments...
- | Neither HeapDeref nor HeapSize has ever done so, be it on AMS (discontinued) or PedroM (which behaves the
- | same way as AMS does, for compatibility and implementation sanity reasons).
- addq.w #1,(%sp)
- cmp.w (%sp),%d3
- beq.s .L__PtrToHandle_not_found
- | We've not run out of the heap table yet.
- jsr (%a3) | HeapDeref.
- | If this handle is not allocated, skip it, so as not to emulate the bug of HeapPtrToHandle(NULL) returning
- | the index of the first free entry in the heap table (instead of H_NULL, which would make more sense, as NULL
- | doesn't belong to any block). This matches the behaviour of kernel::Ptr2Hd.
- move.l %a0,%d4
- beq.s .L__PtrToHandle_loop
- | If a2 < the lowest address of the current handle, the current handle is not the one we're looking for.
- cmpa.l %d4,%a2
- blt.s .L__PtrToHandle_loop
- | a2 >= the lowest address of the current handle.
- jsr (%a4) | HeapSize.
- add.l %d0,%d4
- | If a2 >= the lowest address and < the highest address, the current handle is the one we're looking for.
- cmp.l %a2,%d4
- blt.s .L__PtrToHandle_loop
- | Found the handle.
- move.w (%sp)+,%d0
- .L__PtrToHandle_end:
- movem.l (%sp)+,%d3-%d4/%a2-%a4
- rts
- | The whole heap table was traversed, but no handle was found. Return H_NULL.
- .L__PtrToHandle_not_found:
- moveq #0,%d0
- addq.l #2,%sp
- bra.s .L__PtrToHandle_end
|