Browse Source

tigcclib: add PtrToHandle (TIGCCLIB implementation of kernel::Ptr2Hd).
examples: add a usage example / regression test for PtrToHandle & the estack_max_index address hack.

git-svn-id: file:///var/svn/tigccpp/trunk@1345 9552661e-59e3-4036-b4f2-dbe53926924f

debrouxl 15 years ago
parent
commit
80c122cbe9

+ 90 - 0
tigcc/archive/ptrtohandle.s

@@ -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

+ 1 - 0
tigcc/archive/tigcc.tpr

@@ -435,6 +435,7 @@ GNU Assembler File 216 Folder=startup
 GNU Assembler File 217=sprite8.s
 GNU Assembler File 218=sprite16.s
 GNU Assembler File 219=sprite32.s
+GNU Assembler File 220=ptrtohandle.s
 Text File 1=License.txt
 Text File 2=startup\Startup.txt
 Text File 2 Folder=startup

+ 12 - 7
tigcc/doc/System/Include/alloc.h/HeapPtrToHandle.hsf

@@ -4,6 +4,7 @@ Type=Function
 Subtype=ROM Call
 Header Files=alloc.h
 Definition=HANDLE HeapPtrToHandle (void *Ptr);
+See Also=alloc.h/PtrToHandle
 
 [ROM Call]
 Index=$23A
@@ -12,10 +13,14 @@ Index=$23A
 Determines the handle associated with a block.
 
 [Explanation]
-HeapPtrToHandle returns the handle which is associated with a block that is
-pointed to by <I>Ptr</I> (or <A HREF="$$LINK(alloc.h/H_NULL)">H_NULL</A> if there is not a handle
-that references the given block).
-This routine works by searching the entire table of handles for the given pointer,
-and so should be used accordingly. It assumes that the heap has not been compressed
-since the dereferenced pointer was
-originally obtained or the block it points to is locked.
+HeapPtrToHandle returns the handle associated to the block whose beginning is
+pointed to by <I>Ptr</I> (or <A HREF="$$LINK(alloc.h/H_NULL)">H_NULL</A> if <I>Ptr</I>
+does not point to the beginning of a block).
+<BR>
+This routine works by searching the entire table of handles for the given pointer.
+It will return meaningful results only if the block of memory was not moved (e.g. by heap
+compression) since the pointer was originally obtained.
+<BR>
+<B>Note:</B> <A HREF="$$LINK(alloc.h/PtrToHandle)">PtrToHandle</A>, implemented in the
+TIGCC library, returns the handle associated to the block referenced by the pointer,
+even if the pointer does not point to the beginning of the block.

+ 33 - 0
tigcc/doc/System/Include/alloc.h/PtrToHandle.hsf

@@ -0,0 +1,33 @@
+[Main]
+Name=PtrToHandle
+Type=Function
+Subtype=tigcc.a
+Header Files=alloc.h
+Definition=HANDLE PtrToHandle (void *Ptr);
+See Also=alloc.h/HeapPtrToHandle
+
+[Registers]
+Ptr=a0
+
+[Library Call]
+Asm=1
+TIOS Callback=0
+
+[Description]
+Determines the handle associated with a block.
+
+[Explanation]
+PtrToHandle returns the handle associated to the block pointed to by <I>Ptr</I>
+(or <A HREF="$$LINK(alloc.h/H_NULL)">H_NULL</A> if <I>Ptr</I> does not point within a block).
+<BR>
+This routine will return meaningful results only if the block of memory was not moved (e.g.
+by heap compression) since the pointer was originally obtained.
+<BR>
+The following program shows the difference between <A HREF="$$LINK(alloc.h/HeapPtrToHandle)">HeapPtrToHandle</A>
+and PtrToHandle:
+$$EXAMPLE(Pointer To Handle.c)
+
+
+[References]
+Out=alloc.h/HeapDeref, alloc.h/HeapSize
+

+ 37 - 0
tigcc/examples/Pointer To Handle.c

@@ -0,0 +1,37 @@
+// Return the EStack handle.
+
+#define USE_TI89              // Compile for TI-89
+#define USE_TI92PLUS          // Compile for TI-92 Plus
+#define USE_V200              // Compile for V200
+
+#define RETURN_VALUE          // Return Pushed Expression
+#define MIN_AMS 101           // Compile for AMS 1.01 or higher
+
+#include <tigcclib.h>         // Include All Header Files
+
+// Main Function
+void _main(void)
+{
+  push_END_TAG ();
+  push_END_TAG ();
+  // Outside all allocated blocks.
+  push_shortint (HeapPtrToHandle((void *)1));
+  // Strictly inside a block.
+  push_shortint (HeapPtrToHandle((void *)estack_max_index));
+  // Strictly inside a block, must be the same handle as estack_max_index.
+  push_shortint (HeapPtrToHandle((void *)top_estack));
+  // Beginning of a block.
+  push_shortint (PtrToHandle(HeapDeref(1)));
+  push_LIST_TAG ();
+  push_END_TAG ();
+  // Outside all allocated blocks.
+  push_shortint (PtrToHandle((void *)1));
+  // Strictly inside a block.
+  push_shortint (PtrToHandle((void *)estack_max_index));
+  // Strictly inside a block, must be the same handle as estack_max_index.
+  push_shortint (PtrToHandle((void *)top_estack));
+  // Beginning of a block.
+  push_shortint (PtrToHandle(HeapDeref(1)));
+  push_LIST_TAG ();
+  push_LIST_TAG ();
+}

+ 59 - 0
tigcc/examples/Pointer To Handle.tpr

@@ -0,0 +1,59 @@
+[Settings]
+Archive=0
+Pack=0
+Packed Variable=
+Project Name=ptr2hd
+GCC Switches=-Os -Wall -W -Wwrite-strings -ffunction-sections -fdata-sections
+Assembler Switches=-g -t
+GNU Assembler Switches=
+Debug Info=0
+Standard Library=1
+Command Line=
+Post-Build Process=
+Use Data Variable=0
+Data Variable=
+Copy Data Variable=1
+Copy Data Variable if Archived=1
+Optimize NOPs=1
+Optimize Returns=1
+Optimize Branches=1
+Optimize Moves=1
+Optimize Tests=1
+Optimize Calculations=1
+Remove Unused Sections=1
+Binary Output=0
+Fargo=0
+Flash OS=0
+Cut Unused Ranges=1
+Reorder Sections=1
+Merge Constants=1
+Initialize BSS=1
+
+[Library Options]
+Use TI-89=0
+Use TI-92 Plus=0
+Use V200=0
+Optimize Calc Consts=0
+Use Kernel=0
+Use PreOS=0
+Minimum AMS Version Defined=0
+Minimum AMS Version=1.01
+Unofficial OS Support=0
+Reloc Format=AMS
+ROM Call Format=Direct
+BSS Ref Format=Kernel
+Data Ref Format=Kernel
+Use F-Line Jumps=0
+Use 4-Byte F-Line Jumps=0
+Use Internal F-Line Emulator=0
+Use Return Value=0
+Enable Error Return=0
+Save Screen=0
+Optimize ROM Calls=0
+
+[File Editing]
+Open File=
+
+[Included Files]
+C File 1=Pointer To Handle.c
+

+ 1 - 0
tigcc/examples/build.sh

@@ -49,6 +49,7 @@ tprbuilder -q "Menu Example 1.tpr"; if [ $? -ne 0 ]; then echo FAILED building "
 tprbuilder -q "Menu Example 2.tpr"; if [ $? -ne 0 ]; then echo FAILED building "\"Menu Example 2.tpr\""; fi
 tprbuilder -q "Multiply Polynoms.tpr"; if [ $? -ne 0 ]; then echo FAILED building "\"Multiply Polynoms.tpr\""; fi
 tprbuilder -q "Othello-Reversi.tpr"; if [ $? -ne 0 ]; then echo FAILED building "\"Othello-Reversi.tpr\""; fi
+tprbuilder -q "Pointer To Handle.tpr"; if [ $? -ne 0 ]; then echo FAILED building "\"Pointer To Handle.tpr\""; fi
 tprbuilder -q "Popup Menu Example.tpr"; if [ $? -ne 0 ]; then echo FAILED building "\"Popup Menu Example.tpr\""; fi
 tprbuilder -q "Pretty Print.tpr"; if [ $? -ne 0 ]; then echo FAILED building "\"Pretty Print.tpr\""; fi
 tprbuilder -q "Print EStack.tpr"; if [ $? -ne 0 ]; then echo FAILED building "\"Print EStack.tpr\""; fi