Browse Source

Add XBox 360 port.

Thanks to Eddie Edwards.
Mike Pall 12 years ago
parent
commit
89e4650bae
9 changed files with 232 additions and 24 deletions
  1. 27 5
      doc/install.html
  2. 1 1
      doc/luajit.html
  3. 6 0
      src/host/buildvm.c
  4. 25 9
      src/host/buildvm_peobj.c
  5. 1 1
      src/lj_arch.h
  6. 29 3
      src/lj_def.h
  7. 10 1
      src/lj_frame.h
  8. 42 4
      src/vm_ppc.dasc
  9. 91 0
      src/xedkbuild.bat

+ 27 - 5
doc/install.html

@@ -134,9 +134,9 @@ operating systems, CPUs and compilers:
 <tr class="even">
 <tr class="even">
 <td class="compatcpu"><a href="#cross2">PPC</a></td>
 <td class="compatcpu"><a href="#cross2">PPC</a></td>
 <td class="compatos">GCC 4.3+</td>
 <td class="compatos">GCC 4.3+</td>
-<td class="compatos">GCC 4.3+<br>GCC 4.1 (<a href="#cross2">PS3</a>)</td>
-<td class="compatos compatno">&nbsp;</td>
+<td class="compatos">GCC 4.3+<br>GCC 4.1 (<a href="#ps3">PS3</a>)</td>
 <td class="compatos compatno">&nbsp;</td>
 <td class="compatos compatno">&nbsp;</td>
+<td class="compatos">XEDK (<a href="#xbox360">XBox 360</a>)</td>
 </tr>
 </tr>
 <tr class="odd">
 <tr class="odd">
 <td class="compatcpu"><a href="#cross2">PPC/e500v2</a></td>
 <td class="compatcpu"><a href="#cross2">PPC/e500v2</a></td>
@@ -376,7 +376,7 @@ CPU.
 make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
 make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
      TARGET_CFLAGS="-mfloat-abi=soft"
      TARGET_CFLAGS="-mfloat-abi=soft"
 
 
-# ARM soft-float ABI with VFP (example for Cortex-a8)
+# ARM soft-float ABI with VFP (example for Cortex-A8)
 make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
 make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
      TARGET_CFLAGS="-mcpu=cortex-a8 -mfloat-abi=softfp"
      TARGET_CFLAGS="-mcpu=cortex-a8 -mfloat-abi=softfp"
 
 
@@ -387,8 +387,6 @@ make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabihf-
 make HOST_CC="gcc -m32" CROSS=powerpc-linux-gnu-
 make HOST_CC="gcc -m32" CROSS=powerpc-linux-gnu-
 # PPC/e500v2 (fast interpreter only)
 # PPC/e500v2 (fast interpreter only)
 make HOST_CC="gcc -m32" CROSS=powerpc-e500v2-linux-gnuspe-
 make HOST_CC="gcc -m32" CROSS=powerpc-e500v2-linux-gnuspe-
-# PS3 (fast interpreter only)
-make HOST_CC="gcc -m32" CROSS=ppu-lv2-
 
 
 # MIPS big-endian
 # MIPS big-endian
 make HOST_CC="gcc -m32" CROSS=mips-linux-
 make HOST_CC="gcc -m32" CROSS=mips-linux-
@@ -460,6 +458,30 @@ ISDKF="-arch armv7 -isysroot $ISDK/SDKs/$ISDKVER"
 make HOST_CC="gcc -m32 -arch i386" CROSS=$ISDKP TARGET_FLAGS="$ISDKF" \
 make HOST_CC="gcc -m32 -arch i386" CROSS=$ISDKP TARGET_FLAGS="$ISDKF" \
      TARGET_SYS=iOS
      TARGET_SYS=iOS
 </pre>
 </pre>
+<p>
+You can cross-compile for <b id="ps3">PS3</b> using the PS3&nbsp;SDK from
+a Linux host or a Windows host (requires 32 bit MinGW (GCC) on the host,
+too). Due to restrictions on consoles, the JIT compiler is disabled and
+only the fast interpreter is built:
+</p>
+<pre class="code">
+make HOST_CC="gcc -m32" CROSS=ppu-lv2-
+</pre>
+<p>
+You can cross-compile for <b id="xbox360">XBox 360</b> using the
+XBox&nbsp;360 SDK (MSVC + XEDK). Due to restrictions on consoles, the
+JIT compiler is disabled and only the fast interpreter is built.
+</p>
+<p>
+Open a "Visual Studio .NET Command Prompt" (32&nbsp;bit host compiler),
+<tt>cd</tt> to the directory where you've unpacked the sources and run
+the following commands. This builds a static library <tt>luajit20.lib</tt>,
+which can be linked against your game, just like the Lua library.
+</p>
+<pre class="code">
+cd src
+xedkbuild
+</pre>
 
 
 <h2 id="embed">Embedding LuaJIT</h2>
 <h2 id="embed">Embedding LuaJIT</h2>
 <p>
 <p>

+ 1 - 1
doc/luajit.html

@@ -158,7 +158,7 @@ LuaJIT is Copyright &copy; 2005-2012 Mike Pall, released under the
 <tr><td>Windows</td><td>Linux</td><td>BSD</td><td>OSX</td><td>POSIX</td></tr>
 <tr><td>Windows</td><td>Linux</td><td>BSD</td><td>OSX</td><td>POSIX</td></tr>
 </table>
 </table>
 <table class="feature os os2">
 <table class="feature os os2">
-<tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td><td>PS3</td></tr>
+<tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td><td>PS3</td><td>XBox 360</td></tr>
 </table>
 </table>
 <table class="feature compiler">
 <table class="feature compiler">
 <tr><td>GCC</td><td>CLANG<br>LLVM</td><td>MSVC</td></tr>
 <tr><td>GCC</td><td>CLANG<br>LLVM</td><td>MSVC</td></tr>

+ 6 - 0
src/host/buildvm.c

@@ -100,6 +100,8 @@ static const char *sym_decorate(BuildCtx *ctx,
   char *p;
   char *p;
 #if LJ_64
 #if LJ_64
   const char *symprefix = ctx->mode == BUILD_machasm ? "_" : "";
   const char *symprefix = ctx->mode == BUILD_machasm ? "_" : "";
+#elif LJ_TARGET_XBOX360
+  const char *symprefix = "";
 #else
 #else
   const char *symprefix = ctx->mode != BUILD_elfasm ? "_" : "";
   const char *symprefix = ctx->mode != BUILD_elfasm ? "_" : "";
 #endif
 #endif
@@ -136,7 +138,11 @@ static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type)
   ctx->reloc[ctx->nreloc].sym = relocmap[idx];
   ctx->reloc[ctx->nreloc].sym = relocmap[idx];
   ctx->reloc[ctx->nreloc].type = type;
   ctx->reloc[ctx->nreloc].type = type;
   ctx->nreloc++;
   ctx->nreloc++;
+#if LJ_TARGET_XBOX360
+  return (int)(ctx->code - addr) + 4;  /* Encode symbol offset of .text. */
+#else
   return 0;  /* Encode symbol offset of 0. */
   return 0;  /* Encode symbol offset of 0. */
+#endif
 }
 }
 
 
 /* Naive insertion sort. Performance doesn't matter here. */
 /* Naive insertion sort. Performance doesn't matter here. */

+ 25 - 9
src/host/buildvm_peobj.c

@@ -9,7 +9,7 @@
 #include "buildvm.h"
 #include "buildvm.h"
 #include "lj_bc.h"
 #include "lj_bc.h"
 
 
-#if LJ_TARGET_X86ORX64
+#if LJ_TARGET_X86ORX64 || LJ_TARGET_PPC
 
 
 /* Context for PE object emitter. */
 /* Context for PE object emitter. */
 static char *strtab;
 static char *strtab;
@@ -84,11 +84,21 @@ typedef struct PEsymaux {
 #define PEOBJ_ARCH_TARGET	0x014c
 #define PEOBJ_ARCH_TARGET	0x014c
 #define PEOBJ_RELOC_REL32	0x14  /* MS: REL32, GNU: DISP32. */
 #define PEOBJ_RELOC_REL32	0x14  /* MS: REL32, GNU: DISP32. */
 #define PEOBJ_RELOC_DIR32	0x06
 #define PEOBJ_RELOC_DIR32	0x06
+#define PEOBJ_RELOC_OFS		0
+#define PEOBJ_TEXT_FLAGS	0x60500020  /* 60=r+x, 50=align16, 20=code. */
 #elif LJ_TARGET_X64
 #elif LJ_TARGET_X64
 #define PEOBJ_ARCH_TARGET	0x8664
 #define PEOBJ_ARCH_TARGET	0x8664
 #define PEOBJ_RELOC_REL32	0x04  /* MS: REL32, GNU: DISP32. */
 #define PEOBJ_RELOC_REL32	0x04  /* MS: REL32, GNU: DISP32. */
 #define PEOBJ_RELOC_DIR32	0x02
 #define PEOBJ_RELOC_DIR32	0x02
 #define PEOBJ_RELOC_ADDR32NB	0x03
 #define PEOBJ_RELOC_ADDR32NB	0x03
+#define PEOBJ_RELOC_OFS		0
+#define PEOBJ_TEXT_FLAGS	0x60500020  /* 60=r+x, 50=align16, 20=code. */
+#elif LJ_TARGET_PPC
+#define PEOBJ_ARCH_TARGET	0x01f2
+#define PEOBJ_RELOC_REL32	0x06
+#define PEOBJ_RELOC_DIR32	0x02
+#define PEOBJ_RELOC_OFS		(-4)
+#define PEOBJ_TEXT_FLAGS	0x60400020  /* 60=r+x, 40=align8, 20=code. */
 #endif
 #endif
 
 
 /* Section numbers (0-based). */
 /* Section numbers (0-based). */
@@ -170,12 +180,6 @@ void emit_peobj(BuildCtx *ctx)
   int i, nrsym;
   int i, nrsym;
   union { uint8_t b; uint32_t u; } host_endian;
   union { uint8_t b; uint32_t u; } host_endian;
 
 
-  host_endian.u = 1;
-  if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) {
-    fprintf(stderr, "Error: different byte order for host and target\n");
-    exit(1);
-  }
-
   sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection);
   sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection);
 
 
   /* Fill in PE sections. */
   /* Fill in PE sections. */
@@ -186,7 +190,7 @@ void emit_peobj(BuildCtx *ctx)
   pesect[PEOBJ_SECT_TEXT].relocofs = sofs;
   pesect[PEOBJ_SECT_TEXT].relocofs = sofs;
   sofs += (pesect[PEOBJ_SECT_TEXT].nreloc = (uint16_t)ctx->nreloc) * PEOBJ_RELOC_SIZE;
   sofs += (pesect[PEOBJ_SECT_TEXT].nreloc = (uint16_t)ctx->nreloc) * PEOBJ_RELOC_SIZE;
   /* Flags: 60 = read+execute, 50 = align16, 20 = code. */
   /* Flags: 60 = read+execute, 50 = align16, 20 = code. */
-  pesect[PEOBJ_SECT_TEXT].flags = 0x60500020;
+  pesect[PEOBJ_SECT_TEXT].flags = PEOBJ_TEXT_FLAGS;
 
 
 #if LJ_TARGET_X64
 #if LJ_TARGET_X64
   memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1);
   memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1);
@@ -236,10 +240,22 @@ void emit_peobj(BuildCtx *ctx)
   owrite(ctx, &pesect, sizeof(PEsection)*PEOBJ_NSECTIONS);
   owrite(ctx, &pesect, sizeof(PEsection)*PEOBJ_NSECTIONS);
 
 
   /* Write .text section. */
   /* Write .text section. */
+  host_endian.u = 1;
+  if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) {
+#if LJ_TARGET_PPC
+    uint32_t *p = (uint32_t *)ctx->code;
+    int n = (int)(ctx->codesz >> 2);
+    for (i = 0; i < n; i++, p++)
+      *p = lj_bswap(*p);  /* Byteswap .text section. */
+#else
+    fprintf(stderr, "Error: different byte order for host and target\n");
+    exit(1);
+#endif
+  }
   owrite(ctx, ctx->code, ctx->codesz);
   owrite(ctx, ctx->code, ctx->codesz);
   for (i = 0; i < ctx->nreloc; i++) {
   for (i = 0; i < ctx->nreloc; i++) {
     PEreloc reloc;
     PEreloc reloc;
-    reloc.vaddr = (uint32_t)ctx->reloc[i].ofs;
+    reloc.vaddr = (uint32_t)ctx->reloc[i].ofs + PEOBJ_RELOC_OFS;
     reloc.symidx = 1+2+ctx->reloc[i].sym;  /* Reloc syms are after .text sym. */
     reloc.symidx = 1+2+ctx->reloc[i].sym;  /* Reloc syms are after .text sym. */
     reloc.type = ctx->reloc[i].type ? PEOBJ_RELOC_REL32 : PEOBJ_RELOC_DIR32;
     reloc.type = ctx->reloc[i].type ? PEOBJ_RELOC_REL32 : PEOBJ_RELOC_DIR32;
     owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
     owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);

+ 1 - 1
src/lj_arch.h

@@ -398,7 +398,7 @@
 #endif
 #endif
 
 
 /* Various workarounds for embedded operating systems. */
 /* Various workarounds for embedded operating systems. */
-#if (defined(__ANDROID__) && !defined(LJ_TARGET_X86ORX64)) || defined(__symbian__)
+#if (defined(__ANDROID__) && !defined(LJ_TARGET_X86ORX64)) || defined(__symbian__) || LJ_TARGET_XBOX360
 #define LUAJIT_NO_LOG2
 #define LUAJIT_NO_LOG2
 #endif
 #endif
 #if defined(__symbian__)
 #if defined(__symbian__)

+ 29 - 3
src/lj_def.h

@@ -242,12 +242,18 @@ static LJ_AINLINE uint32_t lj_getu32(const void *p)
 #define LJ_FASTCALL	__fastcall
 #define LJ_FASTCALL	__fastcall
 #endif
 #endif
 
 
+#ifdef _M_PPC
+#pragma intrinsic(_CountLeadingZeros)
+unsigned int _CountLeadingZeros(long);
+static LJ_AINLINE uint32_t lj_fls(uint32_t x)
+{
+  return _CountLeadingZeros(x) ^ 31;
+}
+#else
 #pragma intrinsic(_BitScanForward)
 #pragma intrinsic(_BitScanForward)
 #pragma intrinsic(_BitScanReverse)
 #pragma intrinsic(_BitScanReverse)
 unsigned char _BitScanForward(uint32_t *, unsigned long);
 unsigned char _BitScanForward(uint32_t *, unsigned long);
 unsigned char _BitScanReverse(uint32_t *, unsigned long);
 unsigned char _BitScanReverse(uint32_t *, unsigned long);
-unsigned long _byteswap_ulong(unsigned long);
-uint64_t _byteswap_uint64(uint64_t);
 
 
 static LJ_AINLINE uint32_t lj_ffs(uint32_t x)
 static LJ_AINLINE uint32_t lj_ffs(uint32_t x)
 {
 {
@@ -258,13 +264,33 @@ static LJ_AINLINE uint32_t lj_fls(uint32_t x)
 {
 {
   uint32_t r; _BitScanReverse(&r, x); return r;
   uint32_t r; _BitScanReverse(&r, x); return r;
 }
 }
+#endif
 
 
+unsigned long _byteswap_ulong(unsigned long);
+uint64_t _byteswap_uint64(uint64_t);
 #define lj_bswap(x)	(_byteswap_ulong((x)))
 #define lj_bswap(x)	(_byteswap_ulong((x)))
 #define lj_bswap64(x)	(_byteswap_uint64((x)))
 #define lj_bswap64(x)	(_byteswap_uint64((x)))
 
 
-/* MSVC is only supported on x86/x64, where unaligned loads are always ok. */
+#if defined(_M_PPC) && defined(LUAJIT_NO_UNALIGNED)
+/*
+** Replacement for unaligned loads on XBox 360. Disabled by default since it's
+** usually more costly than the occasional stall when crossing a cache-line.
+*/
+static LJ_AINLINE uint16_t lj_getu16(const void *v)
+{
+  const uint8_t *p = (const uint8_t *)v;
+  return (uint16_t)((p[0]<<8) | p[1]);
+}
+static LJ_AINLINE uint32_t lj_getu32(const void *v)
+{
+  const uint8_t *p = (const uint8_t *)v;
+  return (uint32_t)((p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]);
+}
+#else
+/* Unaligned loads are generally ok on x86/x64. */
 #define lj_getu16(p)	(*(uint16_t *)(p))
 #define lj_getu16(p)	(*(uint16_t *)(p))
 #define lj_getu32(p)	(*(uint32_t *)(p))
 #define lj_getu32(p)	(*(uint32_t *)(p))
+#endif
 
 
 #else
 #else
 #error "missing defines for your compiler"
 #error "missing defines for your compiler"

+ 10 - 1
src/lj_frame.h

@@ -104,7 +104,16 @@ enum {
 #endif
 #endif
 #define CFRAME_SHIFT_MULTRES	3
 #define CFRAME_SHIFT_MULTRES	3
 #elif LJ_TARGET_PPC
 #elif LJ_TARGET_PPC
-#if LJ_ARCH_PPC64
+#if LJ_TARGET_XBOX360
+#define CFRAME_OFS_ERRF		424
+#define CFRAME_OFS_NRES		420
+#define CFRAME_OFS_PREV		400
+#define CFRAME_OFS_L		416
+#define CFRAME_OFS_PC		412
+#define CFRAME_OFS_MULTRES	408
+#define CFRAME_SIZE		384
+#define CFRAME_SHIFT_MULTRES	3
+#elif LJ_ARCH_PPC64
 #define CFRAME_OFS_ERRF		472
 #define CFRAME_OFS_ERRF		472
 #define CFRAME_OFS_NRES		468
 #define CFRAME_OFS_NRES		468
 #define CFRAME_OFS_PREV		448
 #define CFRAME_OFS_PREV		448

+ 42 - 4
src/vm_ppc.dasc

@@ -21,6 +21,7 @@
 |//         Note: a full PPC64 _LP64 port is not planned.
 |//         Note: a full PPC64 _LP64 port is not planned.
 |// GPR64   64 bit registers (but possibly 32 bit pointers, e.g. PS3).
 |// GPR64   64 bit registers (but possibly 32 bit pointers, e.g. PS3).
 |//         Affects reg saves, stack layout, carry/overflow/dot flags etc.
 |//         Affects reg saves, stack layout, carry/overflow/dot flags etc.
+|// FRAME32 Use 32 bit frame layout, even with GPR64 (XBox 360).
 |// TOC     Need table of contents (64 bit or 32 bit variant, e.g. PS3).
 |// TOC     Need table of contents (64 bit or 32 bit variant, e.g. PS3).
 |//         Function pointers are really a struct: code, TOC, env (optional).
 |//         Function pointers are really a struct: code, TOC, env (optional).
 |// TOCENV  Function pointers have an environment pointer, too (not on PS3).
 |// TOCENV  Function pointers have an environment pointer, too (not on PS3).
@@ -128,6 +129,37 @@
 |
 |
 |// Stack layout while in interpreter. Must match with lj_frame.h.
 |// Stack layout while in interpreter. Must match with lj_frame.h.
 |.if GPR64
 |.if GPR64
+|.if FRAME32
+|
+|//			456(sp) // \ 32/64 bit C frame info
+|.define TONUM_LO,	452(sp) // |
+|.define TONUM_HI,	448(sp) // |
+|.define TMPD_LO,	444(sp) // |
+|.define TMPD_HI,	440(sp) // |
+|.define SAVE_CR,	432(sp) // | 64 bit CR save.
+|.define SAVE_ERRF,	424(sp) //  > Parameter save area.
+|.define SAVE_NRES,	420(sp) // |
+|.define SAVE_L,	416(sp) // |
+|.define SAVE_PC,	412(sp) // |
+|.define SAVE_MULTRES,	408(sp) // |
+|.define SAVE_CFRAME,	400(sp) // / 64 bit C frame chain.
+|//			392(sp) // Reserved.
+|.define CFRAME_SPACE,	384     // Delta for sp.
+|// Back chain for sp:	384(sp) <-- sp entering interpreter
+|.define SAVE_LR,	376(sp) // 32 bit LR stored in hi-part.
+|.define SAVE_GPR_,	232     // .. 232+18*8: 64 bit GPR saves.
+|.define SAVE_FPR_,	88      // .. 88+18*8: 64 bit FPR saves.
+|//			80(sp) // Needed for 16 byte stack frame alignment.
+|//			16(sp)  // Callee parameter save area (ABI mandated).
+|//			8(sp)   // Reserved
+|// Back chain for sp:	0(sp)   <-- sp while in interpreter
+|// 32 bit sp stored in hi-part of 0(sp).
+|
+|.define TMPD_BLO,	447(sp)
+|.define TMPD,		TMPD_HI
+|.define TONUM_D,	TONUM_HI
+|
+|.else
 |
 |
 |//			508(sp) // \ 32 bit C frame info.
 |//			508(sp) // \ 32 bit C frame info.
 |.define SAVE_ERRF,	472(sp) // |
 |.define SAVE_ERRF,	472(sp) // |
@@ -155,6 +187,7 @@
 |.define TMPD,		TMPD_HI
 |.define TMPD,		TMPD_HI
 |.define TONUM_D,	TONUM_HI
 |.define TONUM_D,	TONUM_HI
 |
 |
+|.endif
 |.else
 |.else
 |
 |
 |.define SAVE_LR,	276(sp)
 |.define SAVE_LR,	276(sp)
@@ -201,7 +234,7 @@
 |.endmacro
 |.endmacro
 |
 |
 |.macro saveregs
 |.macro saveregs
-|.if GPR64
+|.if GPR64 and not FRAME32
 |  stdu sp, -CFRAME_SPACE(sp)
 |  stdu sp, -CFRAME_SPACE(sp)
 |.else
 |.else
 |  stwu sp, -CFRAME_SPACE(sp)
 |  stwu sp, -CFRAME_SPACE(sp)
@@ -209,7 +242,7 @@
 |  save_ 14; save_ 15; save_ 16
 |  save_ 14; save_ 15; save_ 16
 |  mflr r0
 |  mflr r0
 |  save_ 17; save_ 18; save_ 19; save_ 20; save_ 21; save_ 22
 |  save_ 17; save_ 18; save_ 19; save_ 20; save_ 21; save_ 22
-|.if GPR64
+|.if GPR64 and not FRAME32
 |  std r0, SAVE_LR
 |  std r0, SAVE_LR
 |.else
 |.else
 |  stw r0, SAVE_LR
 |  stw r0, SAVE_LR
@@ -226,10 +259,15 @@
 |.endmacro
 |.endmacro
 |
 |
 |.macro restoreregs
 |.macro restoreregs
+|.if GPR64 and not FRAME32
+|  ld r0, SAVE_LR
+|.else
+|  lwz r0, SAVE_LR
+|.endif
 |.if GPR64
 |.if GPR64
-|  ld r0, SAVE_LR; ld r12, SAVE_CR
+|  ld r12, SAVE_CR
 |.else
 |.else
-|  lwz r0, SAVE_LR; lwz r12, SAVE_CR
+|  lwz r12, SAVE_CR
 |.endif
 |.endif
 |  rest_ 14; rest_ 15; rest_ 16; rest_ 17; rest_ 18; rest_ 19
 |  rest_ 14; rest_ 15; rest_ 16; rest_ 17; rest_ 18; rest_ 19
 |  mtlr r0;
 |  mtlr r0;

+ 91 - 0
src/xedkbuild.bat

@@ -0,0 +1,91 @@
+@rem Script to build LuaJIT with the XBox 360 SDK.
+@rem Donated to the public domain.
+@rem
+@rem Open a "Visual Studio .NET Command Prompt" (32 bit host compiler)
+@rem Then cd to this directory and run this script.
+
+@if not defined INCLUDE goto :FAIL
+@if not defined XEDK goto :FAIL
+
+@setlocal
+@rem ---- Host compiler ----
+@set LJCOMPILE=cl /nologo /c /MD /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE
+@set LJLINK=link /nologo
+@set LJMT=mt /nologo
+@set DASMDIR=..\dynasm
+@set DASM=%DASMDIR%\dynasm.lua
+@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c
+
+%LJCOMPILE% host\minilua.c
+@if errorlevel 1 goto :BAD
+%LJLINK% /out:minilua.exe minilua.obj
+@if errorlevel 1 goto :BAD
+if exist minilua.exe.manifest^
+  %LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe
+
+@rem Error out for 64 bit host compiler
+@minilua
+@if errorlevel 8 goto :FAIL
+
+@set DASMFLAGS=-D GPR64 -D FRAME32 -D PPE -D SQRT -D DUALNUM
+minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h vm_ppc.dasc
+@if errorlevel 1 goto :BAD
+
+%LJCOMPILE% /I "." /I %DASMDIR% /D_XBOX_VER=200 /DLUAJIT_TARGET=LUAJIT_ARCH_PPC  host\buildvm*.c
+@if errorlevel 1 goto :BAD
+%LJLINK% /out:buildvm.exe buildvm*.obj
+@if errorlevel 1 goto :BAD
+if exist buildvm.exe.manifest^
+  %LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe
+
+buildvm -m peobj -o lj_vm.obj
+@if errorlevel 1 goto :BAD
+buildvm -m bcdef -o lj_bcdef.h %ALL_LIB%
+@if errorlevel 1 goto :BAD
+buildvm -m ffdef -o lj_ffdef.h %ALL_LIB%
+@if errorlevel 1 goto :BAD
+buildvm -m libdef -o lj_libdef.h %ALL_LIB%
+@if errorlevel 1 goto :BAD
+buildvm -m recdef -o lj_recdef.h %ALL_LIB%
+@if errorlevel 1 goto :BAD
+buildvm -m vmdef -o jit\vmdef.lua %ALL_LIB%
+@if errorlevel 1 goto :BAD
+buildvm -m folddef -o lj_folddef.h lj_opt_fold.c
+@if errorlevel 1 goto :BAD
+
+@rem ---- Cross compiler ----
+@set LJCOMPILE="%XEDK%\bin\win32\cl" /nologo /c /MT /O2 /W3 /GF /Gm- /GR- /GS- /Gy /openmp- /D_CRT_SECURE_NO_DEPRECATE /DNDEBUG /D_XBOX /D_LIB /DLUAJIT_USE_SYSMALLOC
+@set LJLIB="%XEDK%\bin\win32\lib" /nologo
+
+@if "%1" neq "debug" goto :NODEBUG
+@shift
+@set LJCOMPILE="%LJCOMPILE%" /Zi
+:NODEBUG
+@if "%1"=="amalg" goto :AMALG
+%LJCOMPILE% /DLUA_BUILD_AS_DLL lj_*.c lib_*.c
+@if errorlevel 1 goto :BAD
+%LJLIB% /OUT:luajit20.lib lj_*.obj lib_*.obj
+@if errorlevel 1 goto :BAD
+@goto :NOAMALG
+:AMALG
+%LJCOMPILE% /DLUA_BUILD_AS_DLL ljamalg.c
+@if errorlevel 1 goto :BAD
+%LJLIB% /OUT:luajit20.lib ljamalg.obj lj_vm.obj
+@if errorlevel 1 goto :BAD
+:NOAMALG
+
+@del *.obj *.manifest minilua.exe buildvm.exe
+@echo.
+@echo === Successfully built LuaJIT for XBox 360 ===
+
+@goto :END
+:BAD
+@echo.
+@echo *******************************************************
+@echo *** Build FAILED -- Please check the error messages ***
+@echo *******************************************************
+@goto :END
+:FAIL
+@echo To run this script you must open a "Visual Studio .NET Command Prompt"
+@echo (32 bit host compiler). The XBox 360 SDK must be installed, too.
+:END