changeset 102:b7a9b524f0c3

- mips o32 callbacks, first draft (calls into handler correctly, with correct params, but doesn't return)
author cslag
date Tue, 07 Jun 2016 09:05:34 +0200
parents 1ce60358fbad
children b15d814ba274
files dyncallback/dyncall_args.c dyncallback/dyncall_args_mips.c dyncallback/dyncall_args_mips.h dyncallback/dyncall_args_mips_o32.c dyncallback/dyncall_callback_mips_gas.S dyncallback/dyncall_callback_mips_o32_gas.s
diffstat 6 files changed, 193 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/dyncallback/dyncall_args.c	Tue Jun 07 07:34:37 2016 +0200
+++ b/dyncallback/dyncall_args.c	Tue Jun 07 09:05:34 2016 +0200
@@ -42,7 +42,11 @@
 #elif defined (DC__Arch_ARM_THUMB)
 #  include "dyncall_args_arm32_thumb.c"
 #elif defined (DC__Arch_MIPS)
-#  include "dyncall_args_mips.c"
+#  if defined(DC__ABI_MIPS_O32)
+#    include "dyncall_args_mips_o32.c"
+#  else
+#    include "dyncall_args_mips.c"
+#  endif
 #elif defined (DC__Arch_Sparc)
 #  include "dyncall_args_sparc32.c"
 #elif defined (DC__Arch_Sparcv9)
--- a/dyncallback/dyncall_args_mips.c	Tue Jun 07 07:34:37 2016 +0200
+++ b/dyncallback/dyncall_args_mips.c	Tue Jun 07 09:05:34 2016 +0200
@@ -26,11 +26,11 @@
 
 #include "dyncall_args_mips.h"
 
-DCint dcbArgInt(DCArgs* p) 
+DCint dcbArgInt(DCArgs* p)
 {
   DCint value;
-  if(p->ireg_count < 8)
-    value = p->ireg_data[p->ireg_count++];
+  if(p->reg_count.i < DCARGS_MIPS_PARAM_REGS)
+    value = p->reg_data.i[p->reg_count.i++];
   else {
     value = *((int*)p->stackptr);
     p->stackptr += sizeof(int);
@@ -39,12 +39,17 @@
 }
 DCuint dcbArgUInt(DCArgs* p) { return (DCuint)dcbArgInt(p); }
 
-DCulonglong dcbArgULongLong(DCArgs* p) 
+DCulonglong dcbArgULongLong(DCArgs* p)
 {
   DCulonglong value;
-  p->ireg_count += (p->ireg_count & 1); // Skip one reg if not aligned.
+  p->reg_count.i += (p->reg_count.i & 1); // Skip one reg if not aligned.
+#if defined(DC__Endian_LITTLE)
   value  = ((DCulonglong)dcbArgUInt(p)) << 32;
   value |= dcbArgUInt(p);
+#else
+  value  = dcbArgUInt(p);
+  value |= ((DCulonglong)dcbArgUInt(p)) << 32;
+#endif
   return value;
 }
 DClonglong dcbArgLongLong(DCArgs* p) { return (DClonglong)dcbArgULongLong(p); }
@@ -59,24 +64,30 @@
 DCpointer   dcbArgPointer(DCArgs* p) { return (DCpointer)dcbArgUInt(p); }
 
 DCfloat dcbArgFloat(DCArgs* p)
-{ 
+{
   DCfloat result;
-  if(p->freg_count < 8)
-    result = (DCfloat)p->freg_data[p->freg_count++];
+  if(p->reg_count.f < DCARGS_MIPS_PARAM_REGS)
+    result = (DCfloat)p->reg_data.f[p->reg_count.f++];
   else {
     result = *((float*)p->stackptr);
     p->stackptr += sizeof(float);
   }
-  return result; 
+  return result;
 }
-DCdouble dcbArgDouble(DCArgs* p) 
-{ 
+DCdouble dcbArgDouble(DCArgs* p)
+{
   union {
     DCdouble result;
     DCfloat f[2];
   } d;
-  p->freg_count += (p->freg_count & 1); // Skip one reg if not aligned.
+  p->reg_count.f += (p->reg_count.f & 1); // Skip one reg if not aligned.
+#if defined(DC__Endian_LITTLE)
   d.f[0] = dcbArgFloat(p);
   d.f[1] = dcbArgFloat(p);
+#else
+  d.f[1] = dcbArgFloat(p);
+  d.f[0] = dcbArgFloat(p);
+#endif
   return d.result;
 }
+
--- a/dyncallback/dyncall_args_mips.h	Tue Jun 07 07:34:37 2016 +0200
+++ b/dyncallback/dyncall_args_mips.h	Tue Jun 07 09:05:34 2016 +0200
@@ -29,13 +29,20 @@
 
 #include "dyncall_args.h"
 
+#if !defined(DC__ABI_MIPS_O32)
+#  define DCARGS_MIPS_PARAM_REGS 4
+#else
+#  define DCARGS_MIPS_PARAM_REGS 8
+#endif
+
 struct DCArgs
 {
-  int            ireg_data[8];
-  float          freg_data[8];
-  int            ireg_count;
-  int            freg_count;
-  unsigned char* stackptr;
+	/* Don't change order! */
+#if !defined(DC__ABI_MIPS_O32)
+	struct { int i; float f; } reg_data[DCARGS_MIPS_PARAM_REGS];
+	struct { int i; int   f; } reg_count;
+#endif
+	unsigned char* stackptr;
 };
 
 #endif /* DYNCALLBACK_ARGS_MIPS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dyncallback/dyncall_args_mips_o32.c	Tue Jun 07 09:05:34 2016 +0200
@@ -0,0 +1,85 @@
+/*
+
+ Package: dyncall
+ Library: dyncallback
+ File: dyncallback/dyncall_args_mips.c
+ Description: Callback's Arguments VM - Implementation for MIPS
+ License:
+
+   Copyright (c) 2013-2015 Daniel Adler <dadler@uni-goettingen.de>,
+                           Tassilo Philipp <tphilipp@potion-studios.com>
+
+   Permission to use, copy, modify, and distribute this software for any
+   purpose with or without fee is hereby granted, provided that the above
+   copyright notice and this permission notice appear in all copies.
+
+   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+
+#include "dyncall_args_mips.h"
+
+DCint dcbArgInt(DCArgs* p)
+{
+  DCint value;
+  value = *((int*)p->stackptr);
+  p->stackptr += sizeof(int);
+  return value;
+}
+DCuint dcbArgUInt(DCArgs* p) { return (DCuint)dcbArgInt(p); }
+
+DCulonglong dcbArgULongLong(DCArgs* p)
+{
+  DCulonglong value;
+  p->stackptr += ((int)p->stackptr & 4); // Skip one slot if not aligned.
+#if defined(DC__Endian_LITTLE)
+  value  = dcbArgUInt(p);
+  value |= ((DCulonglong)dcbArgUInt(p)) << 32;
+#else
+  value  = ((DCulonglong)dcbArgUInt(p)) << 32;
+  value |= dcbArgUInt(p);
+#endif
+  return value;
+}
+DClonglong dcbArgLongLong(DCArgs* p) { return (DClonglong)dcbArgULongLong(p); }
+
+DClong      dcbArgLong   (DCArgs* p) { return (DClong)   dcbArgUInt(p); }
+DCulong     dcbArgULong  (DCArgs* p) { return (DCulong)  dcbArgUInt(p); }
+DCchar      dcbArgChar   (DCArgs* p) { return (DCchar)   dcbArgUInt(p); }
+DCuchar     dcbArgUChar  (DCArgs* p) { return (DCuchar)  dcbArgUInt(p); }
+DCshort     dcbArgShort  (DCArgs* p) { return (DCshort)  dcbArgUInt(p); }
+DCushort    dcbArgUShort (DCArgs* p) { return (DCushort) dcbArgUInt(p); }
+DCbool      dcbArgBool   (DCArgs* p) { return (DCbool)   dcbArgUInt(p); }
+DCpointer   dcbArgPointer(DCArgs* p) { return (DCpointer)dcbArgUInt(p); }
+
+DCfloat dcbArgFloat(DCArgs* p)
+{
+  DCfloat result;
+  result = *((float*)p->stackptr);
+  p->stackptr += sizeof(float);
+  return result;
+}
+DCdouble dcbArgDouble(DCArgs* p)
+{
+  union {
+    DCdouble result;
+    DCfloat f[2];
+  } d;
+  p->stackptr += ((int)p->stackptr & 4); // Skip one slot if not aligned.
+#if defined(DC__Endian_LITTLE)
+  d.f[0] = dcbArgFloat(p);
+  d.f[1] = dcbArgFloat(p);
+#else
+  d.f[1] = dcbArgFloat(p);
+  d.f[0] = dcbArgFloat(p);
+#endif
+  return d.result;
+}
+
--- a/dyncallback/dyncall_callback_mips_gas.S	Tue Jun 07 07:34:37 2016 +0200
+++ b/dyncallback/dyncall_callback_mips_gas.S	Tue Jun 07 09:05:34 2016 +0200
@@ -24,13 +24,15 @@
 
 
 
-#if defined(DC__ABI_MIPS_O32)
-#include "dyncall_callback_mips_o32_gas.s"
+#if defined(DC__ABI_MIPS_EABI)
+#  include "dyncall_callback_mips_eabi_gas.s"
+#elif defined(DC__ABI_MIPS_O32)
+#  include "dyncall_callback_mips_o32_gas.s"
 #elif defined(DC__ABI_MIPS_N64)
-#include "dyncall_callback_mips_n64_gas.s"
+#  include "dyncall_callback_mips_n64_gas.s"
 #elif defined(DC__ABI_MIPS_N32)
-#include "dyncall_callback_mips_n32_gas.s"
+#  include "dyncall_callback_mips_n32_gas.s"
 #else
-#include "dyncall_callback_mips_eabi_gas.s"
+#  error Unknown MIPS ABI.
 #endif
 
--- a/dyncallback/dyncall_callback_mips_o32_gas.s	Tue Jun 07 07:34:37 2016 +0200
+++ b/dyncallback/dyncall_callback_mips_o32_gas.s	Tue Jun 07 09:05:34 2016 +0200
@@ -3,7 +3,7 @@
  Package: dyncall
  Library: dyncallback
  File: dyncallback/dyncall_callback_mips_o32_gas.s
- Description: Callback Thunk - Implementation mips o32
+ Description: Callback Thunk - Implementation mips32 o32
  License:
 
    Copyright (c) 2016 Tassilo Philipp <tphilipp@potion-studios.com>
@@ -22,13 +22,66 @@
 
 */
 
-    .section .mdebug.abi32
-    .previous
-    .abicalls
-    .text
-    .align  2
+	/* input:
+		$t4    -> thunk
+		$t4+20 -> cb handler
+		$t4+24 -> userdata
+	*/
+
+	.section .mdebug.abi32
+	.previous
+	.abicalls
+	.text
+	.align  2
 	.globl dcCallbackThunkEntry
-    .ent   dcCallbackThunkEntry
-    .type  dcCallbackThunkEntry, @function
+	.ent   dcCallbackThunkEntry
+	.type  dcCallbackThunkEntry, @function
+
+/* Called by thunk - thunk stores pointer to DCCallback in $12 ($t4), and pointer to called function in $25 ($t9, required for PIC) */
 dcCallbackThunkEntry:
+	.frame  $fp,32,$31      /* infos for debugger: reg use, sizes, */
+	/*.mask   0x00000000,0    /* int stack usage, */
+	/*.fmask  0x00000000,0    /* fp stack usage */
+	.set    noreorder
+	.set    nomacro
 
+	/* Prolog. Just store the minimum, return address, frame pointer, spill area. */
+	addiu $sp, $sp, -32   /* open frame: 32b for 8b aligned frame (retval+ra+fp+spill) */
+	sw    $ra, 20($sp)    /* save link register */
+	sw    $fp, 16($sp)    /* save frame pointer */
+	nop
+	move  $fp, $sp        /* frame pointer = sp */
+
+	/* Since all arguments are in one consecutive block, we'll pass the pointer  */
+	/* to them as second argument to the callback handler. Caller doesn't spill  */
+	/* though, so let's write $4-$7 ($a0-$a3) to the dedicated spill area, first */
+	/* (which is in _caller's_ frame).                                                  */
+	sw $7, 44($sp)
+	sw $6, 40($sp)
+	sw $5, 36($sp)
+	sw $4, 32($sp)
+
+	/* Prepare callback handler call. */
+	move  $4, $12        /* Param 0 = DCCallback*, $12 ($t4) holds pointer to thunk */
+	addiu $5, $sp, 16    /* Param 1 = DCArgs*, basically location of where fp is stored */
+	addiu $6, $sp, 24    /* Param 2 = results pointer to 8b of local data on stack */
+	lw    $7, 24($12)    /* Param 3 = userdata pointer */
+
+	lw    $25, 20($12)    /* store handler entry in $25 ($t9) */
+	jalr  $25             /* jump */
+	nop
+
+	/* Epilog. Tear down frame and return. */
+	move  $sp, $fp      /* restore stack pointer */
+	nop
+	lw    $ra, 20($sp)  /* restore return address */
+	lw    $fp, 16($sp)  /* restore frame pointer */
+	addiu $sp, $sp, 32  /* close frame */
+	j     $ra           /* return */
+	nop
+
+	.set    macro
+	.set    reorder
+	.end    dcCallbackThunkEntry
+	.ident  "handwritten"
+