|
@@ -0,0 +1,90 @@
|
|
|
+| 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
|