Browse Source

Finally abstracted constants properly. Changed how the event module works; wasn't really abstract before. Removed libs we're not going to use: native, signal.

rude 16 years ago
parent
commit
87e3c4131c
100 changed files with 2465 additions and 32723 deletions
  1. 16 0
      platform/msvc2008/common/common.vcproj
  2. 20 0
      platform/msvc2008/event/event.vcproj
  3. 5 1
      platform/msvc2008/filesystem/filesystem.vcproj
  4. 5 0
      platform/msvc2008/graphics/graphics.vcproj
  5. 4 0
      platform/msvc2008/joystick/joystick.vcproj
  6. 4 0
      platform/msvc2008/keyboard/keyboard.vcproj
  7. 0 18
      platform/msvc2008/love.sln
  8. 138 362
      platform/msvc2008/love.vcproj
  9. 4 0
      platform/msvc2008/mouse/mouse.vcproj
  10. 0 260
      platform/msvc2008/native/native.vcproj
  11. 8 0
      platform/msvc2008/physics/physics.vcproj
  12. 0 213
      platform/msvc2008/signal/signal.vcproj
  13. 99 0
      src/common/EnumMap.h
  14. 164 0
      src/common/StringMap.h
  15. 0 10
      src/common/runtime.cpp
  16. 0 12
      src/common/runtime.h
  17. 0 6
      src/love.cpp
  18. 0 1
      src/modules/audio/wrap_Audio.cpp
  19. 235 0
      src/modules/event/Event.cpp
  20. 58 29
      src/modules/event/Event.h
  21. 228 96
      src/modules/event/sdl/Event.cpp
  22. 25 22
      src/modules/event/sdl/Event.h
  23. 113 21
      src/modules/event/sdl/wrap_Event.cpp
  24. 0 1
      src/modules/event/sdl/wrap_Event.h
  25. 25 30
      src/modules/filesystem/File.cpp
  26. 11 1
      src/modules/filesystem/File.h
  27. 4 4
      src/modules/filesystem/physfs/File.cpp
  28. 5 2
      src/modules/filesystem/physfs/wrap_File.cpp
  29. 0 10
      src/modules/filesystem/physfs/wrap_Filesystem.cpp
  30. 0 1
      src/modules/font/freetype/wrap_Font.cpp
  31. 141 0
      src/modules/graphics/Graphics.cpp
  32. 59 14
      src/modules/graphics/Graphics.h
  33. 24 152
      src/modules/graphics/opengl/Graphics.cpp
  34. 30 30
      src/modules/graphics/opengl/Graphics.h
  35. 86 70
      src/modules/graphics/opengl/wrap_Graphics.cpp
  36. 28 7
      src/modules/image/EncodedImageData.cpp
  37. 58 45
      src/modules/image/EncodedImageData.h
  38. 0 5
      src/modules/image/Image.h
  39. 4 4
      src/modules/image/devil/ImageData.cpp
  40. 1 1
      src/modules/image/devil/ImageData.h
  41. 4 9
      src/modules/image/wrap_Image.cpp
  42. 41 68
      src/modules/joystick/Joystick.cpp
  43. 21 16
      src/modules/joystick/Joystick.h
  44. 23 4
      src/modules/joystick/sdl/Joystick.cpp
  45. 10 4
      src/modules/joystick/sdl/Joystick.h
  46. 7 19
      src/modules/joystick/sdl/wrap_Joystick.cpp
  47. 187 0
      src/modules/keyboard/Keyboard.cpp
  48. 157 2
      src/modules/keyboard/Keyboard.h
  49. 160 11
      src/modules/keyboard/sdl/Keyboard.cpp
  50. 11 2
      src/modules/keyboard/sdl/Keyboard.h
  51. 14 162
      src/modules/keyboard/sdl/wrap_Keyboard.cpp
  52. 3 0
      src/modules/keyboard/sdl/wrap_Keyboard.h
  53. 33 24
      src/modules/mouse/Mouse.cpp
  54. 19 6
      src/modules/mouse/Mouse.h
  55. 22 4
      src/modules/mouse/sdl/Mouse.cpp
  56. 8 2
      src/modules/mouse/sdl/Mouse.h
  57. 9 16
      src/modules/mouse/sdl/wrap_Mouse.cpp
  58. 0 162
      src/modules/native/tcc/Native.cpp
  59. 0 99
      src/modules/native/tcc/Native.h
  60. 0 113
      src/modules/native/tcc/api.c
  61. 0 1734
      src/modules/native/tcc/libtcc/arm-gen.c
  62. 0 2548
      src/modules/native/tcc/libtcc/c67-gen.c
  63. 0 446
      src/modules/native/tcc/libtcc/coff.h
  64. 0 4
      src/modules/native/tcc/libtcc/config.h
  65. 0 1714
      src/modules/native/tcc/libtcc/elf.h
  66. 0 1211
      src/modules/native/tcc/libtcc/i386-asm.c
  67. 0 446
      src/modules/native/tcc/libtcc/i386-asm.h
  68. 0 1034
      src/modules/native/tcc/libtcc/i386-gen.c
  69. 0 667
      src/modules/native/tcc/libtcc/il-gen.c
  70. 0 251
      src/modules/native/tcc/libtcc/il-opcodes.h
  71. 0 2263
      src/modules/native/tcc/libtcc/libtcc.c
  72. 0 108
      src/modules/native/tcc/libtcc/libtcc.h
  73. 0 234
      src/modules/native/tcc/libtcc/stab.def
  74. 0 17
      src/modules/native/tcc/libtcc/stab.h
  75. 0 553
      src/modules/native/tcc/libtcc/tcc.c
  76. 0 766
      src/modules/native/tcc/libtcc/tcc.h
  77. 0 1021
      src/modules/native/tcc/libtcc/tccasm.c
  78. 0 957
      src/modules/native/tcc/libtcc/tcccoff.c
  79. 0 2732
      src/modules/native/tcc/libtcc/tccelf.c
  80. 0 5122
      src/modules/native/tcc/libtcc/tccgen.c
  81. 0 1559
      src/modules/native/tcc/libtcc/tccpe.c
  82. 0 2935
      src/modules/native/tcc/libtcc/tccpp.c
  83. 0 469
      src/modules/native/tcc/libtcc/tcctok.h
  84. 0 1419
      src/modules/native/tcc/libtcc/x86_64-gen.c
  85. 0 153
      src/modules/native/tcc/wrap_Native.cpp
  86. 33 19
      src/modules/physics/Joint.cpp
  87. 14 3
      src/modules/physics/Joint.h
  88. 50 44
      src/modules/physics/Shape.cpp
  89. 13 2
      src/modules/physics/Shape.h
  90. 2 2
      src/modules/physics/box2d/Joint.cpp
  91. 1 1
      src/modules/physics/box2d/Joint.h
  92. 2 2
      src/modules/physics/box2d/Shape.cpp
  93. 1 1
      src/modules/physics/box2d/Shape.h
  94. 4 1
      src/modules/physics/box2d/wrap_Joint.cpp
  95. 0 15
      src/modules/physics/box2d/wrap_Physics.cpp
  96. 4 1
      src/modules/physics/box2d/wrap_Shape.cpp
  97. 0 103
      src/modules/signal/posix/wrap_Signal.cpp
  98. 0 1
      src/modules/sound/wrap_Sound.cpp
  99. 0 1
      src/modules/timer/sdl/wrap_Timer.cpp
  100. 10 13
      src/scripts/boot.lua

+ 16 - 0
platform/msvc2008/common/common.vcproj

@@ -154,6 +154,10 @@
 			RelativePath="..\..\..\src\common\Data.h"
 			>
 		</File>
+		<File
+			RelativePath="..\..\..\src\common\EnumMap.h"
+			>
+		</File>
 		<File
 			RelativePath="..\..\..\src\common\Exception.cpp"
 			>
@@ -306,6 +310,18 @@
 			RelativePath="..\..\..\src\common\runtime.h"
 			>
 		</File>
+		<File
+			RelativePath="..\..\..\src\common\string.cpp"
+			>
+		</File>
+		<File
+			RelativePath="..\..\..\src\common\string.h"
+			>
+		</File>
+		<File
+			RelativePath="..\..\..\src\common\StringMap.h"
+			>
+		</File>
 		<File
 			RelativePath="..\..\..\src\common\types.h"
 			>

+ 20 - 0
platform/msvc2008/event/event.vcproj

@@ -205,6 +205,26 @@
 				>
 			</File>
 		</Filter>
+		<File
+			RelativePath="..\..\..\src\modules\event\Event.cpp"
+			>
+			<FileConfiguration
+				Name="Debug|Win32"
+				>
+				<Tool
+					Name="VCCLCompilerTool"
+					ObjectFile="$(IntDir)\event\"
+				/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="Release|Win32"
+				>
+				<Tool
+					Name="VCCLCompilerTool"
+					ObjectFile="$(IntDir)\event\"
+				/>
+			</FileConfiguration>
+		</File>
 		<File
 			RelativePath="..\..\..\src\modules\event\Event.h"
 			>

+ 5 - 1
platform/msvc2008/filesystem/filesystem.vcproj

@@ -170,7 +170,7 @@
 	</References>
 	<Files>
 		<Filter
-			Name="filesystem"
+			Name="physfs"
 			>
 			<File
 				RelativePath="..\..\..\src\modules\filesystem\physfs\File.cpp"
@@ -293,6 +293,10 @@
 				>
 			</File>
 		</Filter>
+		<File
+			RelativePath="..\..\..\src\modules\filesystem\File.cpp"
+			>
+		</File>
 		<File
 			RelativePath="..\..\..\src\modules\filesystem\File.h"
 			>

+ 5 - 0
platform/msvc2008/graphics/graphics.vcproj

@@ -234,6 +234,7 @@
 					<Tool
 						Name="VCCLCompilerTool"
 						ObjectFile="$(IntDir)\graphics\opengl\"
+						WarningLevel="0"
 					/>
 				</FileConfiguration>
 			</File>
@@ -606,6 +607,10 @@
 			RelativePath="..\..\..\src\modules\graphics\Drawable.h"
 			>
 		</File>
+		<File
+			RelativePath="..\..\..\src\modules\graphics\Graphics.cpp"
+			>
+		</File>
 		<File
 			RelativePath="..\..\..\src\modules\graphics\Graphics.h"
 			>

+ 4 - 0
platform/msvc2008/joystick/joystick.vcproj

@@ -205,6 +205,10 @@
 				>
 			</File>
 		</Filter>
+		<File
+			RelativePath="..\..\..\src\modules\joystick\Joystick.cpp"
+			>
+		</File>
 		<File
 			RelativePath="..\..\..\src\modules\joystick\Joystick.h"
 			>

+ 4 - 0
platform/msvc2008/keyboard/keyboard.vcproj

@@ -205,6 +205,10 @@
 				>
 			</File>
 		</Filter>
+		<File
+			RelativePath="..\..\..\src\modules\keyboard\Keyboard.cpp"
+			>
+		</File>
 		<File
 			RelativePath="..\..\..\src\modules\keyboard\Keyboard.h"
 			>

+ 0 - 18
platform/msvc2008/love.sln

@@ -42,11 +42,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mouse", "mouse\mouse.vcproj
 		{8273822F-45A4-4BE3-82F3-B8B3223C578C} = {8273822F-45A4-4BE3-82F3-B8B3223C578C}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "native", "native\native.vcproj", "{CCAD89EC-2C3C-4F69-BF71-D9DA230FE109}"
-	ProjectSection(ProjectDependencies) = postProject
-		{8273822F-45A4-4BE3-82F3-B8B3223C578C} = {8273822F-45A4-4BE3-82F3-B8B3223C578C}
-	EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "physics", "physics\physics.vcproj", "{39CDF8C8-016D-423E-94BA-7DD798CF0E15}"
 	ProjectSection(ProjectDependencies) = postProject
 		{8273822F-45A4-4BE3-82F3-B8B3223C578C} = {8273822F-45A4-4BE3-82F3-B8B3223C578C}
@@ -77,11 +72,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "font", "font\font.vcproj",
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "love", "love.vcproj", "{F2FDC53D-1ECD-4CF1-BA3F-3E59A2484DB9}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "signal", "signal\signal.vcproj", "{5A7AAEBC-F269-41DA-984A-75F975549CA5}"
-	ProjectSection(ProjectDependencies) = postProject
-		{8273822F-45A4-4BE3-82F3-B8B3223C578C} = {8273822F-45A4-4BE3-82F3-B8B3223C578C}
-	EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lovedll", "lovedll\lovedll.vcproj", "{2863FF8A-153F-46E0-8E71-2E58F3809E9B}"
 	ProjectSection(ProjectDependencies) = postProject
 		{8273822F-45A4-4BE3-82F3-B8B3223C578C} = {8273822F-45A4-4BE3-82F3-B8B3223C578C}
@@ -129,10 +119,6 @@ Global
 		{88881251-6818-485E-A262-DE1283096589}.Debug|Win32.Build.0 = Debug|Win32
 		{88881251-6818-485E-A262-DE1283096589}.Release|Win32.ActiveCfg = Release|Win32
 		{88881251-6818-485E-A262-DE1283096589}.Release|Win32.Build.0 = Release|Win32
-		{CCAD89EC-2C3C-4F69-BF71-D9DA230FE109}.Debug|Win32.ActiveCfg = Debug|Win32
-		{CCAD89EC-2C3C-4F69-BF71-D9DA230FE109}.Debug|Win32.Build.0 = Debug|Win32
-		{CCAD89EC-2C3C-4F69-BF71-D9DA230FE109}.Release|Win32.ActiveCfg = Release|Win32
-		{CCAD89EC-2C3C-4F69-BF71-D9DA230FE109}.Release|Win32.Build.0 = Release|Win32
 		{39CDF8C8-016D-423E-94BA-7DD798CF0E15}.Debug|Win32.ActiveCfg = Debug|Win32
 		{39CDF8C8-016D-423E-94BA-7DD798CF0E15}.Debug|Win32.Build.0 = Debug|Win32
 		{39CDF8C8-016D-423E-94BA-7DD798CF0E15}.Release|Win32.ActiveCfg = Release|Win32
@@ -157,10 +143,6 @@ Global
 		{F2FDC53D-1ECD-4CF1-BA3F-3E59A2484DB9}.Debug|Win32.Build.0 = Debug|Win32
 		{F2FDC53D-1ECD-4CF1-BA3F-3E59A2484DB9}.Release|Win32.ActiveCfg = Release|Win32
 		{F2FDC53D-1ECD-4CF1-BA3F-3E59A2484DB9}.Release|Win32.Build.0 = Release|Win32
-		{5A7AAEBC-F269-41DA-984A-75F975549CA5}.Debug|Win32.ActiveCfg = Debug|Win32
-		{5A7AAEBC-F269-41DA-984A-75F975549CA5}.Debug|Win32.Build.0 = Debug|Win32
-		{5A7AAEBC-F269-41DA-984A-75F975549CA5}.Release|Win32.ActiveCfg = Release|Win32
-		{5A7AAEBC-F269-41DA-984A-75F975549CA5}.Release|Win32.Build.0 = Release|Win32
 		{2863FF8A-153F-46E0-8E71-2E58F3809E9B}.Debug|Win32.ActiveCfg = Debug|Win32
 		{2863FF8A-153F-46E0-8E71-2E58F3809E9B}.Debug|Win32.Build.0 = Debug|Win32
 		{2863FF8A-153F-46E0-8E71-2E58F3809E9B}.Release|Win32.ActiveCfg = Release|Win32

+ 138 - 362
platform/msvc2008/love.vcproj

@@ -538,6 +538,26 @@
 			<Filter
 				Name="event"
 				>
+				<File
+					RelativePath="..\..\src\modules\event\Event.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\event\"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\event\"
+						/>
+					</FileConfiguration>
+				</File>
 				<File
 					RelativePath="..\..\src\modules\event\Event.h"
 					>
@@ -598,6 +618,10 @@
 			<Filter
 				Name="filesystem"
 				>
+				<File
+					RelativePath="..\..\src\modules\filesystem\File.cpp"
+					>
+				</File>
 				<File
 					RelativePath="..\..\src\modules\filesystem\File.h"
 					>
@@ -778,6 +802,10 @@
 					RelativePath="..\..\src\modules\graphics\Drawable.h"
 					>
 				</File>
+				<File
+					RelativePath="..\..\src\modules\graphics\Graphics.cpp"
+					>
+				</File>
 				<File
 					RelativePath="..\..\src\modules\graphics\Graphics.h"
 					>
@@ -846,6 +874,7 @@
 							<Tool
 								Name="VCCLCompilerTool"
 								ObjectFile="$(IntDir)\graphics\opengl\"
+								WarningLevel="0"
 							/>
 						</FileConfiguration>
 						<FileConfiguration
@@ -854,6 +883,7 @@
 							<Tool
 								Name="VCCLCompilerTool"
 								ObjectFile="$(IntDir)\graphics\opengl\"
+								WarningLevel="0"
 							/>
 						</FileConfiguration>
 					</File>
@@ -1382,6 +1412,26 @@
 			<Filter
 				Name="joystick"
 				>
+				<File
+					RelativePath="..\..\src\modules\joystick\Joystick.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\joystick\"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\joystick\"
+						/>
+					</FileConfiguration>
+				</File>
 				<File
 					RelativePath="..\..\src\modules\joystick\Joystick.h"
 					>
@@ -1442,6 +1492,26 @@
 			<Filter
 				Name="keyboard"
 				>
+				<File
+					RelativePath="..\..\src\modules\keyboard\Keyboard.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\keyboard\"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\keyboard\"
+						/>
+					</FileConfiguration>
+				</File>
 				<File
 					RelativePath="..\..\src\modules\keyboard\Keyboard.h"
 					>
@@ -1502,6 +1572,26 @@
 			<Filter
 				Name="mouse"
 				>
+				<File
+					RelativePath="..\..\src\modules\mouse\Mouse.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\mouse\"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\mouse\"
+						/>
+					</FileConfiguration>
+				</File>
 				<File
 					RelativePath="..\..\src\modules\mouse\Mouse.h"
 					>
@@ -1562,10 +1652,50 @@
 			<Filter
 				Name="physics"
 				>
+				<File
+					RelativePath="..\..\src\modules\physics\Joint.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\physics\"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\physics\"
+						/>
+					</FileConfiguration>
+				</File>
 				<File
 					RelativePath="..\..\src\modules\physics\Joint.h"
 					>
 				</File>
+				<File
+					RelativePath="..\..\src\modules\physics\Shape.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\physics\"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)\physics\"
+						/>
+					</FileConfiguration>
+				</File>
 				<File
 					RelativePath="..\..\src\modules\physics\Shape.h"
 					>
@@ -3231,368 +3361,6 @@
 					</File>
 				</Filter>
 			</Filter>
-			<Filter
-				Name="native"
-				>
-				<Filter
-					Name="tcc"
-					>
-					<File
-						RelativePath="..\..\src\modules\native\tcc\api.c"
-						>
-						<FileConfiguration
-							Name="Debug|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\native\tcc\"
-							/>
-						</FileConfiguration>
-						<FileConfiguration
-							Name="Release|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\native\tcc\"
-							/>
-						</FileConfiguration>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\native\tcc\api.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\native\tcc\Native.cpp"
-						>
-						<FileConfiguration
-							Name="Debug|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\native\tcc\"
-							/>
-						</FileConfiguration>
-						<FileConfiguration
-							Name="Release|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\native\tcc\"
-							/>
-						</FileConfiguration>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\native\tcc\Native.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\native\tcc\wrap_Native.cpp"
-						>
-						<FileConfiguration
-							Name="Debug|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\native\tcc\"
-							/>
-						</FileConfiguration>
-						<FileConfiguration
-							Name="Release|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\native\tcc\"
-							/>
-						</FileConfiguration>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\native\tcc\wrap_Native.h"
-						>
-					</File>
-					<Filter
-						Name="libtcc"
-						>
-						<File
-							RelativePath="..\..\src\modules\native\tcc\libtcc\libtcc.c"
-							>
-							<FileConfiguration
-								Name="Debug|Win32"
-								>
-								<Tool
-									Name="VCCLCompilerTool"
-									ObjectFile="$(IntDir)\native\tcc\libtcc\"
-									WarningLevel="0"
-								/>
-							</FileConfiguration>
-							<FileConfiguration
-								Name="Release|Win32"
-								>
-								<Tool
-									Name="VCCLCompilerTool"
-									ObjectFile="$(IntDir)\native\tcc\libtcc\"
-									WarningLevel="0"
-								/>
-							</FileConfiguration>
-						</File>
-					</Filter>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="font"
-				>
-				<File
-					RelativePath="..\..\src\modules\font\GlyphData.cpp"
-					>
-					<FileConfiguration
-						Name="Debug|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\font\"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\font\"
-						/>
-					</FileConfiguration>
-				</File>
-				<File
-					RelativePath="..\..\src\modules\font\GlyphData.h"
-					>
-				</File>
-				<File
-					RelativePath="..\..\src\modules\font\ImageRasterizer.cpp"
-					>
-					<FileConfiguration
-						Name="Debug|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\font\"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\font\"
-						/>
-					</FileConfiguration>
-				</File>
-				<File
-					RelativePath="..\..\src\modules\font\ImageRasterizer.h"
-					>
-				</File>
-				<File
-					RelativePath="..\..\src\modules\font\Rasterizer.cpp"
-					>
-					<FileConfiguration
-						Name="Debug|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\font\"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\font\"
-						/>
-					</FileConfiguration>
-				</File>
-				<File
-					RelativePath="..\..\src\modules\font\Rasterizer.h"
-					>
-				</File>
-				<File
-					RelativePath="..\..\src\modules\font\wrap_GlyphData.cpp"
-					>
-					<FileConfiguration
-						Name="Debug|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\font\"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\font\"
-						/>
-					</FileConfiguration>
-				</File>
-				<File
-					RelativePath="..\..\src\modules\font\wrap_GlyphData.h"
-					>
-				</File>
-				<File
-					RelativePath="..\..\src\modules\font\wrap_Rasterizer.cpp"
-					>
-					<FileConfiguration
-						Name="Debug|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\font\"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\font\"
-						/>
-					</FileConfiguration>
-				</File>
-				<File
-					RelativePath="..\..\src\modules\font\wrap_Rasterizer.h"
-					>
-				</File>
-				<Filter
-					Name="freetype"
-					>
-					<File
-						RelativePath="..\..\src\modules\font\freetype\Font.cpp"
-						>
-						<FileConfiguration
-							Name="Debug|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\font\freetype\"
-							/>
-						</FileConfiguration>
-						<FileConfiguration
-							Name="Release|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\font\freetype\"
-							/>
-						</FileConfiguration>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\font\freetype\Font.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\font\freetype\TrueTypeRasterizer.cpp"
-						>
-						<FileConfiguration
-							Name="Debug|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\font\freetype\"
-							/>
-						</FileConfiguration>
-						<FileConfiguration
-							Name="Release|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\font\freetype\"
-							/>
-						</FileConfiguration>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\font\freetype\TrueTypeRasterizer.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\font\freetype\wrap_Font.cpp"
-						>
-						<FileConfiguration
-							Name="Debug|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\font\freetype\"
-							/>
-						</FileConfiguration>
-						<FileConfiguration
-							Name="Release|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\font\freetype\"
-							/>
-						</FileConfiguration>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\font\freetype\wrap_Font.h"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="signal"
-				>
-				<Filter
-					Name="posix"
-					>
-					<File
-						RelativePath="..\..\src\modules\signal\posix\Signal.cpp"
-						>
-						<FileConfiguration
-							Name="Debug|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\signal\posix\"
-							/>
-						</FileConfiguration>
-						<FileConfiguration
-							Name="Release|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\signal\posix\"
-							/>
-						</FileConfiguration>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\signal\posix\Signal.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\signal\posix\wrap_Signal.cpp"
-						>
-						<FileConfiguration
-							Name="Debug|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\signal\posix\"
-							/>
-						</FileConfiguration>
-						<FileConfiguration
-							Name="Release|Win32"
-							>
-							<Tool
-								Name="VCCLCompilerTool"
-								ObjectFile="$(IntDir)\signal\posix\"
-							/>
-						</FileConfiguration>
-					</File>
-					<File
-						RelativePath="..\..\src\modules\signal\posix\wrap_Signal.h"
-						>
-					</File>
-				</Filter>
-			</Filter>
 		</Filter>
 		<Filter
 			Name="common"
@@ -3605,6 +3373,10 @@
 				RelativePath="..\..\src\common\Data.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\src\common\EnumMap.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\src\common\Exception.cpp"
 				>
@@ -3757,6 +3529,10 @@
 				RelativePath="..\..\src\common\runtime.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\src\common\StringMap.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\src\common\types.h"
 				>

+ 4 - 0
platform/msvc2008/mouse/mouse.vcproj

@@ -205,6 +205,10 @@
 				>
 			</File>
 		</Filter>
+		<File
+			RelativePath="..\..\..\src\modules\mouse\Mouse.cpp"
+			>
+		</File>
 		<File
 			RelativePath="..\..\..\src\modules\mouse\Mouse.h"
 			>

+ 0 - 260
platform/msvc2008/native/native.vcproj

@@ -1,260 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="9,00"
-	Name="native"
-	ProjectGUID="{CCAD89EC-2C3C-4F69-BF71-D9DA230FE109}"
-	RootNamespace="native"
-	Keyword="Win32Proj"
-	TargetFrameworkVersion="196613"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="2"
-			CharacterSet="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="../include;../../../src;../../../src/modules;../include/SDL"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;EVENT_EXPORTS;_CRT_SECURE_NO_WARNINGS"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="4"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="lua5.1.lib SDL.lib"
-				OutputFile="$(OutDir)\love\$(ProjectName).dll"
-				LinkIncremental="2"
-				AdditionalLibraryDirectories="..\lib"
-				GenerateDebugInformation="true"
-				SubSystem="2"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="2"
-			CharacterSet="1"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				EnableIntrinsicFunctions="true"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;EVENT_EXPORTS"
-				RuntimeLibrary="2"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				LinkIncremental="1"
-				GenerateDebugInformation="true"
-				SubSystem="2"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="tcc"
-			>
-			<File
-				RelativePath="..\..\..\src\modules\native\tcc\api.c"
-				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						ObjectFile="$(IntDir)\native\tcc\"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						ObjectFile="$(IntDir)\native\tcc\"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\src\modules\native\tcc\api.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\src\modules\native\tcc\Native.cpp"
-				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						ObjectFile="$(IntDir)\native\tcc\"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\src\modules\native\tcc\Native.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\src\modules\native\tcc\wrap_Native.cpp"
-				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						ObjectFile="$(IntDir)\native\tcc\"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\src\modules\native\tcc\wrap_Native.h"
-				>
-			</File>
-			<Filter
-				Name="libtcc"
-				>
-				<File
-					RelativePath="..\..\..\src\modules\native\tcc\libtcc\libtcc.c"
-					>
-					<FileConfiguration
-						Name="Debug|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\native\tcc\libtcc\"
-							WarningLevel="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							ObjectFile="$(IntDir)\native\tcc\libtcc\"
-						/>
-					</FileConfiguration>
-				</File>
-			</Filter>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>

+ 8 - 0
platform/msvc2008/physics/physics.vcproj

@@ -1241,10 +1241,18 @@
 				</File>
 			</Filter>
 		</Filter>
+		<File
+			RelativePath="..\..\..\src\modules\physics\Joint.cpp"
+			>
+		</File>
 		<File
 			RelativePath="..\..\..\src\modules\physics\Joint.h"
 			>
 		</File>
+		<File
+			RelativePath="..\..\..\src\modules\physics\Shape.cpp"
+			>
+		</File>
 		<File
 			RelativePath="..\..\..\src\modules\physics\Shape.h"
 			>

+ 0 - 213
platform/msvc2008/signal/signal.vcproj

@@ -1,213 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="9,00"
-	Name="signal"
-	ProjectGUID="{5A7AAEBC-F269-41DA-984A-75F975549CA5}"
-	RootNamespace="signal"
-	Keyword="Win32Proj"
-	TargetFrameworkVersion="196613"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="2"
-			CharacterSet="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="../include;../../../src;../../../src/modules;"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SIGNAL_EXPORTS"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
-				UsePrecompiledHeader="0"
-				ObjectFile="$(IntDir)\physics\box2d\"
-				WarningLevel="3"
-				DebugInformationFormat="4"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\love\$(ProjectName).dll"
-				LinkIncremental="2"
-				GenerateDebugInformation="true"
-				SubSystem="2"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="2"
-			CharacterSet="1"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				EnableIntrinsicFunctions="true"
-				AdditionalIncludeDirectories="../include;../../../src;../../../src/modules;"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SIGNAL_EXPORTS"
-				RuntimeLibrary="0"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				ObjectFile="$(IntDir)\physics\box2d\"
-				WarningLevel="3"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\love\$(ProjectName).dll"
-				LinkIncremental="1"
-				GenerateDebugInformation="true"
-				SubSystem="2"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="posix"
-			>
-			<File
-				RelativePath="..\..\..\src\modules\signal\posix\Signal.cpp"
-				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						ObjectFile="$(IntDir)\signal\posix\"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\src\modules\signal\posix\Signal.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\src\modules\signal\posix\wrap_Signal.cpp"
-				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						ObjectFile="$(IntDir)\signal\posix\"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\src\modules\signal\posix\wrap_Signal.h"
-				>
-			</File>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>

+ 99 - 0
src/common/EnumMap.h

@@ -0,0 +1,99 @@
+/**
+* Copyright (c) 2006-2009 LOVE Development Team
+* 
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* 
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#ifndef LOVE_ENUM_MAP_H
+#define LOVE_ENUM_MAP_H
+
+#include "Exception.h"
+
+namespace love
+{
+	template<typename T, typename U, unsigned PEAK>
+	class EnumMap
+	{
+	private:
+
+		struct Value
+		{
+			unsigned v;
+			bool set;
+			Value() : set(false) {}
+		};
+
+		Value values_t[PEAK];
+		Value values_u[PEAK];
+
+	public:
+		
+		struct Entry
+		{
+			T t;
+			U u;
+		};
+
+		EnumMap(Entry * entries, unsigned size)
+		{
+			unsigned n = size/sizeof(Entry);
+
+			for(unsigned i = 0; i<n; ++i)
+			{
+				unsigned e_t = (unsigned)entries[i].t;
+				unsigned e_u = (unsigned)entries[i].u;
+
+				if(e_t < PEAK)
+				{
+					values_u[e_t].v = e_u;
+					values_u[e_t].set = true;
+				}
+				if(e_u < PEAK)
+				{
+					values_t[e_u].v = e_t;
+					values_t[e_u].set = true;
+				}
+			}
+		}
+			
+		bool find(T t, U & u)
+		{
+			if((unsigned)t < PEAK && values_u[(unsigned)t].set)
+			{
+				u = (U)values_u[(unsigned)t].v;
+				return true;
+			}
+
+			return false;
+		}
+
+		bool find(U u, T & t)
+		{
+			if((unsigned)u < PEAK && values_t[(unsigned)u].set)
+			{
+				t = (T)values_t[(unsigned)u].v;
+				return true;
+			}
+
+			return false;
+		}
+
+	}; // EnumMap
+
+} // love
+
+#endif // LOVE_ENUM_MAP_H

+ 164 - 0
src/common/StringMap.h

@@ -0,0 +1,164 @@
+/**
+* Copyright (c) 2006-2009 LOVE Development Team
+* 
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* 
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#ifndef LOVE_STRING_MAP_H
+#define LOVE_STRING_MAP_H
+
+#include "Exception.h"
+
+namespace love
+{
+	template<typename T, unsigned SIZE>
+	class StringMap
+	{
+	private:
+
+		struct Record
+		{
+			const char * key;
+			T value;
+			bool set;
+			Record() : set(false) {}
+		};
+
+		const static unsigned MAX = (unsigned)((float)SIZE * 1.5f);
+
+		Record records[MAX];
+		const char * reverse[SIZE];
+
+	public:
+
+		struct Entry
+		{
+			const char * key;
+			T value;
+		};
+
+		StringMap(Entry * entries, unsigned num)
+		{
+
+			for(unsigned i = 0; i < SIZE; ++i)
+				reverse[i] = 0;
+
+			unsigned n = num/sizeof(Entry);
+
+			for(unsigned i = 0; i < n; ++i)
+			{
+				add(entries[i].key, entries[i].value);
+			}
+		}
+
+		bool streq(const char * a, const char * b)
+		{
+			while(*a != 0 && *b != 0)
+			{
+				if(*a != *b)
+					return false;
+				++a;
+				++b;
+			}
+
+			return (*a == 0 && *b == 0);
+		}
+
+		bool find(const char * key, T & t)
+		{
+			unsigned str_hash = djb2(key);
+
+			for(unsigned i = 0; i < MAX; ++i)
+			{
+				unsigned str_i = (str_hash + i) % MAX;
+
+				if(records[i].set && streq(records[i].key, key))
+				{
+					t = records[i].value;
+					return true;
+				}
+			}
+
+			return false;
+		}
+
+		bool find(T key, const char *& str)
+		{
+			unsigned index = (unsigned)key;
+
+			if(index >= SIZE)
+				return false;
+			
+			if(reverse[index] != 0)
+			{
+				str = reverse[index];
+				return true;
+			}
+			else
+			{
+				return false;
+			}
+		}
+
+		bool add(const char * key, T value)
+		{
+			unsigned str_hash = djb2(key);
+			bool inserted = false;
+			
+			for(unsigned i = 0; i < MAX; ++i)
+			{
+				unsigned str_i = (str_hash + i) % MAX;
+
+				if(!records[str_i].set)
+				{
+					inserted = true;
+					records[str_i].set = true;
+					records[str_i].key = key;
+					records[str_i].value = value;
+					break;
+				}
+			}
+
+			unsigned index = (unsigned)value;
+
+			if(index >= SIZE)
+			{
+				printf("\nConstant %s out of bounds with %i!\n", key, index);
+				return false;
+			}
+
+			reverse[index] = key;
+
+			return inserted;
+		}
+
+		unsigned djb2(const char * key)
+		{
+			unsigned hash = 5381;
+			int c;
+
+			while (c = *key++)
+				hash = ((hash << 5) + hash) + c;
+
+			return hash;
+		}
+
+	}; // StringMap
+
+} // love
+
+#endif // LOVE_STRING_MAP_H

+ 0 - 10
src/common/runtime.cpp

@@ -134,16 +134,6 @@ namespace love
 		// Gets the love table.
 		luax_insistglobal(L, "love");
 
-		// Install constants.
-		if(m.constants != 0)
-		{
-			for(int i = 0; m.constants[i].name != 0; i++)
-			{
-				lua_pushinteger(L, m.constants[i].value);
-				lua_setfield(L, -2, m.constants[i].name);
-			}
-		}
-
 		// Create new table for module.
 		lua_newtable(L);
 

+ 0 - 12
src/common/runtime.h

@@ -65,16 +65,6 @@ namespace love
 		bool own; 
 	};
 
-	
-	/**
-	* Used to store constants in arrays.
-	**/
-	struct Constant
-	{
-		const char * name;
-		int value;
-	};
-
 	/**
 	* A Module with Lua wrapper functions and other data.
 	**/
@@ -95,8 +85,6 @@ namespace love
 		// A list of functions which expose the types of the modules (last element 0).
 		const lua_CFunction * types;
 
-		// A list of constants (last element 0).
-		const Constant * constants;
 	};
 
 	/**

+ 0 - 6
src/love.cpp

@@ -33,15 +33,12 @@
 #include <audio/wrap_Audio.h>
 #include <event/sdl/wrap_Event.h>
 #include <filesystem/physfs/wrap_Filesystem.h>
-#include <font/freetype/wrap_Font.h>
 #include <graphics/opengl/wrap_Graphics.h>
 #include <image/wrap_Image.h>
 #include <joystick/sdl/wrap_Joystick.h>
 #include <keyboard/sdl/wrap_Keyboard.h>
 #include <mouse/sdl/wrap_Mouse.h>
-#include <native/tcc/wrap_Native.h>
 #include <physics/box2d/wrap_Physics.h>
-#include <signal/posix/wrap_Signal.h>
 #include <sound/wrap_Sound.h>
 #include <timer/sdl/wrap_Timer.h>
 
@@ -60,15 +57,12 @@ static const luaL_Reg modules[] = {
 	{ "love.audio", love::audio::luaopen_love_audio },
 	{ "love.event", love::event::sdl::luaopen_love_event },
 	{ "love.filesystem", love::filesystem::physfs::luaopen_love_filesystem },
-	{ "love.font", love::font::freetype::luaopen_love_font },
 	{ "love.graphics", love::graphics::opengl::luaopen_love_graphics },
 	{ "love.image", love::image::luaopen_love_image },
 	{ "love.joystick", love::joystick::sdl::luaopen_love_joystick },
 	{ "love.keyboard", love::keyboard::sdl::luaopen_love_keyboard },
 	{ "love.mouse", love::mouse::sdl::luaopen_love_mouse },
-	{ "love.native", love::native::tcc::luaopen_love_native },
 	{ "love.physics", love::physics::box2d::luaopen_love_physics },
-	{ "love.signal", love::signal::posix::luaopen_love_signal },
 	{ "love.sound", love::sound::luaopen_love_sound },
 	{ "love.timer", love::timer::sdl::luaopen_love_timer },
 	{ 0, 0 }

+ 0 - 1
src/modules/audio/wrap_Audio.cpp

@@ -272,7 +272,6 @@ namespace audio
 		w.flags = MODULE_T;
 		w.functions = functions;
 		w.types = types;
-		w.constants = 0;
 
 		return luax_register_module(L, w);
 	}

+ 235 - 0
src/modules/event/Event.cpp

@@ -0,0 +1,235 @@
+/**
+* Copyright (c) 2006-2009 LOVE Development Team
+* 
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* 
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#include "Event.h"
+
+namespace love
+{
+namespace event
+{
+	Event::~Event()
+	{
+	}
+
+	bool Event::getConstant(const char * in, Event::Type & out)
+	{
+		return types.find(in, out);
+	}
+
+	bool Event::getConstant(Event::Type in, const char *& out)
+	{
+		return types.find(in, out);
+	}
+
+	bool Event::getConstant(const char * in, love::mouse::Mouse::Button & out)
+	{
+		return buttons.find(in, out);
+	}
+
+	bool Event::getConstant(love::mouse::Mouse::Button in, const char *& out)
+	{
+		return buttons.find(in, out);
+	}
+
+	bool Event::getConstant(const char * in, love::keyboard::Keyboard::Key & out)
+	{
+		return keys.find(in, out);
+	}
+
+	bool Event::getConstant(love::keyboard::Keyboard::Key in, const char *& out)
+	{
+		return keys.find(in, out);
+	}
+
+	StringMap<Event::Type, Event::TYPE_MAX_ENUM>::Entry Event::typeEntries[] = 
+	{
+		{"kp", Event::TYPE_KEY_PRESSED},
+		{"kr", Event::TYPE_KEY_RELEASED},
+		{"mp", Event::TYPE_MOUSE_PRESSED},
+		{"mr", Event::TYPE_MOUSE_RELEASED},
+		{"jp", Event::TYPE_JOYSTICK_PRESSED},
+		{"jr", Event::TYPE_JOYSTICK_RELEASED},
+		{"q", Event::TYPE_QUIT},
+	};
+
+	StringMap<Event::Type, Event::TYPE_MAX_ENUM> Event::types(Event::typeEntries, sizeof(Event::typeEntries));
+
+	StringMap<love::mouse::Mouse::Button, love::mouse::Mouse::BUTTON_MAX_ENUM>::Entry Event::buttonEntries[] = 
+	{
+		{"l", love::mouse::Mouse::BUTTON_LEFT},
+		{"m", love::mouse::Mouse::BUTTON_MIDDLE},
+		{"r", love::mouse::Mouse::BUTTON_RIGHT},
+		{"wu", love::mouse::Mouse::BUTTON_WHEELUP},
+		{"wd", love::mouse::Mouse::BUTTON_WHEELDOWN},
+		{"x1", love::mouse::Mouse::BUTTON_X1},
+		{"x2", love::mouse::Mouse::BUTTON_X2},
+	};
+
+	StringMap<love::mouse::Mouse::Button, love::mouse::Mouse::BUTTON_MAX_ENUM> Event::buttons(Event::buttonEntries, sizeof(Event::buttonEntries));
+
+	StringMap<love::keyboard::Keyboard::Key, love::keyboard::Keyboard::KEY_MAX_ENUM>::Entry Event::keyEntries[] = 
+	{
+		{"backspace", love::keyboard::Keyboard::KEY_BACKSPACE},
+		{"tab", love::keyboard::Keyboard::KEY_TAB},
+		{"clear", love::keyboard::Keyboard::KEY_CLEAR},
+		{"return", love::keyboard::Keyboard::KEY_RETURN},
+		{"pause", love::keyboard::Keyboard::KEY_PAUSE},
+		{"escape", love::keyboard::Keyboard::KEY_ESCAPE},
+		{" ", love::keyboard::Keyboard::KEY_SPACE},
+		{"!", love::keyboard::Keyboard::KEY_EXCLAIM},
+		{"\"", love::keyboard::Keyboard::KEY_QUOTEDBL},
+		{"#", love::keyboard::Keyboard::KEY_HASH},
+		{"$", love::keyboard::Keyboard::KEY_DOLLAR},
+		{"&", love::keyboard::Keyboard::KEY_AMPERSAND},
+		{"'", love::keyboard::Keyboard::KEY_QUOTE},
+		{"(", love::keyboard::Keyboard::KEY_LEFTPAREN},
+		{")", love::keyboard::Keyboard::KEY_RIGHTPAREN},
+		{"*", love::keyboard::Keyboard::KEY_ASTERISK},
+		{"+", love::keyboard::Keyboard::KEY_PLUS},
+		{",", love::keyboard::Keyboard::KEY_COMMA},
+		{"-", love::keyboard::Keyboard::KEY_MINUS},
+		{".", love::keyboard::Keyboard::KEY_PERIOD},
+		{"/", love::keyboard::Keyboard::KEY_SLASH},
+		{"0", love::keyboard::Keyboard::KEY_0},
+		{"1", love::keyboard::Keyboard::KEY_1},
+		{"2", love::keyboard::Keyboard::KEY_2},
+		{"3", love::keyboard::Keyboard::KEY_3},
+		{"4", love::keyboard::Keyboard::KEY_4},
+		{"5", love::keyboard::Keyboard::KEY_5},
+		{"6", love::keyboard::Keyboard::KEY_6},
+		{"7", love::keyboard::Keyboard::KEY_7},
+		{"8", love::keyboard::Keyboard::KEY_8},
+		{"9", love::keyboard::Keyboard::KEY_9},
+		{":", love::keyboard::Keyboard::KEY_COLON},
+		{";", love::keyboard::Keyboard::KEY_SEMICOLON},
+		{"<", love::keyboard::Keyboard::KEY_LESS},
+		{"=", love::keyboard::Keyboard::KEY_EQUALS},
+		{">", love::keyboard::Keyboard::KEY_GREATER},
+		{"?", love::keyboard::Keyboard::KEY_QUESTION},
+		{"@", love::keyboard::Keyboard::KEY_AT},
+
+		{"[", love::keyboard::Keyboard::KEY_LEFTBRACKET},
+		{"\\", love::keyboard::Keyboard::KEY_BACKSLASH},
+		{"]", love::keyboard::Keyboard::KEY_RIGHTBRACKET},
+		{"^", love::keyboard::Keyboard::KEY_CARET},
+		{"_", love::keyboard::Keyboard::KEY_UNDERSCORE},
+		{"`", love::keyboard::Keyboard::KEY_BACKQUOTE},
+		{"a", love::keyboard::Keyboard::KEY_A},
+		{"b", love::keyboard::Keyboard::KEY_B},
+		{"c", love::keyboard::Keyboard::KEY_C},
+		{"d", love::keyboard::Keyboard::KEY_D},
+		{"e", love::keyboard::Keyboard::KEY_E},
+		{"f", love::keyboard::Keyboard::KEY_F},
+		{"g", love::keyboard::Keyboard::KEY_G},
+		{"h", love::keyboard::Keyboard::KEY_H},
+		{"i", love::keyboard::Keyboard::KEY_I},
+		{"j", love::keyboard::Keyboard::KEY_J},
+		{"k", love::keyboard::Keyboard::KEY_K},
+		{"l", love::keyboard::Keyboard::KEY_L},
+		{"m", love::keyboard::Keyboard::KEY_M},
+		{"n", love::keyboard::Keyboard::KEY_N},
+		{"o", love::keyboard::Keyboard::KEY_O},
+		{"p", love::keyboard::Keyboard::KEY_P},
+		{"q", love::keyboard::Keyboard::KEY_Q},
+		{"r", love::keyboard::Keyboard::KEY_R},
+		{"s", love::keyboard::Keyboard::KEY_S},
+		{"t", love::keyboard::Keyboard::KEY_T},
+		{"u", love::keyboard::Keyboard::KEY_U},
+		{"v", love::keyboard::Keyboard::KEY_V},
+		{"w", love::keyboard::Keyboard::KEY_W},
+		{"x", love::keyboard::Keyboard::KEY_X},
+		{"y", love::keyboard::Keyboard::KEY_Y},
+		{"z", love::keyboard::Keyboard::KEY_Z},
+		{"delete", love::keyboard::Keyboard::KEY_DELETE},
+
+		{"kp0", love::keyboard::Keyboard::KEY_KP0},
+		{"kp1", love::keyboard::Keyboard::KEY_KP1},
+		{"kp2", love::keyboard::Keyboard::KEY_KP2},
+		{"kp3", love::keyboard::Keyboard::KEY_KP3},
+		{"kp4", love::keyboard::Keyboard::KEY_KP4},
+		{"kp5", love::keyboard::Keyboard::KEY_KP5},
+		{"kp6", love::keyboard::Keyboard::KEY_KP6},
+		{"kp7", love::keyboard::Keyboard::KEY_KP7},
+		{"kp8", love::keyboard::Keyboard::KEY_KP8},
+		{"kp9", love::keyboard::Keyboard::KEY_KP9},
+		{"kp.", love::keyboard::Keyboard::KEY_KP_PERIOD},
+		{"kp/", love::keyboard::Keyboard::KEY_KP_DIVIDE},
+		{"kp*", love::keyboard::Keyboard::KEY_KP_MULTIPLY},
+		{"kp-", love::keyboard::Keyboard::KEY_KP_MINUS},
+		{"kp+", love::keyboard::Keyboard::KEY_KP_PLUS},
+		{"kpenter", love::keyboard::Keyboard::KEY_KP_ENTER},
+		{"kp=", love::keyboard::Keyboard::KEY_KP_EQUALS},
+
+		{"kpup", love::keyboard::Keyboard::KEY_UP},
+		{"kpdown", love::keyboard::Keyboard::KEY_DOWN},
+		{"kpright", love::keyboard::Keyboard::KEY_RIGHT},
+		{"kpleft", love::keyboard::Keyboard::KEY_LEFT},
+		{"kpinsert", love::keyboard::Keyboard::KEY_INSERT},
+		{"kphome", love::keyboard::Keyboard::KEY_HOME},
+		{"kpend", love::keyboard::Keyboard::KEY_END},
+		{"kppageup", love::keyboard::Keyboard::KEY_PAGEUP},
+		{"kppagedown", love::keyboard::Keyboard::KEY_PAGEDOWN},
+
+		{"f1", love::keyboard::Keyboard::KEY_F1},
+		{"f2", love::keyboard::Keyboard::KEY_F2},
+		{"f3", love::keyboard::Keyboard::KEY_F3},
+		{"f4", love::keyboard::Keyboard::KEY_F4},
+		{"f5", love::keyboard::Keyboard::KEY_F5},
+		{"f6", love::keyboard::Keyboard::KEY_F6},
+		{"f7", love::keyboard::Keyboard::KEY_F7},
+		{"f8", love::keyboard::Keyboard::KEY_F8},
+		{"f9", love::keyboard::Keyboard::KEY_F9},
+		{"f10", love::keyboard::Keyboard::KEY_F10},
+		{"f11", love::keyboard::Keyboard::KEY_F11},
+		{"f12", love::keyboard::Keyboard::KEY_F12},
+		{"f13", love::keyboard::Keyboard::KEY_F13},
+		{"f14", love::keyboard::Keyboard::KEY_F14},
+		{"f15", love::keyboard::Keyboard::KEY_F15},
+
+		{"numlock", love::keyboard::Keyboard::KEY_NUMLOCK},
+		{"capslock", love::keyboard::Keyboard::KEY_CAPSLOCK},
+		{"scrollock", love::keyboard::Keyboard::KEY_SCROLLOCK},
+		{"rshift", love::keyboard::Keyboard::KEY_RSHIFT},
+		{"lshift", love::keyboard::Keyboard::KEY_LSHIFT},
+		{"rctrl", love::keyboard::Keyboard::KEY_RCTRL},
+		{"lctrl", love::keyboard::Keyboard::KEY_LCTRL},
+		{"ralt", love::keyboard::Keyboard::KEY_RALT},
+		{"lalt", love::keyboard::Keyboard::KEY_LALT},
+		{"rmeta", love::keyboard::Keyboard::KEY_RMETA},
+		{"lmeta", love::keyboard::Keyboard::KEY_LMETA},
+		{"lsuper", love::keyboard::Keyboard::KEY_LSUPER},
+		{"rsuper", love::keyboard::Keyboard::KEY_RSUPER},
+		{"mode", love::keyboard::Keyboard::KEY_MODE},
+		{"compose", love::keyboard::Keyboard::KEY_COMPOSE},
+
+		{"help", love::keyboard::Keyboard::KEY_HELP},
+		{"print", love::keyboard::Keyboard::KEY_PRINT},
+		{"sysreq", love::keyboard::Keyboard::KEY_SYSREQ},
+		{"break", love::keyboard::Keyboard::KEY_BREAK},
+		{"menu", love::keyboard::Keyboard::KEY_MENU},
+		{"power", love::keyboard::Keyboard::KEY_POWER},
+		{"euro", love::keyboard::Keyboard::KEY_EURO},
+		{"undo", love::keyboard::Keyboard::KEY_UNDO},
+	};
+
+	StringMap<love::keyboard::Keyboard::Key, love::keyboard::Keyboard::KEY_MAX_ENUM> Event::keys(Event::keyEntries, sizeof(Event::keyEntries));
+
+} // event
+} // love

+ 58 - 29
src/modules/event/Event.h

@@ -23,6 +23,9 @@
 
 // LOVE
 #include <common/Module.h>
+#include <common/StringMap.h>
+#include <keyboard/Keyboard.h>
+#include <mouse/Mouse.h>
 
 namespace love
 {
@@ -30,40 +33,66 @@ namespace event
 {
 	class Event : public Module
 	{
-	protected:
-		virtual ~Event(){};
 	public:
 
-		enum
+		enum Type
 		{
-		   EVENT_NOEVENT = 0,
-		   EVENT_ACTIVEEVENT,
-		   EVENT_KEYDOWN,
-		   EVENT_KEYUP,
-		   EVENT_MOUSEMOTION,	
-		   EVENT_MOUSEBUTTONDOWN,
-		   EVENT_MOUSEBUTTONUP,
-		   EVENT_JOYAXISMOTION,
-		   EVENT_JOYBALLMOTION,
-		   EVENT_JOYHATMOTION,
-		   EVENT_JOYBUTTONDOWN,
-		   EVENT_JOYBUTTONUP,
-		   EVENT_QUIT,
-		   EVENT_SYSWMEVENT,
-		   EVENT_RESERVEDA,
-		   EVENT_RESERVEDB,
-		   EVENT_VIDEORESIZE,
-		   EVENT_VIDEOEXPOSE,	
-		   EVENT_RESERVED2,
-		   EVENT_RESERVED3,	
-		   EVENT_RESERVED4,
-		   EVENT_RESERVED5,	
-		   EVENT_RESERVED6,
-		   EVENT_RESERVED7,	
-		   EVENT_USEREVENT = 24,
-		   EVENT_NUMEVENTS = 32
+		   TYPE_INVALID,
+		   TYPE_KEY_PRESSED,
+		   TYPE_KEY_RELEASED,
+		   TYPE_MOUSE_PRESSED,
+		   TYPE_MOUSE_RELEASED,
+		   TYPE_JOYSTICK_RELEASED,
+		   TYPE_JOYSTICK_PRESSED,
+		   TYPE_QUIT,
+		   TYPE_MAX_ENUM = 32
 		};
 
+		union Message
+		{
+			Type type;
+
+			struct 
+			{
+				Type type;
+				love::mouse::Mouse::Button b;
+				unsigned x;
+				unsigned y;
+			} mouse;
+
+			struct
+			{
+				Type type;
+				unsigned index;
+				unsigned button;
+			} joystick;
+
+			struct
+			{
+				Type type;
+				love::keyboard::Keyboard::Key k;
+				unsigned short u;
+			} keyboard;
+		};
+
+		virtual ~Event();
+
+		static bool getConstant(const char * in, Type & out);
+		static bool getConstant(Type in, const char *& out);
+		static bool getConstant(const char * in, love::mouse::Mouse::Button & out);
+		static bool getConstant(love::mouse::Mouse::Button in, const char *& out);
+		static bool getConstant(const char * in, love::keyboard::Keyboard::Key & out);
+		static bool getConstant(love::keyboard::Keyboard::Key in, const char *& out);
+
+	private:
+
+		static StringMap<Type, TYPE_MAX_ENUM>::Entry typeEntries[];
+		static StringMap<Type, TYPE_MAX_ENUM> types;
+		static StringMap<love::mouse::Mouse::Button, love::mouse::Mouse::BUTTON_MAX_ENUM>::Entry buttonEntries[];
+		static StringMap<love::mouse::Mouse::Button, love::mouse::Mouse::BUTTON_MAX_ENUM> buttons;
+		static StringMap<love::keyboard::Keyboard::Key, love::keyboard::Keyboard::KEY_MAX_ENUM>::Entry keyEntries[];
+		static StringMap<love::keyboard::Keyboard::Key, love::keyboard::Keyboard::KEY_MAX_ENUM> keys;
+
 	}; // Event
 
 } // event

+ 228 - 96
src/modules/event/sdl/Event.cpp

@@ -20,6 +20,9 @@
 
 #include "Event.h"
 
+#include <keyboard/Keyboard.h>
+#include <mouse/Mouse.h>
+
 namespace love
 {
 namespace event
@@ -31,138 +34,267 @@ namespace sdl
 		return "love.event.sdl";
 	}
 
+	Event::Event()
+	{
+		SDL_EnableUNICODE(1);
+	}
+
 	void Event::pump()
 	{
 		SDL_PumpEvents();
 	}
 
-	int Event::poll(lua_State * L)
+	bool Event::poll(Message & message)
 	{
-		lua_pushcclosure(L, &poll_i, 0);
-		return 1;
-	}
+		static SDL_Event e;
 
-	int Event::wait(lua_State * L)
-	{
 		SDL_EnableUNICODE(1);
 
-		// The union used to get SDL events. 
-		static SDL_Event e;
-
-		SDL_WaitEvent(&e);
+		while(SDL_PollEvent(&e))
+		{
+			if(convert(e, message))
+				return true;
+		}
 
-		return Event::pushEvent(L, e);
+		return false;
 	}
 
-	void Event::quit()
-	{
-		SDL_Event e;
-		e.type = Event::EVENT_QUIT;
-		SDL_PushEvent(&e);
-	}
-
-	int Event::push(lua_State * L)
-	{
-		SDL_Event e;
-		getEvent(L, e);
-		SDL_PushEvent(&e);
-		return 0;
-	}
-
-	int Event::poll_i(lua_State * L)
+	bool Event::wait(Message & message)
 	{
-		SDL_EnableUNICODE(1);
-
-		// The union used to get SDL events. 
 		static SDL_Event e;
-
-		// Get ONE event.
-		while(SDL_PollEvent(&e))
-		{
-			int args = Event::pushEvent(L, e);
-			if(args > 0)
-				return args;
-		}
-
-		// No pending events.
-		return 0;
+		bool ok = (SDL_WaitEvent(&e) == 1);
+		return ok && convert(e, message);
 	}
 
-	int Event::pushEvent(lua_State * L, SDL_Event & e)
+	bool Event::push(Message & message)
+	{
+		static SDL_Event e;
+		bool ok = convert(message, e);
+		return ok && (SDL_PushEvent(&e) == 0);
+	}
+
+	bool Event::convert(SDL_Event & e, Message & m)
 	{
 		switch(e.type)
 		{
 		case SDL_KEYDOWN:
-			lua_pushinteger(L, e.type);
-			lua_pushinteger(L, e.key.keysym.sym);
-			lua_pushinteger(L, e.key.keysym.unicode);
-			return 3;
+			m.type = Event::TYPE_KEY_PRESSED;
+			m.keyboard.u = e.key.keysym.unicode;
+			return keys.find(e.key.keysym.sym, m.keyboard.k);
 		case SDL_KEYUP:
-			lua_pushinteger(L, e.type);
-			lua_pushinteger(L, e.key.keysym.sym);
-			return 2;
+			m.type = Event::TYPE_KEY_RELEASED;
+			return keys.find(e.key.keysym.sym, m.keyboard.k);
 		case SDL_MOUSEBUTTONDOWN:
 		case SDL_MOUSEBUTTONUP:
-			lua_pushinteger(L, e.type);
-			lua_pushinteger(L, e.button.x);
-			lua_pushinteger(L, e.button.y);
-			lua_pushinteger(L, e.button.button);
-			return 4;
+			m.type = (e.type == SDL_MOUSEBUTTONDOWN) ? Event::TYPE_MOUSE_PRESSED : Event::TYPE_MOUSE_RELEASED;
+			m.mouse.x = e.button.x;
+			m.mouse.y = e.button.y;
+			return buttons.find(e.button.button, m.mouse.b);
 		case SDL_JOYBUTTONDOWN:
 		case SDL_JOYBUTTONUP:
-			lua_pushinteger(L, e.type);
-			lua_pushinteger(L, e.jbutton.which);
-			lua_pushinteger(L, e.jbutton.button);
-			return 3;
+			m.type = (e.type == SDL_JOYBUTTONDOWN) ? Event::TYPE_JOYSTICK_PRESSED : Event::TYPE_JOYSTICK_RELEASED;
+			m.joystick.button = e.jbutton.button;
+			m.joystick.index = e.jbutton.which;
+			return true;
 		case SDL_QUIT:
-			lua_pushinteger(L, e.type);
-			return 1;
-		default:
-			break;
+			m.type = Event::TYPE_QUIT;
+			return true;
 		}
 
-		return 0;
+		return false;
 	}
 
-	int Event::getEvent(lua_State * L, SDL_Event & e)
+	bool Event::convert(Message & m, SDL_Event & e)
 	{
-		int type = luaL_checkint(L, 1);
-
-		switch(type)
+		switch(m.type)
 		{
-		case EVENT_KEYDOWN:
-			e.type = type;
-			e.key.keysym.sym = (SDLKey)luaL_checkint(L, 2);
-			e.key.keysym.unicode = luaL_checkint(L, 3);
-			return 3;
-		case EVENT_KEYUP:
-			e.type = type;
-			e.key.keysym.sym = (SDLKey)luaL_checkint(L, 2);
-			return 2;
-		case EVENT_MOUSEBUTTONDOWN:
-		case EVENT_MOUSEBUTTONUP:
-			e.type = type;
-			e.button.x = luaL_checkint(L, 2);
-			e.button.y = luaL_checkint(L, 3);
-			e.button.button = luaL_checkint(L, 4);
-			return 4;
-		case EVENT_JOYBUTTONDOWN:
-		case EVENT_JOYBUTTONUP:
-			e.type = type;
-			e.jbutton.which = luaL_checkint(L, 2);
-			e.jbutton.button = luaL_checkint(L, 3);
-			return 3;
-		case EVENT_QUIT:
-			e.type = type;
-			return 1;
-		default:
-			e.type = EVENT_NOEVENT;
-			break;
+		case Event::TYPE_KEY_PRESSED:
+			e.type = SDL_KEYDOWN;
+			e.key.keysym.unicode = (Uint16)m.keyboard.u;
+			return keys.find(m.keyboard.k, e.key.keysym.sym);;
+		case Event::TYPE_KEY_RELEASED:
+			e.type = SDL_KEYUP;
+			return keys.find(m.keyboard.k, e.key.keysym.sym);
+		case Event::TYPE_MOUSE_PRESSED:
+		case Event::TYPE_MOUSE_RELEASED:
+			e.type = (m.type == Event::TYPE_MOUSE_PRESSED) ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP;
+			e.button.x = m.mouse.x;
+			e.button.y = m.mouse.y;
+			return buttons.find(m.mouse.b, e.button.button);
+		case Event::TYPE_JOYSTICK_PRESSED:
+		case Event::TYPE_JOYSTICK_RELEASED:
+			e.type = (m.type == Event::TYPE_JOYSTICK_PRESSED) ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP;
+			e.jbutton.which = m.joystick.index;
+			e.jbutton.button = m.joystick.button;
+			return true;
+		case Event::TYPE_QUIT:
+			e.type = SDL_QUIT;
+			return true;
 		}
 
-		return 0;
+		return true;
 	}
 
+	EnumMap<love::keyboard::Keyboard::Key, SDLKey, love::keyboard::Keyboard::KEY_MAX_ENUM>::Entry Event::keyEntries[] = 
+	{
+		{ love::keyboard::Keyboard::KEY_BACKSPACE, SDLK_BACKSPACE},
+		{ love::keyboard::Keyboard::KEY_TAB, SDLK_TAB},
+		{ love::keyboard::Keyboard::KEY_CLEAR, SDLK_CLEAR},
+		{ love::keyboard::Keyboard::KEY_RETURN, SDLK_RETURN},
+		{ love::keyboard::Keyboard::KEY_PAUSE, SDLK_PAUSE},
+		{ love::keyboard::Keyboard::KEY_ESCAPE, SDLK_ESCAPE },
+		{ love::keyboard::Keyboard::KEY_SPACE, SDLK_SPACE },
+		{ love::keyboard::Keyboard::KEY_EXCLAIM, SDLK_EXCLAIM },
+		{ love::keyboard::Keyboard::KEY_QUOTEDBL, SDLK_QUOTEDBL },
+		{ love::keyboard::Keyboard::KEY_HASH, SDLK_HASH },
+		{ love::keyboard::Keyboard::KEY_DOLLAR, SDLK_DOLLAR },
+		{ love::keyboard::Keyboard::KEY_AMPERSAND, SDLK_AMPERSAND },
+		{ love::keyboard::Keyboard::KEY_QUOTE, SDLK_QUOTE },
+		{ love::keyboard::Keyboard::KEY_LEFTPAREN, SDLK_LEFTPAREN },
+		{ love::keyboard::Keyboard::KEY_RIGHTPAREN, SDLK_RIGHTPAREN },
+		{ love::keyboard::Keyboard::KEY_ASTERISK, SDLK_ASTERISK },
+		{ love::keyboard::Keyboard::KEY_PLUS, SDLK_PLUS },
+		{ love::keyboard::Keyboard::KEY_COMMA, SDLK_COMMA },
+		{ love::keyboard::Keyboard::KEY_MINUS, SDLK_MINUS },
+		{ love::keyboard::Keyboard::KEY_PERIOD, SDLK_PERIOD },
+		{ love::keyboard::Keyboard::KEY_SLASH, SDLK_SLASH },
+		{ love::keyboard::Keyboard::KEY_0, SDLK_0 },
+		{ love::keyboard::Keyboard::KEY_1, SDLK_1 },
+		{ love::keyboard::Keyboard::KEY_2, SDLK_2 },
+		{ love::keyboard::Keyboard::KEY_3, SDLK_3 },
+		{ love::keyboard::Keyboard::KEY_4, SDLK_4 },
+		{ love::keyboard::Keyboard::KEY_5, SDLK_5 },
+		{ love::keyboard::Keyboard::KEY_6, SDLK_6 },
+		{ love::keyboard::Keyboard::KEY_7, SDLK_7 },
+		{ love::keyboard::Keyboard::KEY_8, SDLK_8 },
+		{ love::keyboard::Keyboard::KEY_9, SDLK_9 },
+		{ love::keyboard::Keyboard::KEY_COLON, SDLK_COLON },
+		{ love::keyboard::Keyboard::KEY_SEMICOLON, SDLK_SEMICOLON },
+		{ love::keyboard::Keyboard::KEY_LESS, SDLK_LESS },
+		{ love::keyboard::Keyboard::KEY_EQUALS, SDLK_EQUALS },
+		{ love::keyboard::Keyboard::KEY_GREATER, SDLK_GREATER },
+		{ love::keyboard::Keyboard::KEY_QUESTION, SDLK_QUESTION },
+		{ love::keyboard::Keyboard::KEY_AT, SDLK_AT },
+
+		{ love::keyboard::Keyboard::KEY_LEFTBRACKET, SDLK_LEFTBRACKET },
+		{ love::keyboard::Keyboard::KEY_BACKSLASH, SDLK_BACKSLASH },
+		{ love::keyboard::Keyboard::KEY_RIGHTBRACKET, SDLK_RIGHTBRACKET },
+		{ love::keyboard::Keyboard::KEY_CARET, SDLK_CARET },
+		{ love::keyboard::Keyboard::KEY_UNDERSCORE, SDLK_UNDERSCORE },
+		{ love::keyboard::Keyboard::KEY_BACKQUOTE, SDLK_BACKQUOTE },
+		{ love::keyboard::Keyboard::KEY_A, SDLK_a },
+		{ love::keyboard::Keyboard::KEY_B, SDLK_b },
+		{ love::keyboard::Keyboard::KEY_C, SDLK_c },
+		{ love::keyboard::Keyboard::KEY_D, SDLK_d },
+		{ love::keyboard::Keyboard::KEY_E, SDLK_e },
+		{ love::keyboard::Keyboard::KEY_F, SDLK_f },
+		{ love::keyboard::Keyboard::KEY_G, SDLK_g },
+		{ love::keyboard::Keyboard::KEY_H, SDLK_h },
+		{ love::keyboard::Keyboard::KEY_I, SDLK_i },
+		{ love::keyboard::Keyboard::KEY_J, SDLK_j },
+		{ love::keyboard::Keyboard::KEY_K, SDLK_k },
+		{ love::keyboard::Keyboard::KEY_L, SDLK_l },
+		{ love::keyboard::Keyboard::KEY_M, SDLK_m },
+		{ love::keyboard::Keyboard::KEY_N, SDLK_n },
+		{ love::keyboard::Keyboard::KEY_O, SDLK_o },
+		{ love::keyboard::Keyboard::KEY_P, SDLK_p },
+		{ love::keyboard::Keyboard::KEY_Q, SDLK_q },
+		{ love::keyboard::Keyboard::KEY_R, SDLK_r },
+		{ love::keyboard::Keyboard::KEY_S, SDLK_s },
+		{ love::keyboard::Keyboard::KEY_T, SDLK_t },
+		{ love::keyboard::Keyboard::KEY_U, SDLK_u },
+		{ love::keyboard::Keyboard::KEY_V, SDLK_v },
+		{ love::keyboard::Keyboard::KEY_W, SDLK_w },
+		{ love::keyboard::Keyboard::KEY_X, SDLK_x },
+		{ love::keyboard::Keyboard::KEY_Y, SDLK_y },
+		{ love::keyboard::Keyboard::KEY_Z, SDLK_z },
+		{ love::keyboard::Keyboard::KEY_DELETE, SDLK_DELETE },
+
+		{ love::keyboard::Keyboard::KEY_KP0, SDLK_KP0 },
+		{ love::keyboard::Keyboard::KEY_KP1, SDLK_KP1 },
+		{ love::keyboard::Keyboard::KEY_KP2, SDLK_KP2 },
+		{ love::keyboard::Keyboard::KEY_KP3, SDLK_KP3 },
+		{ love::keyboard::Keyboard::KEY_KP4, SDLK_KP4 },
+		{ love::keyboard::Keyboard::KEY_KP5, SDLK_KP5 },
+		{ love::keyboard::Keyboard::KEY_KP6, SDLK_KP6 },
+		{ love::keyboard::Keyboard::KEY_KP7, SDLK_KP7 },
+		{ love::keyboard::Keyboard::KEY_KP8, SDLK_KP8 },
+		{ love::keyboard::Keyboard::KEY_KP9, SDLK_KP9 },
+		{ love::keyboard::Keyboard::KEY_KP_PERIOD, SDLK_KP_PERIOD },
+		{ love::keyboard::Keyboard::KEY_KP_DIVIDE, SDLK_KP_DIVIDE },
+		{ love::keyboard::Keyboard::KEY_KP_MULTIPLY, SDLK_KP_MULTIPLY},
+		{ love::keyboard::Keyboard::KEY_KP_MINUS, SDLK_KP_MINUS },
+		{ love::keyboard::Keyboard::KEY_KP_PLUS, SDLK_KP_PLUS },
+		{ love::keyboard::Keyboard::KEY_KP_ENTER, SDLK_KP_ENTER },
+		{ love::keyboard::Keyboard::KEY_KP_EQUALS, SDLK_KP_EQUALS },
+
+		{ love::keyboard::Keyboard::KEY_UP, SDLK_UP },
+		{ love::keyboard::Keyboard::KEY_DOWN, SDLK_DOWN },
+		{ love::keyboard::Keyboard::KEY_RIGHT, SDLK_RIGHT },
+		{ love::keyboard::Keyboard::KEY_LEFT, SDLK_LEFT },
+		{ love::keyboard::Keyboard::KEY_INSERT, SDLK_INSERT },
+		{ love::keyboard::Keyboard::KEY_HOME, SDLK_HOME },
+		{ love::keyboard::Keyboard::KEY_END, SDLK_END },
+		{ love::keyboard::Keyboard::KEY_PAGEUP, SDLK_PAGEUP },
+		{ love::keyboard::Keyboard::KEY_PAGEDOWN, SDLK_PAGEDOWN },
+
+		{ love::keyboard::Keyboard::KEY_F1, SDLK_F1 },
+		{ love::keyboard::Keyboard::KEY_F2, SDLK_F2 },
+		{ love::keyboard::Keyboard::KEY_F3, SDLK_F3 },
+		{ love::keyboard::Keyboard::KEY_F4, SDLK_F4 },
+		{ love::keyboard::Keyboard::KEY_F5, SDLK_F5 },
+		{ love::keyboard::Keyboard::KEY_F6, SDLK_F6 },
+		{ love::keyboard::Keyboard::KEY_F7, SDLK_F7 },
+		{ love::keyboard::Keyboard::KEY_F8, SDLK_F8 },
+		{ love::keyboard::Keyboard::KEY_F9, SDLK_F9 },
+		{ love::keyboard::Keyboard::KEY_F10, SDLK_F10 },
+		{ love::keyboard::Keyboard::KEY_F11, SDLK_F11 },
+		{ love::keyboard::Keyboard::KEY_F12, SDLK_F12 },
+		{ love::keyboard::Keyboard::KEY_F13, SDLK_F13 },
+		{ love::keyboard::Keyboard::KEY_F14, SDLK_F14 },
+		{ love::keyboard::Keyboard::KEY_F15, SDLK_F15 },
+
+		{ love::keyboard::Keyboard::KEY_NUMLOCK, SDLK_NUMLOCK },
+		{ love::keyboard::Keyboard::KEY_CAPSLOCK, SDLK_CAPSLOCK },
+		{ love::keyboard::Keyboard::KEY_SCROLLOCK, SDLK_SCROLLOCK },
+		{ love::keyboard::Keyboard::KEY_RSHIFT, SDLK_RSHIFT },
+		{ love::keyboard::Keyboard::KEY_LSHIFT, SDLK_LSHIFT },
+		{ love::keyboard::Keyboard::KEY_RCTRL, SDLK_RCTRL },
+		{ love::keyboard::Keyboard::KEY_LCTRL, SDLK_LCTRL },
+		{ love::keyboard::Keyboard::KEY_RALT, SDLK_RALT },
+		{ love::keyboard::Keyboard::KEY_LALT, SDLK_LALT },
+		{ love::keyboard::Keyboard::KEY_RMETA, SDLK_RMETA },
+		{ love::keyboard::Keyboard::KEY_LMETA, SDLK_LMETA },
+		{ love::keyboard::Keyboard::KEY_LSUPER, SDLK_LSUPER },
+		{ love::keyboard::Keyboard::KEY_RSUPER, SDLK_RSUPER },
+		{ love::keyboard::Keyboard::KEY_MODE, SDLK_MODE },
+		{ love::keyboard::Keyboard::KEY_COMPOSE, SDLK_COMPOSE },
+
+		{ love::keyboard::Keyboard::KEY_HELP, SDLK_HELP },
+		{ love::keyboard::Keyboard::KEY_PRINT, SDLK_PRINT },
+		{ love::keyboard::Keyboard::KEY_SYSREQ, SDLK_SYSREQ },
+		{ love::keyboard::Keyboard::KEY_BREAK, SDLK_BREAK },
+		{ love::keyboard::Keyboard::KEY_MENU, SDLK_MENU },
+		{ love::keyboard::Keyboard::KEY_POWER, SDLK_POWER },
+		{ love::keyboard::Keyboard::KEY_EURO, SDLK_EURO },
+		{ love::keyboard::Keyboard::KEY_UNDO, SDLK_UNDO },
+	};
+
+	EnumMap<love::keyboard::Keyboard::Key, SDLKey, love::keyboard::Keyboard::KEY_MAX_ENUM> Event::keys(Event::keyEntries, sizeof(Event::keyEntries));
+
+	EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM>::Entry Event::buttonEntries[] = 
+	{
+		{ love::mouse::Mouse::BUTTON_LEFT, SDL_BUTTON_LEFT},
+		{ love::mouse::Mouse::BUTTON_MIDDLE, SDL_BUTTON_MIDDLE},
+		{ love::mouse::Mouse::BUTTON_RIGHT, SDL_BUTTON_RIGHT},
+		{ love::mouse::Mouse::BUTTON_WHEELUP, SDL_BUTTON_WHEELUP},
+		{ love::mouse::Mouse::BUTTON_WHEELDOWN, SDL_BUTTON_WHEELDOWN},
+		{ love::mouse::Mouse::BUTTON_X1, SDL_BUTTON_X1},
+		{ love::mouse::Mouse::BUTTON_X2, SDL_BUTTON_X2},
+	};
+
+	EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM> Event::buttons(Event::buttonEntries, sizeof(Event::buttonEntries));
+
 } // sdl
 } // event
 } // love

+ 25 - 22
src/modules/event/sdl/Event.h

@@ -24,6 +24,7 @@
 // LOVE
 #include <event/Event.h>
 #include <common/runtime.h>
+#include <common/EnumMap.h>
 
 // SDL
 #include <SDL.h>
@@ -34,13 +35,15 @@ namespace event
 {
 namespace sdl
 {
-	class Event : public event::Event
+	class Event : public love::event::Event
 	{
 	public:
 		
 		// Implements Module.
 		const char * getName() const;
 
+		Event();
+
 		/**
 		* Pumps the event queue. This function gathers all the pending input information 
 		* from devices and places it on the event queue. Normally not needed if you poll
@@ -48,38 +51,38 @@ namespace sdl
 		**/ 
 		void pump();
 
-		/**
-		* Returns an iterator function for iterating over pending events.
+		/**
+		* Checks if there are messages in the queue. 
+		* 
+		* @param message The next message in the queue, if the return value is true.
+		* @return True if there a message was found, false otherwise.
 		**/
-		int poll(lua_State * L);
-		
+		bool poll(Message & message);
+
 		/**
 		* Waits for the next event (indefinitely). Useful for creating games where
 		* the screen and game state only needs updating when the user interacts with
 		* the window.
 		**/
-		int wait(lua_State * L);
-
-		/**
-		* Push a quit event. Calling this does not mean the application
-		* will exit immediately, it just means an quit event will be issued. 
-		* How to respond to the quit event is up the application. 
-		**/
-		void quit();
-
-		/**
-		* Pushes an event into the queue.
-		**/
-		int push(lua_State * L);
+		bool wait(Message & message);
 
 		/**
-		* The iterator function.
+		* Push a message onto the event queue.
+		* 
+		* @param message The message to push onto the queue.
+		* @return True on success, false if the queue was full. 
 		**/
-		static int poll_i(lua_State * L);
+		bool push(Message & message);
+
 	private:
 
-		static int pushEvent(lua_State * L, SDL_Event & e);
-		static int getEvent(lua_State * L, SDL_Event & e);
+		bool convert(SDL_Event & e, Message & m);
+		bool convert(Message & m, SDL_Event & e);
+
+		static EnumMap<love::keyboard::Keyboard::Key, SDLKey, love::keyboard::Keyboard::KEY_MAX_ENUM>::Entry keyEntries[];
+		static EnumMap<love::keyboard::Keyboard::Key, SDLKey, love::keyboard::Keyboard::KEY_MAX_ENUM> keys;
+		static EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM>::Entry buttonEntries[];
+		static EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM> buttons;
 
 	}; // System
 

+ 113 - 21
src/modules/event/sdl/wrap_Event.cpp

@@ -34,6 +34,100 @@ namespace sdl
 {
 	static Event * instance = 0;
 	
+	static bool to_message(lua_State * L, Event::Message & msg)
+	{
+		const char * str = luaL_checkstring(L, 1);
+
+		if(!Event::getConstant(str, msg.type))
+			return false;
+
+		switch(msg.type)
+		{
+		case Event::TYPE_KEY_PRESSED:
+			if(!Event::getConstant(luaL_checkstring(L, 2), msg.keyboard.k))
+				return false;
+			msg.keyboard.u = (unsigned short)luaL_optint(L, 3, 0);
+			return true;
+		case Event::TYPE_KEY_RELEASED:
+			if(!Event::getConstant(luaL_checkstring(L, 2), msg.keyboard.k))
+				return false;
+			return true;
+		case Event::TYPE_MOUSE_PRESSED:
+		case Event::TYPE_MOUSE_RELEASED:
+			if(!Event::getConstant(luaL_checkstring(L, 2), msg.mouse.b))
+				return false;
+			msg.mouse.x = luaL_checkint(L, 3);
+			msg.mouse.y = luaL_checkint(L, 4);
+			return true;
+		case Event::TYPE_JOYSTICK_PRESSED:
+		case Event::TYPE_JOYSTICK_RELEASED:
+			msg.joystick.index = luaL_checkint(L, 2);
+			msg.joystick.button = luaL_checkint(L, 3);
+			return true;
+		case Event::TYPE_QUIT:
+			return true;
+		}
+
+		return false;
+	}
+
+	static int push_message(lua_State * L, const Event::Message & msg)
+	{
+		const char * str = 0;
+
+		if(!Event::getConstant(msg.type, str))
+			return 0;
+
+		lua_pushstring(L, str);
+
+		switch(msg.type)
+		{
+		case Event::TYPE_KEY_PRESSED:
+			if(!Event::getConstant(msg.keyboard.k, str))
+				return 0;
+			lua_pushstring(L, str);
+			lua_pushinteger(L, msg.keyboard.u);
+			return 3;
+		case Event::TYPE_KEY_RELEASED:
+			if(!Event::getConstant(msg.keyboard.k, str))
+				return 0;
+			lua_pushstring(L, str);
+			return 2;
+		case Event::TYPE_MOUSE_PRESSED:
+		case Event::TYPE_MOUSE_RELEASED:
+			if(!Event::getConstant(msg.mouse.b, str))
+				return 0;
+			lua_pushinteger(L, msg.mouse.x);
+			lua_pushinteger(L, msg.mouse.y);
+			lua_pushstring(L, str);
+			return 4;
+		case Event::TYPE_JOYSTICK_PRESSED:
+		case Event::TYPE_JOYSTICK_RELEASED:
+			lua_pushinteger(L, msg.joystick.index);
+			lua_pushinteger(L, msg.joystick.button);
+			return 3;
+		case Event::TYPE_QUIT:
+			return 1;
+		}
+
+		return 0;
+	}
+
+	static int poll_i(lua_State * L)
+	{
+		static Event::Message m;
+
+		while(instance->poll(m))
+		{
+			int args = push_message(L, m);
+			if(args > 0)
+				return args;
+		}
+
+		// No pending events.
+		return 0;
+	}
+
 	int w_pump(lua_State * L)
 	{
 		instance->pump();
@@ -42,23 +136,35 @@ namespace sdl
 
 	int w_poll(lua_State * L)
 	{
-		return instance->poll(L);
+		lua_pushcclosure(L, &poll_i, 0);
+		return 1;
 	}
 
 	int w_wait(lua_State * L)
 	{
-		return instance->wait(L);
-	}
+		static Event::Message m;
+
+		if(instance->wait(m))
+		{
+			return push_message(L, m);
+		}
 
-	int w_quit(lua_State * L)
-	{
-		instance->quit();
 		return 0;
 	}
 
 	int w_push(lua_State * L)
 	{
-		return instance->push(L);
+		static Event::Message m;
+
+		if(!to_message(L, m))
+		{
+			luax_pushboolean(L, false);
+			return 1;
+		}
+
+		luax_pushboolean(L, instance->push(m));
+
+		return 1;
 	}
 
 	// List of functions to wrap.
@@ -66,23 +172,10 @@ namespace sdl
 		{ "pump", w_pump }, 
 		{ "poll", w_poll }, 
 		{ "wait", w_wait }, 
-		{ "quit", w_quit }, 
 		{ "push", w_push }, 
 		{ 0, 0 }
 	};
 
-	// List of constants.
-	static const Constant constants[] = {
-		{ "event_keypressed", Event::EVENT_KEYDOWN },
-		{ "event_keyreleased", Event::EVENT_KEYUP },
-		{ "event_mousepressed", Event::EVENT_MOUSEBUTTONDOWN },
-		{ "event_mousereleased", Event::EVENT_MOUSEBUTTONUP },
-		{ "event_joystickpressed", Event::EVENT_JOYBUTTONDOWN },
-		{ "event_joystickreleased", Event::EVENT_JOYBUTTONUP },
-		{ "event_quit", Event::EVENT_QUIT },
-		{ 0, 0 }
-	};
-
 	int luaopen_love_event(lua_State * L)
 	{
 		if(instance == 0)
@@ -103,7 +196,6 @@ namespace sdl
 		w.flags = MODULE_T;
 		w.functions = functions;
 		w.types = 0;
-		w.constants = constants;
 
 		return luax_register_module(L, w);
 	}

+ 0 - 1
src/modules/event/sdl/wrap_Event.h

@@ -34,7 +34,6 @@ namespace sdl
 	int w_pump(lua_State * L);
 	int w_poll(lua_State * L);
 	int w_wait(lua_State * L);
-	int w_quit(lua_State * L);
 	int w_push(lua_State * L);
 
 	extern "C" LOVE_EXPORT int luaopen_love_event(lua_State * L);

+ 25 - 30
src/modules/signal/posix/Signal.h → src/modules/filesystem/File.cpp

@@ -18,40 +18,35 @@
 * 3. This notice may not be removed or altered from any source distribution.
 **/
 
-#ifndef LOVE_SIGNAL_POSIX_SIGNAL_H
-#define LOVE_SIGNAL_POSIX_SIGNAL_H
-
-// signal
-#include <csignal>
-
-// LOVE
-#include <common/Module.h>
-#include <common/Reference.h>
+#include "File.h"
 
 namespace love
 {
-namespace signal
+namespace filesystem
 {
-namespace posix
-{
-	class Signal : public Module
+	File::~File()
 	{
-	private:
-		int signals;
+	}
+
+	bool File::getConstant(const char * in, Mode & out)
+	{
+		return modes.find(in, out);
+	}
+
+	bool File::getConstant(Mode in, const char *& out)
+	{
+		return modes.find(in, out);
+	}
+
+	StringMap<File::Mode, File::MODE_MAX_ENUM>::Entry File::modeEntries[] = 
+	{
+		{"c", File::CLOSED},
+		{"r", File::READ},
+		{"w", File::WRITE},
+		{"w+", File::APPEND},
+	};
+
+	StringMap<File::Mode, File::MODE_MAX_ENUM> File::modes(File::modeEntries, sizeof(File::modeEntries));
 
-	public:
-		Signal();
-		~Signal();
-		bool hook(int sgn);
-		void setCallback(lua_State *L);
-		const char * getName() const;
-		bool raise(int sgn);
-	}; // Signal
-	
-	void handler(int signal);
-	static Reference *cb;
-} // posix
-} // signal
+} // filesystem
 } // love
-
-#endif // LOVE_SIGNAL_POSIX_SIGNAL_H

+ 11 - 1
src/modules/filesystem/File.h

@@ -27,6 +27,7 @@
 // LOVE
 #include <common/Data.h>
 #include <common/Object.h>
+#include <common/StringMap.h>
 
 namespace love
 {
@@ -49,6 +50,7 @@ namespace filesystem
 			READ,
 			WRITE,
 			APPEND,
+			MODE_MAX_ENUM
 		};
 
 		/**
@@ -59,7 +61,7 @@ namespace filesystem
 		/**
 		* Destructor.
 		**/
-		virtual ~File(){};
+		virtual ~File();
 
 		/**
 		* Opens the file in a certain mode.
@@ -158,6 +160,14 @@ namespace filesystem
 		**/
 		virtual std::string getExtension() const = 0;
 
+		static bool getConstant(const char * in, Mode & out);
+		static bool getConstant(Mode in, const char *& out);
+
+	private:
+
+		static StringMap<Mode, MODE_MAX_ENUM>::Entry modeEntries[];
+		static StringMap<Mode, MODE_MAX_ENUM> modes;
+
 	}; // File
 
 } // filesystem

+ 4 - 4
src/modules/filesystem/physfs/File.cpp

@@ -21,7 +21,7 @@
 #include "File.h"
 
 // STD
-#include <string.h>
+#include <cstring>
 
 // LOVE
 #include "Filesystem.h"
@@ -46,6 +46,9 @@ namespace physfs
 	
 	bool File::open(Mode mode)
 	{
+		if(mode == CLOSED)
+			return true;
+
 		// File must exist if read mode.
 		if((mode == READ))
 			if(!PHYSFS_exists(filename.c_str()))
@@ -73,9 +76,6 @@ namespace physfs
 		case WRITE:
 			file = PHYSFS_openWrite(filename.c_str());
 			break;
-		case CLOSED:
-			// Heh. Case closed.
-			return true;
 		}
 
 		return (file != 0);

+ 5 - 2
src/modules/filesystem/physfs/wrap_File.cpp

@@ -44,11 +44,14 @@ namespace physfs
 	int w_File_open(lua_State * L)
 	{
 		File * file = luax_checkfile(L, 1);
-		int mode = luaL_optint(L, 2, File::READ);
+		File::Mode mode;
+
+		if(!File::getConstant(luaL_checkstring(L, 2), mode))
+			return luaL_error(L, "Incorrect file open mode: %s", luaL_checkstring(L, 2));
 
 		try
 		{
-			lua_pushboolean(L, file->open((File::Mode)mode) ? 1 : 0);
+			lua_pushboolean(L, file->open(mode) ? 1 : 0);
 		}
 		catch(Exception e)
 		{

+ 0 - 10
src/modules/filesystem/physfs/wrap_Filesystem.cpp

@@ -265,15 +265,6 @@ namespace physfs
 		0
 	};
 
-	// List of constants.
-	static const Constant constants[] = {
-		{ "file_closed", File::CLOSED },
-		{ "file_read", File::READ },
-		{ "file_write", File::WRITE },
-		{ "file_append", File::APPEND },
-		{ 0, 0 }
-	};
-
 	int luaopen_love_filesystem(lua_State * L)
 	{
 		if(instance == 0)
@@ -295,7 +286,6 @@ namespace physfs
 		w.flags = MODULE_FILESYSTEM_T;
 		w.functions = functions;
 		w.types = types;
-		w.constants = constants;
 
 		return luax_register_module(L, w);
 	}

+ 0 - 1
src/modules/font/freetype/wrap_Font.cpp

@@ -86,7 +86,6 @@ namespace freetype
 		w.flags = MODULE_T;
 		w.functions = functions;
 		w.types = types;
-		w.constants = 0;
 
 		return luax_register_module(L, w);
 	}

+ 141 - 0
src/modules/graphics/Graphics.cpp

@@ -0,0 +1,141 @@
+/**
+* Copyright (c) 2006-2009 LOVE Development Team
+* 
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* 
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#include "Graphics.h"
+
+namespace love
+{
+namespace graphics
+{
+	Graphics::~Graphics()
+	{
+	}
+
+	bool Graphics::getConstant(const char * in, DrawMode & out)
+	{
+		return drawModes.find(in, out);
+	}
+
+	bool Graphics::getConstant(DrawMode in, const char *& out)
+	{
+		return drawModes.find(in, out);
+	}
+
+	bool Graphics::getConstant(const char * in, AlignMode & out)
+	{
+		return alignModes.find(in, out);
+	}
+
+	bool Graphics::getConstant(AlignMode in, const char *& out)
+	{
+		return alignModes.find(in, out);
+	}
+
+	bool Graphics::getConstant(const char * in, BlendMode & out)
+	{
+		return blendModes.find(in, out);
+	}
+
+	bool Graphics::getConstant(BlendMode in, const char *& out)
+	{
+		return blendModes.find(in, out);
+	}
+
+	bool Graphics::getConstant(const char * in, ColorMode & out)
+	{
+		return colorModes.find(in, out);
+	}
+
+	bool Graphics::getConstant(ColorMode in, const char *& out)
+	{
+		return colorModes.find(in, out);
+	}
+
+	bool Graphics::getConstant(const char * in, LineStyle & out)
+	{
+		return lineStyles.find(in, out);
+	}
+
+	bool Graphics::getConstant(LineStyle in, const char *& out)
+	{
+		return lineStyles.find(in, out);
+	}
+
+	bool Graphics::getConstant(const char * in, PointStyle & out)
+	{
+		return pointStyles.find(in, out);
+	}
+
+	bool Graphics::getConstant(PointStyle in, const char *& out)
+	{
+		return pointStyles.find(in, out);
+	}
+
+	StringMap<Graphics::DrawMode, Graphics::DRAW_MAX_ENUM>::Entry Graphics::drawModeEntries[] = 
+	{
+		{ "line", Graphics::DRAW_LINE },
+		{ "fill", Graphics::DRAW_FILL },
+	};
+
+	StringMap<Graphics::DrawMode, Graphics::DRAW_MAX_ENUM> Graphics::drawModes(Graphics::drawModeEntries, sizeof(Graphics::drawModeEntries));
+
+	StringMap<Graphics::AlignMode, Graphics::ALIGN_MAX_ENUM>::Entry Graphics::alignModeEntries[] = 
+	{
+		{ "left", Graphics::ALIGN_LEFT },
+		{ "right", Graphics::ALIGN_RIGHT },
+		{ "center", Graphics::ALIGN_CENTER },
+	};
+
+	StringMap<Graphics::AlignMode, Graphics::ALIGN_MAX_ENUM> Graphics::alignModes(Graphics::alignModeEntries, sizeof(Graphics::alignModeEntries));
+
+	StringMap<Graphics::BlendMode, Graphics::BLEND_MAX_ENUM>::Entry Graphics::blendModeEntries[] = 
+	{
+		{ "alpha", Graphics::BLEND_ALPHA },
+		{ "additive", Graphics::BLEND_ADDITIVE },
+	};
+
+	StringMap<Graphics::BlendMode, Graphics::BLEND_MAX_ENUM> Graphics::blendModes(Graphics::blendModeEntries, sizeof(Graphics::blendModeEntries));
+
+	StringMap<Graphics::ColorMode, Graphics::COLOR_MAX_ENUM>::Entry Graphics::colorModeEntries[] = 
+	{
+		{ "replace", Graphics::COLOR_REPLACE },
+		{ "modulate", Graphics::COLOR_MODULATE },
+	};
+
+	StringMap<Graphics::ColorMode, Graphics::COLOR_MAX_ENUM> Graphics::colorModes(Graphics::colorModeEntries, sizeof(Graphics::colorModeEntries));
+
+	StringMap<Graphics::LineStyle, Graphics::LINE_MAX_ENUM>::Entry Graphics::lineStyleEntries[] = 
+	{
+		{ "smooth", Graphics::LINE_SMOOTH },
+		{ "rough", Graphics::LINE_ROUGH }
+	};
+
+	StringMap<Graphics::LineStyle, Graphics::LINE_MAX_ENUM> Graphics::lineStyles(Graphics::lineStyleEntries, sizeof(Graphics::lineStyleEntries));
+
+	StringMap<Graphics::PointStyle, Graphics::POINT_MAX_ENUM>::Entry Graphics::pointStyleEntries[] = 
+	{
+		{ "smooth", Graphics::POINT_SMOOTH },
+		{ "rough", Graphics::POINT_ROUGH }
+	};
+
+	StringMap<Graphics::PointStyle, Graphics::POINT_MAX_ENUM> Graphics::pointStyles(Graphics::pointStyleEntries, sizeof(Graphics::pointStyleEntries));
+
+} // graphics
+} // love

+ 59 - 14
src/modules/graphics/Graphics.h

@@ -23,6 +23,7 @@
 
 // LOVE
 #include <common/Module.h>
+#include <common/StringMap.h>
 
 namespace love
 {
@@ -34,43 +35,87 @@ namespace graphics
 
 		enum DrawMode
 		{
-			DRAW_LINE, 
-			DRAW_FILL
+			DRAW_LINE = 1, 
+			DRAW_FILL,
+			DRAW_MAX_ENUM
 		};
 
 		enum AlignMode
 		{
-			ALIGN_LEFT, 
+			ALIGN_LEFT = 1, 
 			ALIGN_CENTER, 
-			ALIGN_RIGHT
+			ALIGN_RIGHT,
+			ALIGN_MAX_ENUM
 		};
 
 		enum BlendMode
 		{
-			BLEND_ALPHA, 
-			BLEND_ADDITIVE
+			BLEND_ALPHA = 1, 
+			BLEND_ADDITIVE,
+			BLEND_MAX_ENUM
 		};
 
 		enum ColorMode
 		{
-			COLOR_MODULATE, 
-			COLOR_REPLACE
+			COLOR_MODULATE = 1, 
+			COLOR_REPLACE,
+			COLOR_MAX_ENUM
 		};
 
 		enum LineStyle
 		{
-			LINE_ROUGH, 
-			LINE_SMOOTH
+			LINE_ROUGH = 1, 
+			LINE_SMOOTH,
+			LINE_MAX_ENUM
 		};
 
 		enum PointStyle
 		{
-			POINT_ROUGH,
-			POINT_SMOOTH
+			POINT_ROUGH = 1,
+			POINT_SMOOTH,
+			POINT_MAX_ENUM
 		};
 
-		virtual ~Graphics(){};
-		
+		virtual ~Graphics();
+
+		static bool getConstant(const char * in, DrawMode & out);
+		static bool getConstant(DrawMode in, const char *& out);
+
+		static bool getConstant(const char * in, AlignMode & out);
+		static bool getConstant(AlignMode in, const char *& out);
+
+		static bool getConstant(const char * in, BlendMode & out);
+		static bool getConstant(BlendMode in, const char *& out);
+
+		static bool getConstant(const char * in, ColorMode & out);
+		static bool getConstant(ColorMode in, const char *& out);
+
+		static bool getConstant(const char * in, LineStyle & out);
+		static bool getConstant(LineStyle in, const char *& out);
+
+		static bool getConstant(const char * in, PointStyle & out);
+		static bool getConstant(PointStyle in, const char *& out);
+
+	private:
+
+		static StringMap<DrawMode, DRAW_MAX_ENUM>::Entry drawModeEntries[];
+		static StringMap<DrawMode, DRAW_MAX_ENUM> drawModes;
+
+		static StringMap<AlignMode, ALIGN_MAX_ENUM>::Entry alignModeEntries[];
+		static StringMap<AlignMode, ALIGN_MAX_ENUM> alignModes;
+
+		static StringMap<BlendMode, BLEND_MAX_ENUM>::Entry blendModeEntries[];
+		static StringMap<BlendMode, BLEND_MAX_ENUM> blendModes;
+
+		static StringMap<ColorMode, COLOR_MAX_ENUM>::Entry colorModeEntries[];
+		static StringMap<ColorMode, COLOR_MAX_ENUM> colorModes;
+
+		static StringMap<LineStyle, LINE_MAX_ENUM>::Entry lineStyleEntries[];
+		static StringMap<LineStyle, LINE_MAX_ENUM> lineStyles;
+
+		static StringMap<PointStyle, POINT_MAX_ENUM>::Entry pointStyleEntries[];
+		static StringMap<PointStyle, POINT_MAX_ENUM> pointStyles;
+
 	}; // Graphics
 
 } // graphics

+ 24 - 152
src/modules/graphics/opengl/Graphics.cpp

@@ -38,7 +38,7 @@ namespace opengl
 		currentMode.width = 0;
 		currentMode.height = 0;
 
-		// Windows should be centered.
+		// Window should be centered.
 		SDL_putenv("SDL_VIDEO_CENTERED=center");
 
 		if(SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
@@ -511,7 +511,7 @@ namespace opengl
 		return currentFont;
 	}
 
-	void Graphics::setBlendMode( int mode )
+	void Graphics::setBlendMode( Graphics::BlendMode mode )
 	{
 		if(mode == BLEND_ADDITIVE)
 			glBlendFunc(GL_SRC_ALPHA, GL_ONE);
@@ -519,7 +519,7 @@ namespace opengl
 			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 	}
 
-	void Graphics::setColorMode ( int mode )
+	void Graphics::setColorMode ( Graphics::ColorMode mode )
 	{
 		if(mode == COLOR_MODULATE)
 			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
@@ -527,7 +527,7 @@ namespace opengl
 			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 	}
 	
-	int Graphics::getBlendMode()
+	Graphics::BlendMode Graphics::getBlendMode()
 	{
 		GLint dst, src;
 		glGetIntegerv(GL_BLEND_DST, &dst);
@@ -539,7 +539,7 @@ namespace opengl
 			return BLEND_ALPHA;
 	}
 
-	int Graphics::getColorMode()
+	Graphics::ColorMode Graphics::getColorMode()
 	{
 		GLint mode;
 		glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &mode);
@@ -555,7 +555,7 @@ namespace opengl
 		glLineWidth(width);
 	}
 
-	void Graphics::setLineStyle( int style )
+	void Graphics::setLineStyle(Graphics::LineStyle style )
 	{
 		if(style == LINE_ROUGH)
 			glDisable (GL_LINE_SMOOTH);
@@ -566,7 +566,7 @@ namespace opengl
 		}		
 	}
 
-	void Graphics::setLine( float width, int style )
+	void Graphics::setLine( float width, Graphics::LineStyle style )
 	{
 		glLineWidth(width);
 
@@ -600,7 +600,7 @@ namespace opengl
 		return w;
 	}
 
-	int Graphics::getLineStyle()
+	Graphics::LineStyle Graphics::getLineStyle()
 	{
 		if(glIsEnabled(GL_LINE_SMOOTH) == GL_TRUE)
 			return LINE_SMOOTH;
@@ -626,7 +626,7 @@ namespace opengl
 		glPointSize((GLfloat)size);
 	}
 
-	void Graphics::setPointStyle( int style )
+	void Graphics::setPointStyle( Graphics::PointStyle style )
 	{
 		if( style == POINT_SMOOTH )
 			glEnable(GL_POINT_SMOOTH);
@@ -634,7 +634,7 @@ namespace opengl
 			glDisable(GL_POINT_SMOOTH);
 	}
 
-	void Graphics::setPoint( float size, int style )
+	void Graphics::setPoint( float size, Graphics::PointStyle style )
 	{
 		if( style == POINT_SMOOTH )
 			glEnable(GL_POINT_SMOOTH);
@@ -651,7 +651,7 @@ namespace opengl
 		return (float)size;
 	}
 
-	int Graphics::getPointStyle()
+	Graphics::PointStyle Graphics::getPointStyle()
 	{
 		if(glIsEnabled(GL_POINT_SMOOTH) == GL_TRUE)
 			return POINT_SMOOTH;
@@ -724,7 +724,7 @@ namespace opengl
 		}
 	}
 
-	void Graphics::printf( const char * str, float x, float y, float wrap, int align)
+	void Graphics::printf( const char * str, float x, float y, float wrap, AlignMode align)
 	{
 		if(currentFont != 0)
 		{
@@ -846,13 +846,13 @@ namespace opengl
 		glEnable(GL_TEXTURE_2D);
 	}
 
-	void Graphics::triangle( int type, float x1, float y1, float x2, float y2, float x3, float y3 )
+	void Graphics::triangle(DrawMode mode, float x1, float y1, float x2, float y2, float x3, float y3 )
 	{
 		glDisable(GL_CULL_FACE);
 		glDisable(GL_TEXTURE_2D);
 		glPushMatrix();
 
-		switch(type)
+		switch(mode)
 		{
 		case DRAW_LINE:
 			glBegin(GL_LINE_LOOP);
@@ -877,12 +877,12 @@ namespace opengl
 		glEnable(GL_CULL_FACE);
 	}
 
-	void Graphics::rectangle( int type, float x, float y, float w, float h )
+	void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h )
 	{
 		glDisable(GL_TEXTURE_2D);
 		glPushMatrix();
 
-		switch(type)
+		switch(mode)
 		{
 		case DRAW_LINE:
 			glBegin(GL_LINE_LOOP);
@@ -908,13 +908,13 @@ namespace opengl
 		glEnable(GL_TEXTURE_2D);
 	}
 
-	void Graphics::quad( int type, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4 )
+	void Graphics::quad(DrawMode mode, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4 )
 	{
 		glDisable(GL_CULL_FACE);
 		glDisable(GL_TEXTURE_2D);
 		glPushMatrix();
 
-		switch(type)
+		switch(mode)
 		{
 		case DRAW_LINE:
 			glBegin(GL_LINE_LOOP);
@@ -941,7 +941,7 @@ namespace opengl
 		glEnable(GL_CULL_FACE);
 	}
 
-	void Graphics::circle( int type, float x, float y, float radius, int points )
+	void Graphics::circle(DrawMode mode, float x, float y, float radius, int points )
 	{
 		float two_pi = 3.14159265f * 2;
 		if(points <= 0) points = 1;
@@ -952,7 +952,7 @@ namespace opengl
 
 		glTranslatef(x, y, 0.0f);
 
-		switch(type)
+		switch(mode)
 		{
 		case DRAW_LINE:
 			glBegin(GL_LINE_LOOP);
@@ -987,12 +987,11 @@ namespace opengl
 		if( n < 2 )
 			return luaL_error(L, "Error: function needs at least two parameters.");
 
-		// The first one MUST be a number.
-		if( !lua_isnumber(L, 1) )
-			return luaL_error(L, "Error: first parameter must be a number.");
+		DrawMode mode;
 
-		// Get rendering mode. (line/fill)
-		int mode = (int)lua_tonumber(L, 1);
+		const char * str = luaL_checkstring(L, 1);
+		if(!getConstant(str, mode))
+			return luaL_error(L, "Invalid draw mode: %s", str);
 
 		// Get the type of the second argument.
 		int luatype = lua_type(L, 2);
@@ -1046,133 +1045,6 @@ namespace opengl
 		return 0;
 	}
 
-	int Graphics::polygong( lua_State * L )
-	{
-		// Get number of params.
-		int n = lua_gettop(L);
-
-		// Need at least two params.
-		if( n < 2 )
-			return luaL_error(L, "Error: function needs at least two parameters.");
-
-		// The first one MUST be a number.
-		if( !lua_isnumber(L, 1) )
-			return luaL_error(L, "Error: first parameter must be a number.");
-
-		int vertc = 0, colorc = 0;
-
-		if( n == 3 )
-		{
-			if((!lua_istable(L, 2) || !lua_istable(L, 3))) 
-				return luaL_error(L, "Error: two tables expected.");
-			vertc = (int)lua_objlen(L, 2);
-			colorc = (int)lua_objlen(L, 3);
-			if( (vertc <= 0 || colorc <= 0)) 
-				return luaL_error(L, "Error: empty table.");
-		}
-
-		// Get rendering mode. (line/fill)
-		int mode = (int)lua_tonumber(L, 1);
-		GLenum glmode = (mode==DRAW_LINE) ? GL_LINE_LOOP : GL_POLYGON;
-
-		// Get the type of the second argument.
-		int luatype = lua_type(L, 2);
-
-		if(!(luatype == LUA_TTABLE || luatype == LUA_TNUMBER))
-			return luaL_error(L, "Error: expected number or table values.");
-
-		glPushAttrib(GL_CURRENT_BIT);
-		glDisable(GL_CULL_FACE);
-		glDisable(GL_TEXTURE_2D);
-
-		switch(luatype)
-		{
-		case LUA_TTABLE:
-
-			if( n == 2 )
-			{
-				glBegin(glmode);
-				lua_pushnil(L);
-				while(true)
-				{
-					if(lua_next(L, 2) == 0) break;
-					GLfloat x = (GLfloat)lua_tonumber(L, -1);
-					lua_pop(L, 1);
-					if(lua_next(L, 2) == 0) break;
-					GLfloat y = (GLfloat)lua_tonumber(L, -1);
-					lua_pop(L, 1);
-					if(lua_next(L, 2) == 0) break;
-					GLubyte r = (GLubyte)lua_tonumber(L, -1);
-					lua_pop(L, 1);
-					if(lua_next(L, 2) == 0) break;
-					GLubyte g = (GLubyte)lua_tonumber(L, -1);
-					lua_pop(L, 1);
-					if(lua_next(L, 2) == 0) break;
-					GLubyte b = (GLubyte)lua_tonumber(L, -1);
-					lua_pop(L, 1);
-					if(lua_next(L, 2) == 0) break;
-					GLubyte a = (GLubyte)lua_tonumber(L, -1);
-					lua_pop(L, 1);
-					glColor4ub(r, g, b, a);
-					glVertex2f(x, y);
-				}
-				glEnd();
-			}
-			else if(n == 3)
-			{
-				// Allocate memory.
-				GLfloat * verts = new GLfloat[vertc];
-				GLubyte * colors = new GLubyte[colorc];
-				int verti = 0, colori = 0;
-
-				// Get verts.
-				lua_pushnil(L);
-				while(lua_next(L, 2))
-				{
-					verts[verti++] = (GLfloat)lua_tonumber(L, -1);
-					lua_pop(L, 1);
-				}
-
-				// Get colors.
-				lua_pushnil(L);
-				while(lua_next(L, 3))
-				{
-					colors[colori++] = (GLubyte)lua_tonumber(L, -1);
-					lua_pop(L, 1);
-				}
-
-				glEnable(GL_VERTEX_ARRAY);
-				glEnable(GL_COLOR_ARRAY);
-				glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
-				glVertexPointer(2, GL_FLOAT, 0, verts);
-				glDrawArrays(glmode, 0, (GLint)(vertc/2));
-				glDisable(GL_VERTEX_ARRAY);
-				glDisable(GL_COLOR_ARRAY);
-				delete [] verts;
-				delete [] colors;
-			}	
-
-			break;
-		case LUA_TNUMBER:
-			// Assume params to be packed like this: x, y, r, g, b, a, x, y, r, ...
-			glBegin(glmode);
-			for(int i = 2; i < (n-1); i+=6)
-			{
-				glColor4ub((GLubyte)lua_tonumber(L, i+2), (GLubyte)lua_tonumber(L, i+3), (GLubyte)lua_tonumber(L, i+4), (GLubyte)lua_tonumber(L, i+5));
-				glVertex2f((GLfloat)lua_tonumber(L, i), (GLfloat)lua_tonumber(L, i+1));
-			}				
-			glEnd();
-			break;
-		}
-
-		glEnable(GL_CULL_FACE);
-		glEnable(GL_TEXTURE_2D);
-		glPopAttrib();
-
-
-		return 0;
-	}
-
 	love::image::ImageData * Graphics::newScreenshot(love::image::Image * image)
 	{
 		int w = getWidth();

+ 30 - 30
src/modules/graphics/opengl/Graphics.h

@@ -284,7 +284,7 @@ namespace opengl
 		* Sets the current font.
 		* @parm font A Font object.
 		**/
-		void setFont( Font * font );
+		void setFont(Font * font);
 
 		/**
 		* Sets a default font. The font is
@@ -293,7 +293,7 @@ namespace opengl
 		* @param data Data 
 		* @param size The size of the font.
 		**/
-		void setFont( Data * data, int size = 12);
+		void setFont(Data * data, int size = 12);
 
 		/**
 		* Gets the current Font, or nil if none.
@@ -303,40 +303,40 @@ namespace opengl
 		/**
 		* Sets the current blend mode.
 		**/
-		void setBlendMode( int mode );
+		void setBlendMode(BlendMode mode);
 
 		/**
 		* Sets the current color mode.
 		**/
-		void setColorMode ( int mode );
+		void setColorMode (ColorMode mode);
 
 		/**
 		* Gets the current blend mode.
 		**/
-		int getBlendMode();
+		BlendMode getBlendMode();
 
 		/**
 		* Gets the current color mode.
 		**/
-		int getColorMode();
+		ColorMode getColorMode();
 
 		/**
 		* Sets the line width.
 		* @param width The new width of the line.
 		**/
-		void setLineWidth( float width );
+		void setLineWidth(float width);
 
 		/**
 		* Sets the line style.
 		* @param style LINE_ROUGH or LINE_SMOOTH.
 		**/
-		void setLineStyle( int style );
+		void setLineStyle(LineStyle style);
 
 		/**
 		* Sets the type of line used to draw primitives.
 		* A shorthand for setLineWidth and setLineStyle.
 		**/
-		void setLine( float width, int style = 0 );
+		void setLine(float width, LineStyle style);
 
 		/**
 		* Disables line stippling.
@@ -356,7 +356,7 @@ namespace opengl
 		/**
 		* Gets the line style.
 		**/
-		int getLineStyle();
+		LineStyle getLineStyle();
 
 		/**
 		* Gets the line stipple pattern and repeat factor.
@@ -368,18 +368,18 @@ namespace opengl
 		/**
 		* Sets the size of points.
 		**/
-		void setPointSize( float size );
+		void setPointSize(float size);
 
 		/**
 		* Sets the style of points.
 		* @param style POINT_SMOOTH or POINT_ROUGH.
 		**/
-		void setPointStyle( int style );
+		void setPointStyle(PointStyle style);
 
 		/**
 		* Shorthand for setPointSize and setPointStyle.
 		**/
-		void setPoint( float size, int style );
+		void setPoint(float size, PointStyle style);
 
 		/**
 		* Gets the point size.
@@ -389,7 +389,7 @@ namespace opengl
 		/**
 		* Gets the point style.
 		**/
-		int getPointStyle();
+		PointStyle getPointStyle();
 
 		/**
 		* Gets the maximum point size supported. 
@@ -404,7 +404,7 @@ namespace opengl
 		* @param x The x-coordiante.
 		* @param y The y-coordiante.
 		**/
-		void print( const char * str, float x, float y );
+		void print(const char * str, float x, float y);
 
 		/**
 		* Draws text at the specified coordinates, with rotation.
@@ -412,7 +412,7 @@ namespace opengl
 		* @param y The y-coordinate.
 		* @param angle The amount of rotation.
 		**/
-		void print( const char * str, float x, float y , float angle );
+		void print(const char * str, float x, float y , float angle);
 
 		/**
 		* Draws text at the specified coordinates, with rotation and 
@@ -422,7 +422,7 @@ namespace opengl
 		* @param angle The amount of rotation.
 		* @param s The scale factor. (1 = normal).
 		**/
-		void print( const char * str, float x, float y , float angle, float s );
+		void print(const char * str, float x, float y , float angle, float s);
 
 		/**
 		* Draws text at the specified coordinates, with rotation and 
@@ -433,7 +433,7 @@ namespace opengl
 		* @param sx The scale factor along the x-axis. (1 = normal).
 		* @param sy The scale factor along the y-axis. (1 = normal).
 		**/
-		void print( const char * str, float x, float y , float angle, float sx, float sy);
+		void print(const char * str, float x, float y , float angle, float sx, float sy);
 
 		/**
 		* Draw formatted text on screen at the specified coordinates.
@@ -444,14 +444,14 @@ namespace opengl
 		* @param wrap The maximum width of the text area.
 		* @param align Where to align the text.
 		**/
-		void printf( const char * str, float x, float y, float wrap, int align = 0 );
+		void printf(const char * str, float x, float y, float wrap, AlignMode align);
 
 		/**
 		* Draws a point at (x,y).
 		* @param x Point along x-axis.
 		* @param y Point along y-axis.
 		**/
-		void point( float x, float y );
+		void point(float x, float y);
 
 		/**
 		* Draws a line from (x1,y1) to (x2,y2).
@@ -460,11 +460,11 @@ namespace opengl
 		* @param x2 Second x-coordinate.
 		* @param y2 Second y-coordinate.
 		**/
-		void line( float x1, float y1, float x2, float y2 );
+		void line(float x1, float y1, float x2, float y2);
 
 		/**
 		* Draws a triangle using the three coordinates passed.
-		* @param type The type of drawing (line/filled).
+		* @param mode The mode of drawing (line/filled).
 		* @param x1 First x-coordinate.
 		* @param y1 First y-coordinate.
 		* @param x2 Second x-coordinate.
@@ -472,7 +472,7 @@ namespace opengl
 		* @param x3 Third x-coordinate.
 		* @param y3 Third y-coordinate.
 		**/
-		void triangle( int type, float x1, float y1, float x2, float y2, float x3, float y3 );
+		void triangle(DrawMode mode, float x1, float y1, float x2, float y2, float x3, float y3);
 
 		/**
 		* Draws a rectangle.
@@ -481,11 +481,11 @@ namespace opengl
 		* @param w The width of the rectangle.
 		* @param h The height of the rectangle.
 		**/
-		void rectangle( int type, float x, float y, float w, float h );
+		void rectangle(DrawMode mode, float x, float y, float w, float h);
 
 		/**
 		* Draws a quadrilateral using the four coordinates passed.
-		* @param type The type of drawing (line/filled).
+		* @param mode The mode of drawing (line/filled).
 		* @param x1 First x-coordinate.
 		* @param y1 First y-coordinate.
 		* @param x2 Second x-coordinate.
@@ -495,25 +495,25 @@ namespace opengl
 		* @param x4 Fourth x-coordinate.
 		* @param y4 Fourth y-coordinate.
 		**/
-		void quad( int type, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4 );
+		void quad(DrawMode mode, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4);
 
 		/**
 		* Draws a circle using the specified arguments.
-		* @param type The type of drawing (line/filled).
+		* @param mode The mode of drawing (line/filled).
 		* @param x X-coordinate.
 		* @param y Y-coordinate.
 		* @param radius Radius of the circle.
 		* @param points Amount of points to use to draw the circle.
 		**/
-		void circle( int type, float x, float y, float radius, int points = 10 );
+		void circle(DrawMode mode, float x, float y, float radius, int points = 10);
 
 		/**
 		* Draws a polygon with an arbitrary number of vertices.
 		* @param type The type of drawing (line/filled).
 		* @param ... Vertex components (x1, y1, x2, y2, etc).
 		**/
-		int polygon( lua_State * L );
-		int polygong( lua_State * L );
+		int polygon(lua_State * L);
+		int polygong(lua_State * L);
 
 		/**
 		* Creates a screenshot of the view and saves it to the default folder.

+ 86 - 70
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -360,27 +360,45 @@ namespace opengl
 
 	int w_setBlendMode(lua_State * L)
 	{
-		int mode = luaL_checkint(L, 1);
+		Graphics::BlendMode mode;
+		const char * str = luaL_checkstring(L, 1);
+		if(!Graphics::getConstant(str, mode))
+			return luaL_error(L, "Invalid blend mode: %s", str);
+
 		instance->setBlendMode(mode);
 		return 0;
 	}
 
 	int w_setColorMode(lua_State * L)
 	{
-		int mode = luaL_checkint(L, 1);
+		Graphics::ColorMode mode;
+		const char * str = luaL_checkstring(L, 1);
+		if(!Graphics::getConstant(str, mode))
+			return luaL_error(L, "Invalid color mode: %s", str);
+
 		instance->setColorMode(mode);
 		return 0;
 	}
 
 	int w_getBlendMode(lua_State * L)
 	{
-		lua_pushinteger(L, instance->getBlendMode());
+		Graphics::BlendMode mode = instance->getBlendMode();
+		const char * str = luaL_checkstring(L, 1);
+		if(!Graphics::getConstant(str, mode))
+			return luaL_error(L, "Invalid blend mode: %s", str);
+
+		lua_pushstring(L, str);
 		return 1;
 	}
 
 	int w_getColorMode(lua_State * L)
 	{
-		lua_pushinteger(L, instance->getColorMode());
+		Graphics::ColorMode mode = instance->getColorMode();
+		const char * str = luaL_checkstring(L, 1);
+		if(!Graphics::getConstant(str, mode))
+			return luaL_error(L, "Invalid blend mode: %s", str);
+
+		lua_pushstring(L, str);
 		return 1;
 	}
 
@@ -393,7 +411,11 @@ namespace opengl
 
 	int w_setLineStyle(lua_State * L)
 	{
-		int style = luaL_checkint(L, 1);
+		Graphics::LineStyle style;
+		const char * str = luaL_checkstring(L, 1);
+		if(!Graphics::getConstant(str, style))
+			return luaL_error(L, "Invalid line style: %s", str);
+
 		instance->setLineStyle(style);
 		return 0;
 	}
@@ -401,7 +423,16 @@ namespace opengl
 	int w_setLine(lua_State * L)
 	{
 		float width = (float)luaL_checknumber(L, 1);
-		int style = luaL_optint(L, 2, Graphics::LINE_SMOOTH);
+
+		Graphics::LineStyle style = Graphics::LINE_SMOOTH;
+
+		if(lua_gettop(L) >= 2)
+		{
+			const char * str = luaL_checkstring(L, 1);
+			if(!Graphics::getConstant(str, style))
+				return luaL_error(L, "Invalid line style: %s", str);
+		}
+
 		instance->setLine(width, style);
 		return 0;
 	}
@@ -446,7 +477,15 @@ namespace opengl
 
 	int w_setPointStyle(lua_State * L)
 	{
-		int style = luaL_checkint(L, 1);
+		Graphics::PointStyle style = Graphics::POINT_SMOOTH;
+
+		if(lua_gettop(L) >= 2)
+		{
+			const char * str = luaL_checkstring(L, 1);
+			if(!Graphics::getConstant(str, style))
+				return luaL_error(L, "Invalid point style: %s", str);
+		}
+
 		instance->setPointStyle(style);
 		return 0;
 	}
@@ -454,7 +493,12 @@ namespace opengl
 	int w_setPoint(lua_State * L)
 	{
 		float size = (float)luaL_checknumber(L, 1);
-		int style = luaL_optint(L, 2, Graphics::POINT_SMOOTH);
+
+		Graphics::PointStyle style;
+		const char * str = luaL_checkstring(L, 1);
+		if(!Graphics::getConstant(str, style))
+			return luaL_error(L, "Invalid point style: %s", str);
+
 		instance->setPoint(size, style);
 		return 0;
 	}
@@ -587,7 +631,16 @@ namespace opengl
 		float x = (float)luaL_checknumber(L, 2);
 		float y = (float)luaL_checknumber(L, 3);
 		float wrap = (float)luaL_checknumber(L, 4);
-		int align = luaL_optint(L, 5, 0);
+
+		Graphics::AlignMode align = Graphics::ALIGN_LEFT;
+
+		if(lua_gettop(L) >= 5)
+		{
+			const char * str = luaL_checkstring(L, 5);
+			if(!Graphics::getConstant(str, align))
+				return luaL_error(L, "Incorrect alignment: %s", str);
+		}
+
 		instance->printf(str, x, y, wrap, align);
 		return 0;
 	}
@@ -612,31 +665,43 @@ namespace opengl
 
 	int w_triangle(lua_State * L)
 	{
-		int type = luaL_checkint(L, 1);
+		Graphics::DrawMode mode;
+		const char * str = luaL_checkstring(L, 1);
+		if(!Graphics::getConstant(str, mode))
+			return luaL_error(L, "Incorrect draw mode %s", str);
+
 		float x1 = (float)luaL_checknumber(L, 2);
 		float y1 = (float)luaL_checknumber(L, 3);
 		float x2 = (float)luaL_checknumber(L, 4);
 		float y2 = (float)luaL_checknumber(L, 5);
 		float x3 = (float)luaL_checknumber(L, 6);
 		float y3 = (float)luaL_checknumber(L, 7);
-		instance->triangle(type, x1, y1, x2, y2, x3, y3);
+		instance->triangle(mode, x1, y1, x2, y2, x3, y3);
 		return 0;
 	}
 
 	int w_rectangle(lua_State * L)
 	{
-		int type = luaL_checkint(L, 1);
+		Graphics::DrawMode mode;
+		const char * str = luaL_checkstring(L, 1);
+		if(!Graphics::getConstant(str, mode))
+			return luaL_error(L, "Incorrect draw mode %s", str);
+
 		float x = (float)luaL_checknumber(L, 2);
 		float y = (float)luaL_checknumber(L, 3);
 		float w = (float)luaL_checknumber(L, 4);
 		float h = (float)luaL_checknumber(L, 5);
-		instance->rectangle(type, x, y, w, h);
+		instance->rectangle(mode, x, y, w, h);
 		return 0;
 	}
 
 	int w_quad(lua_State * L)
 	{
-		int type = luaL_checkint(L, 1);
+		Graphics::DrawMode mode;
+		const char * str = luaL_checkstring(L, 1);
+		if(!Graphics::getConstant(str, mode))
+			return luaL_error(L, "Incorrect draw mode %s", str);
+
 		float x1 = (float)luaL_checknumber(L, 2);
 		float y1 = (float)luaL_checknumber(L, 3);
 		float x2 = (float)luaL_checknumber(L, 4);
@@ -645,18 +710,22 @@ namespace opengl
 		float y3 = (float)luaL_checknumber(L, 7);
 		float x4 = (float)luaL_checknumber(L, 6);
 		float y4 = (float)luaL_checknumber(L, 7);
-		instance->quad(type, x1, y1, x2, y2, x3, y3, x4, y4);
+		instance->quad(mode, x1, y1, x2, y2, x3, y3, x4, y4);
 		return 0;
 	}
 
 	int w_circle(lua_State * L)
 	{
-		int type = luaL_checkint(L, 1);
+		Graphics::DrawMode mode;
+		const char * str = luaL_checkstring(L, 1);
+		if(!Graphics::getConstant(str, mode))
+			return luaL_error(L, "Incorrect draw mode %s", str);
+
 		float x = (float)luaL_checknumber(L, 2);
 		float y = (float)luaL_checknumber(L, 3);
 		float radius = (float)luaL_checknumber(L, 4);
 		int points = luaL_optint(L, 5, 10);
-		instance->circle(type, x, y, radius, points);
+		instance->circle(mode, x, y, radius, points);
 		return 0;
 	}
 
@@ -795,58 +864,6 @@ namespace opengl
 		0		
 	};
 
-	// List of constants.
-	static const Constant constants[] = {
-
-		{ "align_left", Graphics::ALIGN_LEFT },
-		{ "align_right", Graphics::ALIGN_RIGHT },
-		{ "align_center", Graphics::ALIGN_CENTER },
-
-		{ "blend_alpha", Graphics::BLEND_ALPHA },
-		{ "blend_additive", Graphics::BLEND_ADDITIVE },
-		{ "color_replace", Graphics::COLOR_REPLACE },
-		{ "color_modulate", Graphics::COLOR_MODULATE },
-
-		{ "draw_line", Graphics::DRAW_LINE },
-		{ "draw_fill", Graphics::DRAW_FILL },
-
-		{ "line_smooth", Graphics::LINE_SMOOTH },
-		{ "line_rough", Graphics::LINE_ROUGH },
-
-		{ "point_smooth", Graphics::POINT_SMOOTH },
-		{ "point_rough", Graphics::POINT_ROUGH },
-
-		{ "filter_linear", Image::FILTER_LINEAR },
-		{ "filter_nearest", Image::FILTER_NEAREST },
-
-		{ "wrap_clamp", Image::WRAP_CLAMP },
-		{ "wrap_repeat", Image::WRAP_REPEAT },
-
-		/**
-
-		// Vertex buffer geometry types.
-
-		{ "type_points", TYPE_POINTS },
-		{ "type_lines", TYPE_LINES },
-		{ "type_line_strip", TYPE_LINE_STRIP },
-		{ "type_triangles", TYPE_TRIANGLES },
-		{ "type_triangle_strip", TYPE_TRIANGLE_STRIP },
-		{ "type_triangle_fan", TYPE_TRIANGLE_FAN },
-		{ "type_num", TYPE_NUM },
-		
-		// Vertex buffer usage hints.
-
-		{ "usage_array", USAGE_ARRAY },
-		{ "usage_dynamic", USAGE_DYNAMIC },
-		{ "usage_static", USAGE_STATIC },
-		{ "usage_stream", USAGE_STREAM },
-		{ "usage_num", USAGE_NUM },
-		**/
-
-
-		{ 0, 0 }
-	};
-
 	int luaopen_love_graphics(lua_State * L)
 	{
 		if(instance == 0)
@@ -867,7 +884,6 @@ namespace opengl
 		w.flags = MODULE_T;
 		w.functions = functions;
 		w.types = types;
-		w.constants = constants;
 
 		luax_register_module(L, w);
 

+ 28 - 7
src/modules/image/EncodedImageData.cpp

@@ -24,22 +24,43 @@ namespace love
 {
 namespace image
 {
-	EncodedImageData::EncodedImageData(void * d, Image::ImageFormat f, int s) {
-		data = d;
-		format = f;
-		size = s;
+	EncodedImageData::EncodedImageData(void * d, Format f, int s)
+		: data(d), format(f), size(s)
+	{
 	}
 	
-	void * EncodedImageData::getData() const {
+	void * EncodedImageData::getData() const 
+	{
 		return data;
 	}
 	
-	Image::ImageFormat EncodedImageData::getFormat() {
+	EncodedImageData::Format EncodedImageData::getFormat() const
+	{
 		return format;
 	}
 	
-	int EncodedImageData::getSize() const {
+	int EncodedImageData::getSize() const 
+	{
 		return size;
 	}
+
+	bool EncodedImageData::getConstant(const char * in, EncodedImageData::Format & out)
+	{
+		return formats.find(in, out);
+	}
+
+	bool EncodedImageData::getConstant(EncodedImageData::Format in, const char *& out)
+	{
+		return formats.find(in, out);
+	}
+
+	StringMap<EncodedImageData::Format, EncodedImageData::FORMAT_MAX_ENUM>::Entry EncodedImageData::formatEntries[] = 
+	{
+		{"tga", EncodedImageData::FORMAT_TGA},
+		{"bmp", EncodedImageData::FORMAT_BMP},
+	};
+
+	StringMap<EncodedImageData::Format, EncodedImageData::FORMAT_MAX_ENUM> EncodedImageData::formats(EncodedImageData::formatEntries, sizeof(EncodedImageData::formatEntries));
+
 } // image
 } // love

+ 58 - 45
src/modules/image/EncodedImageData.h

@@ -23,60 +23,73 @@
 
 // LOVE
 #include <common/Data.h>
+#include <common/StringMap.h>
 
 #include "Image.h"
 
 namespace love
 {	
-	namespace image
+namespace image
+{
+	/**
+	 * Represents encoded pixel data. 
+	 **/
+	class EncodedImageData : public Data
 	{
+	public:
+		
+		enum Format 
+		{
+			FORMAT_TGA = 1,
+			FORMAT_BMP,
+			FORMAT_MAX_ENUM
+		};
+
+		/**
+		* Constructor.
+		**/
+		EncodedImageData(void * data, Format format, int size);
+		
+		/**
+		* Destructor.
+		**/
+		virtual ~EncodedImageData(){};
+		
+		// Implements Data.
+		void * getData() const;
+		int getSize() const;
+		
+		/**
+		* Get the format the data is encoded in.
+		**/
+		Format getFormat() const;
+
+		static bool getConstant(const char * in, Format & out);
+		static bool getConstant(Format in, const char *& out);
+		
+	private:
+		
+		/**
+		* Actual data.
+		**/
+		void * data;
+		
+		/**
+		* Size of the data.
+		**/
+		int size;
+		
 		/**
-		 * Represents encoded pixel data. 
+		 * Image format.
 		 **/
-		class EncodedImageData : public Data
-			{
-			public:
-				
-				/**
-				* Constructor.
-				**/
-				EncodedImageData(void * data, Image::ImageFormat format, int size);
-				
-				/**
-				* Destructor.
-				**/
-				virtual ~EncodedImageData(){};
-				
-				// Implements Data.
-				void * getData() const;
-				int getSize() const;
-				
-				/**
-				* Get the format the data is encoded in.
-				**/
-				
-				Image::ImageFormat getFormat();
-				
-			private:
-				
-				/**
-				* Actual data.
-				**/
-				void * data;
-				
-				/**
-				* Size of the data.
-				**/
-				int size;
-				
-				/**
-				 * Image format.
-				 **/
-				Image::ImageFormat format;
-				
-			}; // EncodedImageData
+		Format format;
+
+		static StringMap<Format, FORMAT_MAX_ENUM>::Entry formatEntries[];
+		static StringMap<Format, FORMAT_MAX_ENUM> formats;
 		
-	} // image
+	}; // EncodedImageData
+	
+} // image
 } // love
 
 #endif // LOVE_IMAGE_ENCODED_IMAGE_DATA_H

+ 0 - 5
src/modules/image/Image.h

@@ -76,11 +76,6 @@ namespace image
 		 * @return The new ImageData.
 		 **/
 		virtual ImageData * newImageData(int width, int height, void *data) = 0;
-		
-		enum ImageFormat {
-			FORMAT_TGA,
-			FORMAT_BMP
-		};
 
 	}; // Image
 

+ 4 - 4
src/modules/image/devil/ImageData.cpp

@@ -165,13 +165,13 @@ namespace devil
 		return pixels[y*width+x];
 	}
 	
-	love::image::EncodedImageData * ImageData::encodeImageData(love::image::ImageData * d, love::image::Image::ImageFormat f) {
+	love::image::EncodedImageData * ImageData::encodeImageData(love::image::ImageData * d, EncodedImageData::Format f) {
 		ILubyte * data;
 		ILuint w = d->getWidth();
 		int h = d->getHeight(); // has to be a signed int so we can make it negative for BMPs
 		int headerLen, bpp, row, size, padding, filesize;
 		switch (f) {
-			case Image::FORMAT_BMP:
+			case EncodedImageData::FORMAT_BMP:
 				headerLen = 54;
 				bpp = 3;
 				row = w * bpp;
@@ -231,7 +231,7 @@ namespace devil
 				}
 				data -= filesize;
 				break;
-			case Image::FORMAT_TGA:
+			case EncodedImageData::FORMAT_TGA:
 			default: // TGA is the default format
 				headerLen = 18;
 				bpp = 3;
@@ -263,7 +263,7 @@ namespace devil
 				ILubyte * temp = new ILubyte[row];
 				ILubyte * src = data - row;
 				ILubyte * dst = data + size;
-				for (unsigned i = 0; i < (h >> 1); i++) {
+				for (int i = 0; i < (h >> 1); i++) {
 					memcpy(temp,src+=row,row);
 					memcpy(src,dst-=row,row);
 					memcpy(dst,temp,row);

+ 1 - 1
src/modules/image/devil/ImageData.h

@@ -84,7 +84,7 @@ namespace devil
 		 * @param f The format to convert to.
 		 * @return A pointer to the encoded image data.
 		 **/
-		static love::image::EncodedImageData * encodeImageData(love::image::ImageData * d, love::image::Image::ImageFormat f);
+		static love::image::EncodedImageData * encodeImageData(love::image::ImageData * d, EncodedImageData::Format f);
 
 	}; // ImageData
 

+ 4 - 9
src/modules/image/wrap_Image.cpp

@@ -21,6 +21,7 @@
 #include "wrap_Image.h"
 
 #include <common/Data.h>
+#include <common/StringMap.h>
 
 #include "devil/Image.h"
 #include "devil/ImageData.h"
@@ -30,7 +31,7 @@ namespace love
 namespace image
 {
 	static Image * instance = 0;
-
+	
 	int w_newImageData(lua_State * L)
 	{
 
@@ -72,7 +73,8 @@ namespace image
 	
 	int w_newEncodedImageData(lua_State * L) {
 		ImageData * t = luax_checkimagedata(L, 1);
-		Image::ImageFormat format = (Image::ImageFormat)luaL_optint(L, 2, Image::FORMAT_TGA);
+		EncodedImageData::Format format;
+		EncodedImageData::getConstant(luaL_checkstring(L, 2), format);
 		EncodedImageData * e = love::image::devil::ImageData::encodeImageData(t, format);
 		luax_newtype(L, "Data", DATA_T, (void*)e); // since we don't need any of EncodedImageData's features
 		return 1;
@@ -89,12 +91,6 @@ namespace image
 		luaopen_imagedata,
 		0
 	};
-	
-	static const Constant constants[] = {
-		{ "format_tga", Image::FORMAT_TGA },
-		{ "format_bmp", Image::FORMAT_BMP },
-		{ 0, 0 }
-	};
 
 	int luaopen_love_image(lua_State * L)
 	{
@@ -116,7 +112,6 @@ namespace image
 		w.flags = MODULE_IMAGE_T;
 		w.functions = functions;
 		w.types = types;
-		w.constants = constants;
 
 		return luax_register_module(L, w);
 	}

+ 41 - 68
src/modules/signal/posix/Signal.cpp → src/modules/joystick/Joystick.cpp

@@ -1,85 +1,58 @@
-/**
-* Copyright (c) 2006-2009 LOVE Development Team
-* 
-* This software is provided 'as-is', without any express or implied
-* warranty.  In no event will the authors be held liable for any damages
-* arising from the use of this software.
-* 
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-* 
-* 1. The origin of this software must not be misrepresented; you must not
-*    claim that you wrote the original software. If you use this software
-*    in a product, an acknowledgment in the product documentation would be
-*    appreciated but is not required.
-* 2. Altered source versions must be plainly marked as such, and must not be
-*    misrepresented as being the original software.
-* 3. This notice may not be removed or altered from any source distribution.
+/**
+* Copyright (c) 2006-2009 LOVE Development Team
+* 
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* 
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
 **/
 
-#include "Signal.h"
+#include "Joystick.h"
 
 namespace love
 {
-namespace signal
-{
-namespace posix
+namespace joystick
 {
 
-	Signal::Signal()
-		: signals(0)
-	{
-		cb = 0;
-	}
-	
-	Signal::~Signal()
+	Joystick::~Joystick()
 	{
-		//::signal(signals, SIG_DFL);
 	}
-	
-	bool Signal::hook(int sgn)
-	{
-		signals |= sgn;
-		::signal(sgn, (void (*)(int)) &handler);
-		return true;
-	}
-	
-	void Signal::setCallback(lua_State *L)
-	{
-		luax_assert_argc(L, 1, 1);
-		luax_assert_function(L, -1);
 
-		if(cb != 0)
-		{
-			delete cb;
-			cb = 0;
-		}
-
-		cb = new Reference(L);
-	}
-	
-	bool Signal::raise(int sgn)
+	bool Joystick::getConstant(const char * in, Joystick::Hat & out)
 	{
-		// MSVC warns about int -> bool conversion.
-		return ::raise(sgn) ? true : false;
+		return hats.find(in, out);
 	}
-	
-	void handler(int signal)
+
+	bool Joystick::getConstant(Joystick::Hat in, const char *& out)
 	{
-		if (cb == 0)
-			return;
-		lua_State *L = cb->getL();
-		cb->push();
-		lua_pushnumber(L, signal);
-		lua_call(L, 1, 0);
+		return hats.find(in, out);
 	}
-	
-	const char * Signal::getName() const
+
+	StringMap<Joystick::Hat, Joystick::HAT_MAX_ENUM>::Entry Joystick::hatEntries[] = 
 	{
-		return "love.signal.posix";
-	}
+		{"c", Joystick::HAT_CENTERED},
+		{"u", Joystick::HAT_UP},
+		{"r", Joystick::HAT_RIGHT},
+		{"d", Joystick::HAT_DOWN},
+		{"l", Joystick::HAT_LEFT},
+		{"ru", Joystick::HAT_RIGHTUP},
+		{"rd", Joystick::HAT_RIGHTDOWN},
+		{"lu", Joystick::HAT_LEFTUP},
+		{"ld", Joystick::HAT_LEFTDOWN},
+	};
+
+	StringMap<Joystick::Hat, Joystick::HAT_MAX_ENUM> Joystick::hats(Joystick::hatEntries, sizeof(Joystick::hatEntries));
 
-} // posix
-} // signal
+} // joystick
 } // love

+ 21 - 16
src/modules/joystick/Joystick.h

@@ -23,6 +23,7 @@
 
 // LOVE
 #include <common/Module.h>
+#include <common/StringMap.h>
 
 namespace love
 {
@@ -32,26 +33,30 @@ namespace joystick
 	{
 	public:
 
-		enum JoystickAxis
+		enum Hat
 		{
-			JOYSTICK_AXIS_HORIZONTAL = 0,
-			JOYSTICK_AXIS_VERITCAL = 1,
+			HAT_INVALID,
+			HAT_CENTERED,
+			HAT_UP,
+			HAT_RIGHT,
+			HAT_DOWN,
+			HAT_LEFT,
+			HAT_RIGHTUP,
+			HAT_RIGHTDOWN,
+			HAT_LEFTUP,
+			HAT_LEFTDOWN,
+			HAT_MAX_ENUM = 16
 		};
 
-		enum JoystickHat
-		{
-			JOYSTICK_HAT_CENTERED = 0,
-			JOYSTICK_HAT_UP = 1,
-			JOYSTICK_HAT_RIGHT = 2,
-			JOYSTICK_HAT_DOWN = 4,
-			JOYSTICK_HAT_LEFT = 8,
-			JOYSTICK_HAT_RIGHTUP = (2|1),
-			JOYSTICK_HAT_RIGHTDOWN = (2|4),
-			JOYSTICK_HAT_LEFTUP = (8|1),
-			JOYSTICK_HAT_LEFTDOWN = (8|4)
-		};
+		virtual ~Joystick();
+
+		static bool getConstant(const char * in, Hat & out);
+		static bool getConstant(Hat in, const char *& out);
+
+	private:
 
-		virtual ~Joystick(){};
+		static StringMap<Hat, HAT_MAX_ENUM>::Entry hatEntries[];
+		static StringMap<Hat, HAT_MAX_ENUM> hats;
 
 	}; // Joystick
 

+ 23 - 4
src/modules/joystick/sdl/Joystick.cpp

@@ -202,15 +202,19 @@ namespace sdl
 		return (SDL_JoystickGetButton(joysticks[index], button) == 1);
 	}
 
-	int Joystick::getHat(int index, int hat)
+	Joystick::Hat Joystick::getHat(int index, int hat)
 	{
+		Hat h = HAT_INVALID;
+
 		if(!verifyJoystick(index))
-			return 0;
+			return h;
 
 		if(hat >= getNumHats(index))
-			return 0;
+			return h;
+
+		hats.find(SDL_JoystickGetHat(joysticks[index], hat), h);
 
-		return SDL_JoystickGetHat(joysticks[index], hat);
+		return h;
 	}
 
 	void Joystick::close(int index)
@@ -225,6 +229,21 @@ namespace sdl
 		}
 	}
 
+	EnumMap<Joystick::Hat, Uint8, Joystick::HAT_MAX_ENUM>::Entry Joystick::hatEntries[] = 
+	{
+		{Joystick::HAT_CENTERED, SDL_HAT_CENTERED},
+		{Joystick::HAT_UP, SDL_HAT_UP},
+		{Joystick::HAT_RIGHT, SDL_HAT_RIGHT},
+		{Joystick::HAT_DOWN, SDL_HAT_DOWN},
+		{Joystick::HAT_LEFT, SDL_HAT_LEFT},
+		{Joystick::HAT_RIGHTUP, SDL_HAT_RIGHTUP},
+		{Joystick::HAT_RIGHTDOWN, SDL_HAT_RIGHTDOWN},
+		{Joystick::HAT_LEFTUP, SDL_HAT_LEFTUP},
+		{Joystick::HAT_LEFTDOWN, SDL_HAT_LEFTDOWN},
+	};
+
+	EnumMap<Joystick::Hat, Uint8, Joystick::HAT_MAX_ENUM> Joystick::hats(Joystick::hatEntries, sizeof(Joystick::hatEntries));
+
 } // sdl
 } // joystick
 } // love

+ 10 - 4
src/modules/joystick/sdl/Joystick.h

@@ -21,11 +21,12 @@
 #ifndef LOVE_JOYSTICK_SDL_JOYSTICK_H
 #define LOVE_JOYSTICK_SDL_JOYSTICK_H
 
-// SDL
-#include <SDL.h>
-
 // LOVE
 #include <joystick/Joystick.h>
+#include <common/EnumMap.h>
+
+// SDL
+#include <SDL.h>
 
 namespace love
 {
@@ -59,9 +60,14 @@ namespace sdl
 		int getAxes(lua_State * L);
 		int getBall(lua_State * L);
 		bool isDown(int index, int button);
-		int getHat(int index, int hat);
+		Hat getHat(int index, int hat);
 		void close(int index);
 
+	private:
+
+		static EnumMap<Hat, Uint8, Joystick::HAT_MAX_ENUM>::Entry hatEntries[];
+		static EnumMap<Hat, Uint8, Joystick::HAT_MAX_ENUM> hats;
+
 	}; // Joystick
 
 } // sdl

+ 7 - 19
src/modules/joystick/sdl/wrap_Joystick.cpp

@@ -113,7 +113,13 @@ namespace sdl
 	{
 		int index = luaL_checkint(L, 1);
 		int hat = luaL_checkint(L, 2);
-		lua_pushinteger(L, instance->getHat(index, hat));
+
+		Joystick::Hat h = instance->getHat(index, hat);
+
+		const char * direction = "";
+		Joystick::getConstant(h, direction);
+		lua_pushstring(L, direction);
+
 		return 1;
 	}
 
@@ -145,23 +151,6 @@ namespace sdl
 		{ 0, 0 }
 	};
 
-	// List of constants.
-	static const Constant constants[] = {
-		{ "joystick_axis_horizontal", Joystick::JOYSTICK_AXIS_HORIZONTAL },
-		{ "joystick_axis_vertical", Joystick::JOYSTICK_AXIS_VERITCAL },
-
-		{ "joystick_hat_centered", Joystick::JOYSTICK_HAT_CENTERED },
-		{ "joystick_hat_up", Joystick::JOYSTICK_HAT_UP },
-		{ "joystick_hat_right", Joystick::JOYSTICK_HAT_RIGHT },
-		{ "joystick_hat_down", Joystick::JOYSTICK_HAT_DOWN },
-		{ "joystick_hat_left", Joystick::JOYSTICK_HAT_LEFT },
-		{ "joystick_hat_rightup", Joystick::JOYSTICK_HAT_RIGHTUP },
-		{ "joystick_hat_rightdown", Joystick::JOYSTICK_HAT_RIGHTDOWN },
-		{ "joystick_hat_leftup", Joystick::JOYSTICK_HAT_LEFTUP },
-		{ "joystick_hat_leftdown", Joystick::JOYSTICK_HAT_LEFTDOWN },
-		{ 0, 0 }
-	};
-
 	int luaopen_love_joystick(lua_State * L)
 	{
 		if(instance == 0)
@@ -183,7 +172,6 @@ namespace sdl
 		w.flags = MODULE_T;
 		w.functions = functions;
 		w.types = 0;
-		w.constants = constants;
 
 		return luax_register_module(L, w);
 	}

+ 187 - 0
src/modules/keyboard/Keyboard.cpp

@@ -0,0 +1,187 @@
+/**
+* Copyright (c) 2006-2009 LOVE Development Team
+* 
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* 
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#include "Keyboard.h"
+
+namespace love
+{
+namespace keyboard
+{
+
+	bool Keyboard::getConstant(const char * in, Keyboard::Key & out)
+	{
+		return keys.find(in, out);
+	}
+
+	bool Keyboard::getConstant(Keyboard::Key in, const char *& out)
+	{
+		return keys.find(in, out);
+	}
+
+	StringMap<Keyboard::Key, Keyboard::KEY_MAX_ENUM>::Entry Keyboard::keyEntries[] = 
+	{
+		{"backspace", Keyboard::KEY_BACKSPACE},
+		{"tab", Keyboard::KEY_TAB},
+		{"clear", Keyboard::KEY_CLEAR},
+		{"return", Keyboard::KEY_RETURN},
+		{"pause", Keyboard::KEY_PAUSE},
+		{"escape", Keyboard::KEY_ESCAPE},
+		{" ", Keyboard::KEY_SPACE},
+		{"!", Keyboard::KEY_EXCLAIM},
+		{"\"", Keyboard::KEY_QUOTEDBL},
+		{"#", Keyboard::KEY_HASH},
+		{"$", Keyboard::KEY_DOLLAR},
+		{"&", Keyboard::KEY_AMPERSAND},
+		{"'", Keyboard::KEY_QUOTE},
+		{"(", Keyboard::KEY_LEFTPAREN},
+		{")", Keyboard::KEY_RIGHTPAREN},
+		{"*", Keyboard::KEY_ASTERISK},
+		{"+", Keyboard::KEY_PLUS},
+		{",", Keyboard::KEY_COMMA},
+		{"-", Keyboard::KEY_MINUS},
+		{".", Keyboard::KEY_PERIOD},
+		{"/", Keyboard::KEY_SLASH},
+		{"0", Keyboard::KEY_0},
+		{"1", Keyboard::KEY_1},
+		{"2", Keyboard::KEY_2},
+		{"3", Keyboard::KEY_3},
+		{"4", Keyboard::KEY_4},
+		{"5", Keyboard::KEY_5},
+		{"6", Keyboard::KEY_6},
+		{"7", Keyboard::KEY_7},
+		{"8", Keyboard::KEY_8},
+		{"9", Keyboard::KEY_9},
+		{":", Keyboard::KEY_COLON},
+		{";", Keyboard::KEY_SEMICOLON},
+		{"<", Keyboard::KEY_LESS},
+		{"=", Keyboard::KEY_EQUALS},
+		{">", Keyboard::KEY_GREATER},
+		{"?", Keyboard::KEY_QUESTION},
+		{"@", Keyboard::KEY_AT},
+
+		{"[", Keyboard::KEY_LEFTBRACKET},
+		{"\\", Keyboard::KEY_BACKSLASH},
+		{"]", Keyboard::KEY_RIGHTBRACKET},
+		{"^", Keyboard::KEY_CARET},
+		{"_", Keyboard::KEY_UNDERSCORE},
+		{"`", Keyboard::KEY_BACKQUOTE},
+		{"a", Keyboard::KEY_A},
+		{"b", Keyboard::KEY_B},
+		{"c", Keyboard::KEY_C},
+		{"d", Keyboard::KEY_D},
+		{"e", Keyboard::KEY_E},
+		{"f", Keyboard::KEY_F},
+		{"g", Keyboard::KEY_G},
+		{"h", Keyboard::KEY_H},
+		{"i", Keyboard::KEY_I},
+		{"j", Keyboard::KEY_J},
+		{"k", Keyboard::KEY_K},
+		{"l", Keyboard::KEY_L},
+		{"m", Keyboard::KEY_M},
+		{"n", Keyboard::KEY_N},
+		{"o", Keyboard::KEY_O},
+		{"p", Keyboard::KEY_P},
+		{"q", Keyboard::KEY_Q},
+		{"r", Keyboard::KEY_R},
+		{"s", Keyboard::KEY_S},
+		{"t", Keyboard::KEY_T},
+		{"u", Keyboard::KEY_U},
+		{"v", Keyboard::KEY_V},
+		{"w", Keyboard::KEY_W},
+		{"x", Keyboard::KEY_X},
+		{"y", Keyboard::KEY_Y},
+		{"z", Keyboard::KEY_Z},
+		{"delete", Keyboard::KEY_DELETE},
+
+		{"kp0", Keyboard::KEY_KP0},
+		{"kp1", Keyboard::KEY_KP1},
+		{"kp2", Keyboard::KEY_KP2},
+		{"kp3", Keyboard::KEY_KP3},
+		{"kp4", Keyboard::KEY_KP4},
+		{"kp5", Keyboard::KEY_KP5},
+		{"kp6", Keyboard::KEY_KP6},
+		{"kp7", Keyboard::KEY_KP7},
+		{"kp8", Keyboard::KEY_KP8},
+		{"kp9", Keyboard::KEY_KP9},
+		{"kp.", Keyboard::KEY_KP_PERIOD},
+		{"kp/", Keyboard::KEY_KP_DIVIDE},
+		{"kp*", Keyboard::KEY_KP_MULTIPLY},
+		{"kp-", Keyboard::KEY_KP_MINUS},
+		{"kp+", Keyboard::KEY_KP_PLUS},
+		{"kpenter", Keyboard::KEY_KP_ENTER},
+		{"kp=", Keyboard::KEY_KP_EQUALS},
+
+		{"kpup", Keyboard::KEY_UP},
+		{"kpdown", Keyboard::KEY_DOWN},
+		{"kpright", Keyboard::KEY_RIGHT},
+		{"kpleft", Keyboard::KEY_LEFT},
+		{"kpinsert", Keyboard::KEY_INSERT},
+		{"kphome", Keyboard::KEY_HOME},
+		{"kpend", Keyboard::KEY_END},
+		{"kppageup", Keyboard::KEY_PAGEUP},
+		{"kppagedown", Keyboard::KEY_PAGEDOWN},
+
+		{"f1", Keyboard::KEY_F1},
+		{"f2", Keyboard::KEY_F2},
+		{"f3", Keyboard::KEY_F3},
+		{"f4", Keyboard::KEY_F4},
+		{"f5", Keyboard::KEY_F5},
+		{"f6", Keyboard::KEY_F6},
+		{"f7", Keyboard::KEY_F7},
+		{"f8", Keyboard::KEY_F8},
+		{"f9", Keyboard::KEY_F9},
+		{"f10", Keyboard::KEY_F10},
+		{"f11", Keyboard::KEY_F11},
+		{"f12", Keyboard::KEY_F12},
+		{"f13", Keyboard::KEY_F13},
+		{"f14", Keyboard::KEY_F14},
+		{"f15", Keyboard::KEY_F15},
+
+		{"numlock", Keyboard::KEY_NUMLOCK},
+		{"capslock", Keyboard::KEY_CAPSLOCK},
+		{"scrollock", Keyboard::KEY_SCROLLOCK},
+		{"rshift", Keyboard::KEY_RSHIFT},
+		{"lshift", Keyboard::KEY_LSHIFT},
+		{"rctrl", Keyboard::KEY_RCTRL},
+		{"lctrl", Keyboard::KEY_LCTRL},
+		{"ralt", Keyboard::KEY_RALT},
+		{"lalt", Keyboard::KEY_LALT},
+		{"rmeta", Keyboard::KEY_RMETA},
+		{"lmeta", Keyboard::KEY_LMETA},
+		{"lsuper", Keyboard::KEY_LSUPER},
+		{"rsuper", Keyboard::KEY_RSUPER},
+		{"mode", Keyboard::KEY_MODE},
+		{"compose", Keyboard::KEY_COMPOSE},
+
+		{"help", Keyboard::KEY_HELP},
+		{"print", Keyboard::KEY_PRINT},
+		{"sysreq", Keyboard::KEY_SYSREQ},
+		{"break", Keyboard::KEY_BREAK},
+		{"menu", Keyboard::KEY_MENU},
+		{"power", Keyboard::KEY_POWER},
+		{"euro", Keyboard::KEY_EURO},
+		{"undo", Keyboard::KEY_UNDO},
+	};
+
+	StringMap<Keyboard::Key, Keyboard::KEY_MAX_ENUM> Keyboard::keys(Keyboard::keyEntries, sizeof(Keyboard::keyEntries));
+
+
+} // keyboard
+} // love

+ 157 - 2
src/modules/keyboard/Keyboard.h

@@ -23,6 +23,7 @@
 
 // LOVE
 #include <common/Module.h>
+#include <common/StringMap.h>
 
 namespace love
 {
@@ -32,11 +33,165 @@ namespace keyboard
 	{
 	public:
 
-		static const int KEY_REPEAT_DELAY = -1;
-		static const int KEY_REPEAT_INTERVAL = -2;
+		enum Key
+		{
+			KEY_UNKNOWN,
+			KEY_BACKSPACE,
+			KEY_TAB,
+			KEY_CLEAR,
+			KEY_RETURN,
+			KEY_PAUSE,
+			KEY_ESCAPE,
+			KEY_SPACE,
+			KEY_EXCLAIM,
+			KEY_QUOTEDBL,
+			KEY_HASH,
+			KEY_DOLLAR,
+			KEY_AMPERSAND,
+			KEY_QUOTE,
+			KEY_LEFTPAREN,
+			KEY_RIGHTPAREN,
+			KEY_ASTERISK,
+			KEY_PLUS,
+			KEY_COMMA,
+			KEY_MINUS,
+			KEY_PERIOD,
+			KEY_SLASH,
+			KEY_0,
+			KEY_1,
+			KEY_2,
+			KEY_3,
+			KEY_4,
+			KEY_5,
+			KEY_6,
+			KEY_7,
+			KEY_8,
+			KEY_9,
+			KEY_COLON,
+			KEY_SEMICOLON,
+			KEY_LESS,
+			KEY_EQUALS,
+			KEY_GREATER,
+			KEY_QUESTION,
+			KEY_AT,
+
+			KEY_LEFTBRACKET,
+			KEY_BACKSLASH,
+			KEY_RIGHTBRACKET,
+			KEY_CARET,
+			KEY_UNDERSCORE,
+			KEY_BACKQUOTE,
+			KEY_A,
+			KEY_B,
+			KEY_C,
+			KEY_D,
+			KEY_E,
+			KEY_F,
+			KEY_G,
+			KEY_H,
+			KEY_I,
+			KEY_J,
+			KEY_K,
+			KEY_L,
+			KEY_M,
+			KEY_N,
+			KEY_O,
+			KEY_P,
+			KEY_Q,
+			KEY_R,
+			KEY_S,
+			KEY_T,
+			KEY_U,
+			KEY_V,
+			KEY_W,
+			KEY_X,
+			KEY_Y,
+			KEY_Z,
+			KEY_DELETE,
+
+			KEY_KP0,
+			KEY_KP1,
+			KEY_KP2,
+			KEY_KP3,
+			KEY_KP4,
+			KEY_KP5,
+			KEY_KP6,
+			KEY_KP7,
+			KEY_KP8,
+			KEY_KP9,
+			KEY_KP_PERIOD,
+			KEY_KP_DIVIDE,
+			KEY_KP_MULTIPLY,
+			KEY_KP_MINUS,
+			KEY_KP_PLUS,
+			KEY_KP_ENTER,
+			KEY_KP_EQUALS,
+
+			KEY_UP,
+			KEY_DOWN,
+			KEY_RIGHT,
+			KEY_LEFT,
+			KEY_INSERT,
+			KEY_HOME,
+			KEY_END,
+			KEY_PAGEUP,
+			KEY_PAGEDOWN,
+
+			KEY_F1,
+			KEY_F2,
+			KEY_F3,
+			KEY_F4,
+			KEY_F5,
+			KEY_F6,
+			KEY_F7,
+			KEY_F8,
+			KEY_F9,
+			KEY_F10,
+			KEY_F11,
+			KEY_F12,
+			KEY_F13,
+			KEY_F14,
+			KEY_F15,
+
+			KEY_NUMLOCK,
+			KEY_CAPSLOCK,
+			KEY_SCROLLOCK,
+			KEY_RSHIFT,
+			KEY_LSHIFT,
+			KEY_RCTRL,
+			KEY_LCTRL,
+			KEY_RALT,
+			KEY_LALT,
+			KEY_RMETA,
+			KEY_LMETA,
+			KEY_LSUPER,
+			KEY_RSUPER,
+			KEY_MODE,
+			KEY_COMPOSE,
+
+			KEY_HELP,
+			KEY_PRINT,
+			KEY_SYSREQ,
+			KEY_BREAK,
+			KEY_MENU,
+			KEY_POWER,
+			KEY_EURO,
+			KEY_UNDO,
+			KEY_MAX_ENUM = 512
+		};
+
+		static const int DEFAULT = 0;
 
 		virtual ~Keyboard(){}
 
+		static bool getConstant(const char * in, Key & out);
+		static bool getConstant(Key in, const char *& out);
+
+	private:
+
+		static StringMap<Key, KEY_MAX_ENUM>::Entry keyEntries[];
+		static StringMap<Key, KEY_MAX_ENUM> keys;
+
 	}; // Keyboard
 
 } // keyboard

+ 160 - 11
src/modules/keyboard/sdl/Keyboard.cpp

@@ -20,9 +20,6 @@
 
 #include "Keyboard.h"
 
-// SDL
-#include <SDL.h>
-
 namespace love
 {
 namespace keyboard
@@ -34,22 +31,26 @@ namespace sdl
 		return "love.keyboard.sdl";
 	}
 
-	bool Keyboard::isDown(int key) const
+	bool Keyboard::isDown(Key key) const
 	{
-		Uint8 * keystate = SDL_GetKeyState(0);
-		return keystate[key] == 1;		
+		SDLKey k;
+		
+		if(keys.find(key, k))
+		{		
+			Uint8 * keystate = SDL_GetKeyState(0);
+			return keystate[(unsigned)k] == 1;	
+		}
+
+		return false;	
 	}
 
 	void Keyboard::setKeyRepeat(int delay, int interval) const
 	{
-		if(delay == KEY_REPEAT_DELAY)
+		if(delay == DEFAULT)
 			delay = SDL_DEFAULT_REPEAT_DELAY;
 
-		if(interval == KEY_REPEAT_INTERVAL)
+		if(interval == DEFAULT)
 			interval = SDL_DEFAULT_REPEAT_INTERVAL;
-		
-		if(SDL_EnableKeyRepeat(delay, interval) == -1)
-			throw new Exception("[Keyboard::enableKeyRepeat] Unable to enable key repeat");
 	}
 
 	int Keyboard::getKeyRepeatDelay() const
@@ -66,6 +67,154 @@ namespace sdl
 		return interval;
 	}
 
+	EnumMap<Keyboard::Key, SDLKey, Keyboard::KEY_MAX_ENUM>::Entry Keyboard::keyEntries[] = 
+	{
+		{ Keyboard::KEY_BACKSPACE, SDLK_BACKSPACE},
+		{ Keyboard::KEY_TAB, SDLK_TAB},
+		{ Keyboard::KEY_CLEAR, SDLK_CLEAR},
+		{ Keyboard::KEY_RETURN, SDLK_RETURN},
+		{ Keyboard::KEY_PAUSE, SDLK_PAUSE},
+		{ Keyboard::KEY_ESCAPE, SDLK_ESCAPE },
+		{ Keyboard::KEY_SPACE, SDLK_SPACE },
+		{ Keyboard::KEY_EXCLAIM, SDLK_EXCLAIM },
+		{ Keyboard::KEY_QUOTEDBL, SDLK_QUOTEDBL },
+		{ Keyboard::KEY_HASH, SDLK_HASH },
+		{ Keyboard::KEY_DOLLAR, SDLK_DOLLAR },
+		{ Keyboard::KEY_AMPERSAND, SDLK_AMPERSAND },
+		{ Keyboard::KEY_QUOTE, SDLK_QUOTE },
+		{ Keyboard::KEY_LEFTPAREN, SDLK_LEFTPAREN },
+		{ Keyboard::KEY_RIGHTPAREN, SDLK_RIGHTPAREN },
+		{ Keyboard::KEY_ASTERISK, SDLK_ASTERISK },
+		{ Keyboard::KEY_PLUS, SDLK_PLUS },
+		{ Keyboard::KEY_COMMA, SDLK_COMMA },
+		{ Keyboard::KEY_MINUS, SDLK_MINUS },
+		{ Keyboard::KEY_PERIOD, SDLK_PERIOD },
+		{ Keyboard::KEY_SLASH, SDLK_SLASH },
+		{ Keyboard::KEY_0, SDLK_0 },
+		{ Keyboard::KEY_1, SDLK_1 },
+		{ Keyboard::KEY_2, SDLK_2 },
+		{ Keyboard::KEY_3, SDLK_3 },
+		{ Keyboard::KEY_4, SDLK_4 },
+		{ Keyboard::KEY_5, SDLK_5 },
+		{ Keyboard::KEY_6, SDLK_6 },
+		{ Keyboard::KEY_7, SDLK_7 },
+		{ Keyboard::KEY_8, SDLK_8 },
+		{ Keyboard::KEY_9, SDLK_9 },
+		{ Keyboard::KEY_COLON, SDLK_COLON },
+		{ Keyboard::KEY_SEMICOLON, SDLK_SEMICOLON },
+		{ Keyboard::KEY_LESS, SDLK_LESS },
+		{ Keyboard::KEY_EQUALS, SDLK_EQUALS },
+		{ Keyboard::KEY_GREATER, SDLK_GREATER },
+		{ Keyboard::KEY_QUESTION, SDLK_QUESTION },
+		{ Keyboard::KEY_AT, SDLK_AT },
+
+		{ Keyboard::KEY_LEFTBRACKET, SDLK_LEFTBRACKET },
+		{ Keyboard::KEY_BACKSLASH, SDLK_BACKSLASH },
+		{ Keyboard::KEY_RIGHTBRACKET, SDLK_RIGHTBRACKET },
+		{ Keyboard::KEY_CARET, SDLK_CARET },
+		{ Keyboard::KEY_UNDERSCORE, SDLK_UNDERSCORE },
+		{ Keyboard::KEY_BACKQUOTE, SDLK_BACKQUOTE },
+		{ Keyboard::KEY_A, SDLK_a },
+		{ Keyboard::KEY_B, SDLK_b },
+		{ Keyboard::KEY_C, SDLK_c },
+		{ Keyboard::KEY_D, SDLK_d },
+		{ Keyboard::KEY_E, SDLK_e },
+		{ Keyboard::KEY_F, SDLK_f },
+		{ Keyboard::KEY_G, SDLK_g },
+		{ Keyboard::KEY_H, SDLK_h },
+		{ Keyboard::KEY_I, SDLK_i },
+		{ Keyboard::KEY_J, SDLK_j },
+		{ Keyboard::KEY_K, SDLK_k },
+		{ Keyboard::KEY_L, SDLK_l },
+		{ Keyboard::KEY_M, SDLK_m },
+		{ Keyboard::KEY_N, SDLK_n },
+		{ Keyboard::KEY_O, SDLK_o },
+		{ Keyboard::KEY_P, SDLK_p },
+		{ Keyboard::KEY_Q, SDLK_q },
+		{ Keyboard::KEY_R, SDLK_r },
+		{ Keyboard::KEY_S, SDLK_s },
+		{ Keyboard::KEY_T, SDLK_t },
+		{ Keyboard::KEY_U, SDLK_u },
+		{ Keyboard::KEY_V, SDLK_v },
+		{ Keyboard::KEY_W, SDLK_w },
+		{ Keyboard::KEY_X, SDLK_x },
+		{ Keyboard::KEY_Y, SDLK_y },
+		{ Keyboard::KEY_Z, SDLK_z },
+		{ Keyboard::KEY_DELETE, SDLK_DELETE },
+
+		{ Keyboard::KEY_KP0, SDLK_KP0 },
+		{ Keyboard::KEY_KP1, SDLK_KP1 },
+		{ Keyboard::KEY_KP2, SDLK_KP2 },
+		{ Keyboard::KEY_KP3, SDLK_KP3 },
+		{ Keyboard::KEY_KP4, SDLK_KP4 },
+		{ Keyboard::KEY_KP5, SDLK_KP5 },
+		{ Keyboard::KEY_KP6, SDLK_KP6 },
+		{ Keyboard::KEY_KP7, SDLK_KP7 },
+		{ Keyboard::KEY_KP8, SDLK_KP8 },
+		{ Keyboard::KEY_KP9, SDLK_KP9 },
+		{ Keyboard::KEY_KP_PERIOD, SDLK_KP_PERIOD },
+		{ Keyboard::KEY_KP_DIVIDE, SDLK_KP_DIVIDE },
+		{ Keyboard::KEY_KP_MULTIPLY, SDLK_KP_MULTIPLY},
+		{ Keyboard::KEY_KP_MINUS, SDLK_KP_MINUS },
+		{ Keyboard::KEY_KP_PLUS, SDLK_KP_PLUS },
+		{ Keyboard::KEY_KP_ENTER, SDLK_KP_ENTER },
+		{ Keyboard::KEY_KP_EQUALS, SDLK_KP_EQUALS },
+
+		{ Keyboard::KEY_UP, SDLK_UP },
+		{ Keyboard::KEY_DOWN, SDLK_DOWN },
+		{ Keyboard::KEY_RIGHT, SDLK_RIGHT },
+		{ Keyboard::KEY_LEFT, SDLK_LEFT },
+		{ Keyboard::KEY_INSERT, SDLK_INSERT },
+		{ Keyboard::KEY_HOME, SDLK_HOME },
+		{ Keyboard::KEY_END, SDLK_END },
+		{ Keyboard::KEY_PAGEUP, SDLK_PAGEUP },
+		{ Keyboard::KEY_PAGEDOWN, SDLK_PAGEDOWN },
+
+		{ Keyboard::KEY_F1, SDLK_F1 },
+		{ Keyboard::KEY_F2, SDLK_F2 },
+		{ Keyboard::KEY_F3, SDLK_F3 },
+		{ Keyboard::KEY_F4, SDLK_F4 },
+		{ Keyboard::KEY_F5, SDLK_F5 },
+		{ Keyboard::KEY_F6, SDLK_F6 },
+		{ Keyboard::KEY_F7, SDLK_F7 },
+		{ Keyboard::KEY_F8, SDLK_F8 },
+		{ Keyboard::KEY_F9, SDLK_F9 },
+		{ Keyboard::KEY_F10, SDLK_F10 },
+		{ Keyboard::KEY_F11, SDLK_F11 },
+		{ Keyboard::KEY_F12, SDLK_F12 },
+		{ Keyboard::KEY_F13, SDLK_F13 },
+		{ Keyboard::KEY_F14, SDLK_F14 },
+		{ Keyboard::KEY_F15, SDLK_F15 },
+
+		{ Keyboard::KEY_NUMLOCK, SDLK_NUMLOCK },
+		{ Keyboard::KEY_CAPSLOCK, SDLK_CAPSLOCK },
+		{ Keyboard::KEY_SCROLLOCK, SDLK_SCROLLOCK },
+		{ Keyboard::KEY_RSHIFT, SDLK_RSHIFT },
+		{ Keyboard::KEY_LSHIFT, SDLK_LSHIFT },
+		{ Keyboard::KEY_RCTRL, SDLK_RCTRL },
+		{ Keyboard::KEY_LCTRL, SDLK_LCTRL },
+		{ Keyboard::KEY_RALT, SDLK_RALT },
+		{ Keyboard::KEY_LALT, SDLK_LALT },
+		{ Keyboard::KEY_RMETA, SDLK_RMETA },
+		{ Keyboard::KEY_LMETA, SDLK_LMETA },
+		{ Keyboard::KEY_LSUPER, SDLK_LSUPER },
+		{ Keyboard::KEY_RSUPER, SDLK_RSUPER },
+		{ Keyboard::KEY_MODE, SDLK_MODE },
+		{ Keyboard::KEY_COMPOSE, SDLK_COMPOSE },
+
+		{ Keyboard::KEY_HELP, SDLK_HELP },
+		{ Keyboard::KEY_PRINT, SDLK_PRINT },
+		{ Keyboard::KEY_SYSREQ, SDLK_SYSREQ },
+		{ Keyboard::KEY_BREAK, SDLK_BREAK },
+		{ Keyboard::KEY_MENU, SDLK_MENU },
+		{ Keyboard::KEY_POWER, SDLK_POWER },
+		{ Keyboard::KEY_EURO, SDLK_EURO },
+		{ Keyboard::KEY_UNDO, SDLK_UNDO },
+	};
+
+	EnumMap<Keyboard::Key, SDLKey, Keyboard::KEY_MAX_ENUM> Keyboard::keys(Keyboard::keyEntries, sizeof(Keyboard::keyEntries));
+
+
 } // sdl
 } // keyboard
 } // love

+ 11 - 2
src/modules/keyboard/sdl/Keyboard.h

@@ -23,6 +23,10 @@
 
 // LOVE
 #include <keyboard/Keyboard.h>
+#include <common/EnumMap.h>
+
+// SDL
+#include <SDL.h>
 
 namespace love
 {
@@ -42,14 +46,14 @@ namespace sdl
 		* @param key A key identifier.
 		* @return boolean
 		**/
-		bool isDown(int key) const;
+		bool isDown(Key key) const;
 
 		/**
 		* Enables key repeating.
 		* @param delay The amount of delay before repeating the key (in milliseconds)
 		* @param interval Specifies the amount of time between repeats (in milliseconds)
 		**/
-		void setKeyRepeat(int delay = 0, int interval = 0) const;
+		void setKeyRepeat(int delay, int interval) const;
 
 		/**
 		* Gets the specified delay for the key repeat.
@@ -63,6 +67,11 @@ namespace sdl
 		**/
 		int getKeyRepeatInterval() const;
 
+	private:
+
+		static EnumMap<Key, SDLKey, Keyboard::KEY_MAX_ENUM>::Entry keyEntries[];
+		static EnumMap<Key, SDLKey, Keyboard::KEY_MAX_ENUM> keys;
+
 	}; // Keyboard
 
 } // sdl

+ 14 - 162
src/modules/keyboard/sdl/wrap_Keyboard.cpp

@@ -26,12 +26,21 @@ namespace keyboard
 {
 namespace sdl
 {
-	static Keyboard * instance = 0;
+	static Keyboard * instance;
 
 	int w_isDown(lua_State * L)
 	{
-		int b = luaL_checkint(L, 1);
-		luax_pushboolean(L, instance->isDown(b));
+		Keyboard::Key k;
+
+		if(Keyboard::getConstant(luaL_checkstring(L, 1), k))
+		{
+			luax_pushboolean(L, instance->isDown(k));
+		}
+		else
+		{
+			luax_pushboolean(L, false);
+		}
+
 		return 1;
 	}
 
@@ -39,13 +48,11 @@ namespace sdl
 	{
 		if(lua_gettop(L) == 0)
 		{
-			instance->setKeyRepeat();
+			instance->setKeyRepeat(0, 0);
 			return 0;
 		}
 
-		int a = luaL_checkint(L, 1);
-		int b = luaL_checkint(L, 2);
-		instance->setKeyRepeat(a, b);
+		instance->setKeyRepeat(luaL_checkint(L, 1), luaL_checkint(L, 2));
 		return 0;
 	}
 
@@ -64,160 +71,6 @@ namespace sdl
 		{ 0, 0 }
 	};
 
-	// List of constants.
-	static const Constant constants[] = {
-		{ "key_unknown", 0 },
-		{ "key_first", 0 },
-		{ "key_backspace", 8 },
-		{ "key_tab", 9 },
-		{ "key_clear", 12 },
-		{ "key_return", 13 },
-		{ "key_pause", 19 },
-		{ "key_escape", 27 },
-		{ "key_space", 32 },
-		{ "key_exclaim", 33 },
-		{ "key_quotedbl", 34 },
-		{ "key_hash", 35 },
-		{ "key_dollar", 36 },
-		{ "key_ampersand", 38 },
-		{ "key_quote", 39 },
-		{ "key_leftparen", 40 },
-		{ "key_rightparen", 41 },
-		{ "key_asterisk", 42 },
-		{ "key_plus", 43 },
-		{ "key_comma", 44 },
-		{ "key_minus", 45 },
-		{ "key_period", 46 },
-		{ "key_slash", 47 },
-
-		{ "key_0", 48 },
-		{ "key_1", 49 },
-		{ "key_2", 50 },
-		{ "key_3", 51 },
-		{ "key_4", 52 },
-		{ "key_5", 53 },
-		{ "key_6", 54 },
-		{ "key_7", 55 },
-		{ "key_8", 56 },
-		{ "key_9", 57 },
-
-		{ "key_colon", 58 },
-		{ "key_semicolon", 59 },
-		{ "key_less", 60 },
-		{ "key_equals", 61 },
-		{ "key_greater", 62 },
-		{ "key_question", 63 },
-		{ "key_at", 64 },
-
-		{ "key_leftbracket", 91 },
-		{ "key_backslash", 92 },
-		{ "key_rightbracket", 93 },
-		{ "key_caret", 94 },
-		{ "key_underscore", 95 },
-		{ "key_backquote", 96 },
-
-		{ "key_a", 97 },
-		{ "key_b", 98 },
-		{ "key_c", 99 },
-		{ "key_d", 100 },
-		{ "key_e", 101 },
-		{ "key_f", 102 },
-		{ "key_g", 103 },
-		{ "key_h", 104 },
-		{ "key_i", 105 },
-		{ "key_j", 106 },
-		{ "key_k", 107 },
-		{ "key_l", 108 },
-		{ "key_m", 109 },
-		{ "key_n", 110 },
-		{ "key_o", 111 },
-		{ "key_p", 112 },
-		{ "key_q", 113 },
-		{ "key_r", 114 },
-		{ "key_s", 115 },
-		{ "key_t", 116 },
-		{ "key_u", 117 },
-		{ "key_v", 118 },
-		{ "key_w", 119 },
-		{ "key_x", 120 },
-		{ "key_y", 121 },
-		{ "key_z", 122 },
-		{ "key_delete", 127 },
-
-		{ "key_kp0", 256 },
-		{ "key_kp1", 257 },
-		{ "key_kp2", 258 },
-		{ "key_kp3", 259 },
-		{ "key_kp4", 260 },
-		{ "key_kp5", 261 },
-		{ "key_kp6", 262 },
-		{ "key_kp7", 263 },
-		{ "key_kp8", 264 },
-		{ "key_kp9", 265 },
-		{ "key_kp_period", 266 },
-		{ "key_kp_divide", 267 },
-		{ "key_kp_multiply", 268 },
-		{ "key_kp_minus", 269 },
-		{ "key_kp_plus", 270 },
-		{ "key_kp_enter", 271 },
-		{ "key_kp_equals", 272 },
-
-		{ "key_up", 273 },
-		{ "key_down", 274 },
-		{ "key_right", 275 },
-		{ "key_left", 276 },
-		{ "key_insert", 277 },
-		{ "key_home", 278 },
-		{ "key_end", 279 },
-		{ "key_pageup", 280 },
-		{ "key_pagedown", 281 },
-
-		{ "key_f1", 282 },
-		{ "key_f2", 283 },
-		{ "key_f3", 284 },
-		{ "key_f4", 285 },
-		{ "key_f5", 286 },
-		{ "key_f6", 287 },
-		{ "key_f7", 288 },
-		{ "key_f8", 289 },
-		{ "key_f9", 290 },
-		{ "key_f10", 291 },
-		{ "key_f11", 292 },
-		{ "key_f12", 293 },
-		{ "key_f13", 294 },
-		{ "key_f14", 295 },
-		{ "key_f15", 296 },
-
-		{ "key_numlock", 300 },
-		{ "key_capslock", 301 },
-		{ "key_scrollock", 302 },
-		{ "key_rshift", 303 },
-		{ "key_lshift", 304 },
-		{ "key_rctrl", 305 },
-		{ "key_lctrl", 306 },
-		{ "key_ralt", 307 },
-		{ "key_lalt", 308 },
-		{ "key_rmeta", 309 },
-		{ "key_lmeta", 310 },
-		{ "key_lsuper", 311 },
-		{ "key_rsuper", 312 },
-		{ "key_mode", 313 },
-		{ "key_compose", 314 },
-
-		{ "key_help", 315 },
-		{ "key_print", 316 },
-		{ "key_sysreq", 317 },
-		{ "key_break", 318 },
-		{ "key_menu", 319 },
-		{ "key_power", 320 },
-		{ "key_euro", 321 },
-		{ "key_undo", 322 },
-
-		{ "key_repeat_delay", Keyboard::KEY_REPEAT_DELAY },
-		{ "key_repeat_interval", Keyboard::KEY_REPEAT_INTERVAL },
-		{ 0, 0 }
-	};
-
 	int luaopen_love_keyboard(lua_State * L)
 	{
 		if(instance == 0)
@@ -238,7 +91,6 @@ namespace sdl
 		w.flags = MODULE_T;
 		w.functions = functions;
 		w.types = 0;
-		w.constants = constants;
 
 		return luax_register_module(L, w);
 	}

+ 3 - 0
src/modules/keyboard/sdl/wrap_Keyboard.h

@@ -25,6 +25,9 @@
 #include <common/config.h>
 #include "Keyboard.h"
 
+// SDL
+#include <SDL.h>
+
 namespace love
 {
 namespace keyboard

+ 33 - 24
src/modules/native/tcc/wrap_Native.h → src/modules/mouse/Mouse.cpp

@@ -16,27 +16,36 @@
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
-**/
-
-#ifndef LOVE_NATIVE_TCC_WRAP_NATIVE_H
-#define LOVE_NATIVE_TCC_WRAP_NATIVE_H
-
-// LOVE
-#include <common/config.h>
-#include "Native.h"
-
-namespace love
-{
-namespace native
-{
-namespace tcc
-{
-	int w_compile(lua_State * L);
-	int w_getSymbol(lua_State * L);
-	extern "C" LOVE_EXPORT int luaopen_love_native(lua_State * L);
-
-} // tcc
-} // native
-} // love
-
-#endif // LOVE_NATIVE_TCC_WRAP_NATIVE_H
+**/
+
+#include "Mouse.h"
+
+namespace love
+{
+namespace mouse
+{
+	bool Mouse::getConstant(const char * in, Button & out)
+	{
+		return buttons.find(in, out);
+	}
+
+	bool Mouse::getConstant(Button in, const char *& out)
+	{
+		return buttons.find(in, out);
+	}
+
+	StringMap<Mouse::Button, Mouse::BUTTON_MAX_ENUM>::Entry Mouse::buttonEntries[] = 
+	{
+		{"l", Mouse::BUTTON_LEFT},
+		{"m", Mouse::BUTTON_MIDDLE},
+		{"r", Mouse::BUTTON_RIGHT},
+		{"wu", Mouse::BUTTON_WHEELUP},
+		{"wd", Mouse::BUTTON_WHEELDOWN},
+		{"x1", Mouse::BUTTON_X1},
+		{"x2", Mouse::BUTTON_X2},
+	};
+
+	StringMap<Mouse::Button, Mouse::BUTTON_MAX_ENUM> Mouse::buttons(Mouse::buttonEntries, sizeof(Mouse::buttonEntries));
+
+} // mouse
+} // love

+ 19 - 6
src/modules/mouse/Mouse.h

@@ -23,6 +23,7 @@
 
 // LOVE
 #include <common/Module.h>
+#include <common/StringMap.h>
 
 namespace love
 {
@@ -32,17 +33,29 @@ namespace mouse
 	{
 	public:
 		
-		enum MouseButton
+		enum Button
 		{
-			MOUSE_LEFT = 1,
-			MOUSE_MIDDLE, 
-			MOUSE_RIGHT,
-			MOUSE_WHEELUP,
-			MOUSE_WHEELDOWN
+			BUTTON_INVALID,
+			BUTTON_LEFT,
+			BUTTON_MIDDLE,
+			BUTTON_RIGHT,
+			BUTTON_WHEELUP,
+			BUTTON_WHEELDOWN,
+			BUTTON_X1,
+			BUTTON_X2,
+			BUTTON_MAX_ENUM
 		};
 
 		virtual ~Mouse(){};
 
+		static bool getConstant(const char * in, Button & out);
+		static bool getConstant(Button in, const char *& out);
+
+	private:
+
+		static StringMap<Button, BUTTON_MAX_ENUM>::Entry buttonEntries[];
+		static StringMap<Button, BUTTON_MAX_ENUM> buttons;
+
 	}; // Mouse
 
 } // mouse

+ 22 - 4
src/modules/mouse/sdl/Mouse.cpp

@@ -48,9 +48,9 @@ namespace sdl
 		return y;
 	}
 
-	void Mouse::getPosition(int * x, int * y) const
+	void Mouse::getPosition(int & x, int & y) const
 	{
-		SDL_GetMouseState(x, y);
+		SDL_GetMouseState(&x, &y);
 	}
 
 	void Mouse::setPosition(int x, int y)
@@ -63,9 +63,14 @@ namespace sdl
 		SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE);
 	}
 
-	bool Mouse::isDown(int button) const
+	bool Mouse::isDown(Button button) const
 	{
-		return (SDL_GetMouseState(0, 0) & SDL_BUTTON(button)) != 0;
+		unsigned b = 0;
+
+		if(!buttons.find(button, b))
+			return false;
+
+		return (SDL_GetMouseState(0, 0) & SDL_BUTTON(b)) != 0;
 	}
 
 	bool Mouse::isVisible() const
@@ -83,6 +88,19 @@ namespace sdl
 		return (SDL_WM_GrabInput(SDL_GRAB_QUERY) ==  SDL_GRAB_ON ? true : false);
 	}
 
+	EnumMap<Mouse::Button, unsigned, Mouse::BUTTON_MAX_ENUM>::Entry Mouse::buttonEntries[] = 
+	{
+		{ Mouse::BUTTON_LEFT, SDL_BUTTON_LEFT},
+		{ Mouse::BUTTON_MIDDLE, SDL_BUTTON_MIDDLE},
+		{ Mouse::BUTTON_RIGHT, SDL_BUTTON_RIGHT},
+		{ Mouse::BUTTON_WHEELUP, SDL_BUTTON_WHEELUP},
+		{ Mouse::BUTTON_WHEELDOWN, SDL_BUTTON_WHEELDOWN},
+		{ Mouse::BUTTON_X1, SDL_BUTTON_X1},
+		{ Mouse::BUTTON_X2, SDL_BUTTON_X2},
+	};
+
+	EnumMap<Mouse::Button, unsigned, Mouse::BUTTON_MAX_ENUM> Mouse::buttons(Mouse::buttonEntries, sizeof(Mouse::buttonEntries));
+
 } // sdl
 } // mouse
 } // love

+ 8 - 2
src/modules/mouse/sdl/Mouse.h

@@ -23,6 +23,7 @@
 
 // LOVE
 #include <mouse/Mouse.h>
+#include <common/EnumMap.h>
 
 namespace love
 {
@@ -39,14 +40,19 @@ namespace sdl
 		
 		int getX() const;
 		int getY() const;
-		void getPosition(int * x, int * y) const;
+		void getPosition(int & x, int & y) const;
 		void setPosition(int x, int y);
 		void setVisible(bool visible);
-		bool isDown(int button) const;
+		bool isDown(Button button) const;
 		bool isVisible() const;
 		void setGrab(bool grab);
 		bool isGrabbed() const;
 
+	public:
+
+		static EnumMap<Button, unsigned, BUTTON_MAX_ENUM>::Entry buttonEntries[];
+		static EnumMap<Button, unsigned, BUTTON_MAX_ENUM> buttons;
+
 	}; // Mouse
 
 } // sdl

+ 9 - 16
src/modules/mouse/sdl/wrap_Mouse.cpp

@@ -25,7 +25,7 @@ namespace love
 namespace mouse
 {
 namespace sdl
-{
+{
 	static Mouse * instance = 0;
 
 	int w_getX(lua_State * L)
@@ -43,7 +43,7 @@ namespace sdl
 	int w_getPosition(lua_State * L)
 	{
 		int x, y;
-		instance->getPosition(&x, &y);
+		instance->getPosition(x, y);
 		lua_pushinteger(L, x);
 		lua_pushinteger(L, y);
 		return 2;
@@ -59,8 +59,13 @@ namespace sdl
 
 	int w_isDown(lua_State * L)
 	{
-		int b = luaL_checkint(L, 1);
-		luax_pushboolean(L, instance->isDown(b));
+		Mouse::Button button;
+
+		if(!Mouse::getConstant(luaL_checkstring(L, 1), button))
+			luax_pushboolean(L, false);
+		else
+			luax_pushboolean(L, instance->isDown(button));
+
 		return 1;
 	}
 
@@ -104,17 +109,6 @@ namespace sdl
 		{ 0, 0 }
 	};
 
-	// List of constants.
-	static const Constant constants[] = {
-		{ "mouse_left", Mouse::MOUSE_LEFT },
-		{ "mouse_middle", Mouse::MOUSE_MIDDLE },
-		{ "mouse_right", Mouse::MOUSE_RIGHT },
-		{ "mouse_wheelup", Mouse::MOUSE_WHEELUP },
-		{ "mouse_wheeldown", Mouse::MOUSE_WHEELDOWN },
-		{ 0, 0 }
-	};
-
-
 	int luaopen_love_mouse(lua_State * L)
 	{
 		if(instance == 0)
@@ -135,7 +129,6 @@ namespace sdl
 		w.flags = MODULE_T;
 		w.functions = functions;
 		w.types = 0;
-		w.constants = constants;
 
 		return luax_register_module(L, w);
 	}

+ 0 - 162
src/modules/native/tcc/Native.cpp

@@ -1,162 +0,0 @@
-/**
-* Copyright (c) 2006-2009 LOVE Development Team
-* 
-* This software is provided 'as-is', without any express or implied
-* warranty.  In no event will the authors be held liable for any damages
-* arising from the use of this software.
-* 
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-* 
-* 1. The origin of this software must not be misrepresented; you must not
-*    claim that you wrote the original software. If you use this software
-*    in a product, an acknowledgment in the product documentation would be
-*    appreciated but is not required.
-* 2. Altered source versions must be plainly marked as such, and must not be
-*    misrepresented as being the original software.
-* 3. This notice may not be removed or altered from any source distribution.
-**/
-
-#include "Native.h"
-
-#include <cstring>
-#include <cstdlib>
-
-// The API which should be made available to TCC.
-#include "api.h"
-
-namespace love
-{
-namespace native
-{
-namespace tcc
-{
-
-	Compiler::Compiler()
-		: state(0), buffer(0)
-	{
-		state = tcc_new();
-
-		if(!state) 
-		{
-			throw love::Exception("Could not create TCC state.");
-		}
-
-		tcc_set_output_type(state, TCC_OUTPUT_MEMORY);
-
-		// Add APIs here.
-		for(const tcc_function * f = tcc_api; (*f).name != 0; f++)
-		{
-			tcc_add_symbol(state, (*f).name, (*f).fn);
-		}
-	}
-
-	Compiler::~Compiler()
-	{
-		if(state != 0)
-			tcc_delete(state);
-
-		if(buffer != 0)
-			free(buffer);
-	}
-
-	bool Compiler::compile(const char ** str, int size)
-	{
-		if(state == 0)
-			return false;
-
-		for(int i =0; i<size; i++)
-		{
-			if (tcc_compile_string(state, str[i]) == -1)
-				return false;
-		}
-
-		if(!relocate())
-			return false;
-
-		return true;
-	}
-
-	bool Compiler::relocate()
-	{
-		if(state == 0)
-			return false;
-
-		int size = tcc_relocate(state, 0);
-
-		if(size == -1)
-			return false;
-
-		buffer = malloc(size);
-
-		if(buffer == 0)
-			return false;
-
-		if(tcc_relocate(state, buffer) == -1)
-		{
-			free(buffer);
-			buffer = 0;
-			return false;
-		}
-
-		return true;
-	}
-
-	void * Compiler::getSymbol(const char * sym)
-	{
-		if(state == 0)
-			return 0;
-
-		return tcc_get_symbol(state, sym);
-	}
-
-
-	Native::Native()
-	{
-	}
-
-	Native::~Native()
-	{
-		for(int i = 0; i<(int)compilers.size(); i++)
-			delete compilers[i];
-	}
-
-	const char * Native::getName() const
-	{
-		return "love.native.tcc";
-	}
-
-	bool Native::compile(const char ** str, int size)
-	{
-		// Create a new compiler.
-		Compiler * c = new Compiler();
-
-		// Compile the code.
-		if(!c->compile(str, size))
-		{
-			delete c;
-			return false;
-		}
-
-		compilers.push_back(c);
-
-		return true;
-	}
-
-	void * Native::getSymbol(const char * sym)
-	{
-		for(int i = 0; i<(int)compilers.size(); i++)
-		{
-			void * s = compilers[i]->getSymbol(sym);
-
-			if(s != 0)
-				return s;
-		}
-
-		return 0;
-	}
-
-} // tcc
-} // native
-} // love

+ 0 - 99
src/modules/native/tcc/Native.h

@@ -1,99 +0,0 @@
-/**
-* Copyright (c) 2006-2009 LOVE Development Team
-* 
-* This software is provided 'as-is', without any express or implied
-* warranty.  In no event will the authors be held liable for any damages
-* arising from the use of this software.
-* 
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-* 
-* 1. The origin of this software must not be misrepresented; you must not
-*    claim that you wrote the original software. If you use this software
-*    in a product, an acknowledgment in the product documentation would be
-*    appreciated but is not required.
-* 2. Altered source versions must be plainly marked as such, and must not be
-*    misrepresented as being the original software.
-* 3. This notice may not be removed or altered from any source distribution.
-**/
-
-#ifndef LOVE_NATIVE_TCC_NATIVE_H
-#define LOVE_NATIVE_TCC_NATIVE_H
-
-// C++
-#include <vector>
-
-// tcc
-#include "libtcc/libtcc.h"
-
-// LOVE
-#include <common/Module.h>
-
-namespace love
-{
-namespace native
-{
-namespace tcc
-{
-
-	class Compiler
-	{
-		friend class Native;
-	private:
-		TCCState * state;
-		void * buffer;
-	public:
-		Compiler();
-		~Compiler();
-
-
-		bool compile(const char ** str, int size);
-
-		void * getSymbol(const char * sym);
-
-	private:
-		bool relocate();
-	};
-
-	class Native : public Module
-	{
-	private:
-
-		std::vector<Compiler *> compilers;		
-
-	public:
-
-		/**
-		* Constructor.
-		**/
-		Native();
-
-		/**
-		* Destructor.
-		**/
-		~Native();
-
-		/**
-		* Gets the name of the module.
-		* @return Always returns "love.native.tcc".
-		**/
-		const char * getName() const;
-
-		/**
-		* Compile an array of strings in order, and relocate.
-		* @param The array of strings to compile. 
-		* @param The number of strings to compile.
-		* @return True on success, false otherwise.
-		**/
-		bool compile(const char ** str, int size);
-
-		void * getSymbol(const char * sym);
-
-	}; // Native
-
-} // tcc
-} // native
-} // love
-
-#endif // LOVE_NATIVE_TCC_NATIVE_H

+ 0 - 113
src/modules/native/tcc/api.c

@@ -1,113 +0,0 @@
-/**
-* Copyright (c) 2006-2009 LOVE Development Team
-* 
-* This software is provided 'as-is', without any express or implied
-* warranty.  In no event will the authors be held liable for any damages
-* arising from the use of this software.
-* 
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-* 
-* 1. The origin of this software must not be misrepresented; you must not
-*    claim that you wrote the original software. If you use this software
-*    in a product, an acknowledgment in the product documentation would be
-*    appreciated but is not required.
-* 2. Altered source versions must be plainly marked as such, and must not be
-*    misrepresented as being the original software.
-* 3. This notice may not be removed or altered from any source distribution.
-**/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "api.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-// Lua
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
-
-/* 
-* MSVC did not require that every funtion be
-* cast to (void*), but gcc did. Ah well, this
-* is shorter than {"funcname", funcname} anyway.
-*/
-#define FVOID(f) { #f, (void*)f }
-
-const tcc_function tcc_api[] =
-{
-
-	// cstring
-	FVOID(memcpy),
-	FVOID(memmove),
-	FVOID(strcpy),
-	FVOID(strncpy),
-	FVOID(strcat),
-	FVOID(strncat),
-	FVOID(memcmp),
-	FVOID(strcmp),
-	FVOID(strcoll),
-	FVOID(strncmp),
-	FVOID(strxfrm),
-	FVOID(memchr),
-	FVOID(strchr),
-	FVOID(strcspn),
-	FVOID(strpbrk),
-	FVOID(strrchr),
-	FVOID(strspn),
-	FVOID(strstr),
-	FVOID(strtok),
-	FVOID(memset),
-	FVOID(strerror),
-	FVOID(strlen),
-
-	// Lua (some of it)
-	FVOID(lua_isnumber),
-	FVOID(lua_isstring),
-	FVOID(lua_iscfunction),
-	FVOID(lua_isuserdata),
-	FVOID(lua_type),
-	FVOID(lua_typename),
-
-	FVOID(lua_equal),
-	FVOID(lua_rawequal),
-	FVOID(lua_lessthan),
-
-	FVOID(lua_tonumber),
-	FVOID(lua_tointeger),
-	FVOID(lua_toboolean),
-	FVOID(lua_tolstring),
-	FVOID(lua_objlen),
-	FVOID(lua_tocfunction),
-	FVOID(lua_touserdata),
-	FVOID(lua_tothread),
-	FVOID(lua_topointer),
-
-	FVOID(lua_pushnil),
-	FVOID(lua_pushnumber),
-	FVOID(lua_pushinteger),
-	FVOID(lua_pushlstring),
-	FVOID(lua_pushstring),
-	FVOID(lua_pushvfstring),
-
-	FVOID(lua_pushfstring),
-	FVOID(lua_pushcclosure),
-	FVOID(lua_pushboolean),
-	FVOID(lua_pushlightuserdata),
-	FVOID(lua_pushthread),
-
-	FVOID(luaL_register),
-	FVOID(luaL_error),
-
-	// End
-	{ 0, 0 }
-};
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 1734
src/modules/native/tcc/libtcc/arm-gen.c

@@ -1,1734 +0,0 @@
-/*
- *  ARMv4 code generator for TCC
- * 
- *  Copyright (c) 2003 Daniel Glöckner
- *
- *  Based on i386-gen.c by Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifdef TCC_ARM_EABI
-#define TCC_ARM_VFP
-#endif
-
-
-/* number of available registers */
-#ifdef TCC_ARM_VFP
-#define NB_REGS            13
-#else
-#define NB_REGS             9
-#endif
-
-/* a register can belong to several classes. The classes must be
-   sorted from more general to more precise (see gv2() code which does
-   assumptions on it). */
-#define RC_INT     0x0001 /* generic integer register */
-#define RC_FLOAT   0x0002 /* generic float register */
-#define RC_R0      0x0004
-#define RC_R1      0x0008 
-#define RC_R2      0x0010
-#define RC_R3      0x0020
-#define RC_R12     0x0040
-#define RC_F0      0x0080
-#define RC_F1      0x0100
-#define RC_F2      0x0200
-#define RC_F3      0x0400
-#ifdef TCC_ARM_VFP
-#define RC_F4      0x0800
-#define RC_F5      0x1000
-#define RC_F6      0x2000
-#define RC_F7      0x4000
-#endif
-#define RC_IRET    RC_R0  /* function return: integer register */
-#define RC_LRET    RC_R1  /* function return: second integer register */
-#define RC_FRET    RC_F0  /* function return: float register */
-
-/* pretty names for the registers */
-enum {
-    TREG_R0 = 0,
-    TREG_R1,
-    TREG_R2,
-    TREG_R3,
-    TREG_R12,
-    TREG_F0,
-    TREG_F1,
-    TREG_F2,
-    TREG_F3,
-#ifdef TCC_ARM_VFP
-    TREG_F4,
-    TREG_F5,
-    TREG_F6,
-    TREG_F7,
-#endif
-};
-
-int reg_classes[NB_REGS] = {
-    /* r0 */ RC_INT | RC_R0,
-    /* r1 */ RC_INT | RC_R1,
-    /* r2 */ RC_INT | RC_R2,
-    /* r3 */ RC_INT | RC_R3,
-    /* r12 */ RC_INT | RC_R12,
-    /* f0 */ RC_FLOAT | RC_F0,
-    /* f1 */ RC_FLOAT | RC_F1,
-    /* f2 */ RC_FLOAT | RC_F2,
-    /* f3 */ RC_FLOAT | RC_F3,
-#ifdef TCC_ARM_VFP
- /* d4/s8 */ RC_FLOAT | RC_F4,
-/* d5/s10 */ RC_FLOAT | RC_F5,
-/* d6/s12 */ RC_FLOAT | RC_F6,
-/* d7/s14 */ RC_FLOAT | RC_F7,
-#endif
-};
-
-static int two2mask(int a,int b) {
-  return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);
-}
-
-static int regmask(int r) {
-  return reg_classes[r]&~(RC_INT|RC_FLOAT);
-}
-
-#ifdef TCC_ARM_VFP
-#define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0)
-#endif
-
-/* return registers for function */
-#define REG_IRET TREG_R0 /* single word int return register */
-#define REG_LRET TREG_R1 /* second word return register (for long long) */
-#define REG_FRET TREG_F0 /* float return register */
-
-#ifdef TCC_ARM_EABI
-#define TOK___divdi3 TOK___aeabi_ldivmod
-#define TOK___moddi3 TOK___aeabi_ldivmod
-#define TOK___udivdi3 TOK___aeabi_uldivmod
-#define TOK___umoddi3 TOK___aeabi_uldivmod
-#endif
-
-/* defined if function parameters must be evaluated in reverse order */
-#define INVERT_FUNC_PARAMS
-
-/* defined if structures are passed as pointers. Otherwise structures
-   are directly pushed on stack. */
-//#define FUNC_STRUCT_PARAM_AS_PTR
-
-#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
-static CType float_type, double_type, func_float_type, func_double_type;
-#define func_ldouble_type func_double_type
-#else
-#define func_float_type func_old_type
-#define func_double_type func_old_type
-#define func_ldouble_type func_old_type
-#endif
-
-/* pointer size, in bytes */
-#define PTR_SIZE 4
-
-/* long double size and alignment, in bytes */
-#ifdef TCC_ARM_VFP
-#define LDOUBLE_SIZE  8
-#endif
-
-#ifndef LDOUBLE_SIZE
-#define LDOUBLE_SIZE  8
-#endif
-
-#ifdef TCC_ARM_EABI
-#define LDOUBLE_ALIGN 8
-#else
-#define LDOUBLE_ALIGN 4
-#endif
-
-/* maximum alignment (for aligned attribute support) */
-#define MAX_ALIGN     8
-
-#define CHAR_IS_UNSIGNED
-
-/******************************************************/
-/* ELF defines */
-
-#define EM_TCC_TARGET EM_ARM
-
-/* relocation type for 32 bit data relocation */
-#define R_DATA_32   R_ARM_ABS32
-#define R_JMP_SLOT  R_ARM_JUMP_SLOT
-#define R_COPY      R_ARM_COPY
-
-#define ELF_START_ADDR 0x00008000
-#define ELF_PAGE_SIZE  0x1000
-
-/******************************************************/
-static unsigned long func_sub_sp_offset,last_itod_magic;
-static int leaffunc;
-
-void o(unsigned long i)
-{
-  /* this is a good place to start adding big-endian support*/
-  int ind1;
-
-  ind1 = ind + 4;
-  if (!cur_text_section)
-    error("compiler error! This happens f.ex. if the compiler\n"
-         "can't evaluate constant expressions outside of a function.");
-  if (ind1 > cur_text_section->data_allocated)
-    section_realloc(cur_text_section, ind1);
-  cur_text_section->data[ind++] = i&255;
-  i>>=8;
-  cur_text_section->data[ind++] = i&255;
-  i>>=8; 
-  cur_text_section->data[ind++] = i&255;
-  i>>=8;
-  cur_text_section->data[ind++] = i;
-}
-
-static unsigned long stuff_const(unsigned long op,unsigned long c)
-{
-  int try_neg=0;
-  unsigned long nc = 0,negop = 0;
-
-  switch(op&0x1F00000)
-  {
-    case 0x800000: //add
-    case 0x400000: //sub
-      try_neg=1;
-      negop=op^0xC00000;
-      nc=-c;
-      break;
-    case 0x1A00000: //mov
-    case 0x1E00000: //mvn
-      try_neg=1;
-      negop=op^0x400000;
-      nc=~c;
-      break;
-    case 0x200000: //xor
-      if(c==~0)
-	return (op&0xF010F000)|((op>>16)&0xF)|0x1E00000;
-      break;
-    case 0x0: //and
-      if(c==~0)
-	return (op&0xF010F000)|((op>>16)&0xF)|0x1A00000;
-    case 0x1C00000: //bic
-      try_neg=1;
-      negop=op^0x1C00000;
-      nc=~c;
-      break;
-    case 0x1800000: //orr
-      if(c==~0)
-	return (op&0xFFF0FFFF)|0x1E00000;
-      break;
-  }
-  do {
-    unsigned long m;
-    int i;
-    if(c<256) /* catch undefined <<32 */
-      return op|c;
-    for(i=2;i<32;i+=2) {
-      m=(0xff>>i)|(0xff<<(32-i));
-      if(!(c&~m))
-	return op|(i<<7)|(c<<i)|(c>>(32-i));
-    }
-    op=negop;
-    c=nc;
-  } while(try_neg--);
-  return 0;
-}
-
-
-//only add,sub
-void stuff_const_harder(unsigned long op,unsigned long v) {
-  unsigned long x;
-  x=stuff_const(op,v);
-  if(x)
-    o(x);
-  else {
-    unsigned long a[16],nv,no,o2,n2;
-    int i,j,k;
-    a[0]=0xff;
-    o2=(op&0xfff0ffff)|((op&0xf000)<<4);;
-    for(i=1;i<16;i++)
-      a[i]=(a[i-1]>>2)|(a[i-1]<<30);
-    for(i=0;i<12;i++)
-      for(j=i<4?i+12:15;j>=i+4;j--)
-	if((v&(a[i]|a[j]))==v) {
-	  o(stuff_const(op,v&a[i]));
-	  o(stuff_const(o2,v&a[j]));
-	  return;
-	}
-    no=op^0xC00000;
-    n2=o2^0xC00000;
-    nv=-v;
-    for(i=0;i<12;i++)
-      for(j=i<4?i+12:15;j>=i+4;j--)
-	if((nv&(a[i]|a[j]))==nv) {
-	  o(stuff_const(no,nv&a[i]));
-	  o(stuff_const(n2,nv&a[j]));
-	  return;
-	}
-    for(i=0;i<8;i++)
-      for(j=i+4;j<12;j++)
-	for(k=i<4?i+12:15;k>=j+4;k--)
-	  if((v&(a[i]|a[j]|a[k]))==v) {
-	    o(stuff_const(op,v&a[i]));
-	    o(stuff_const(o2,v&a[j]));
-	    o(stuff_const(o2,v&a[k]));
-	    return;
-	  }
-    no=op^0xC00000;
-    nv=-v;
-    for(i=0;i<8;i++)
-      for(j=i+4;j<12;j++)
-	for(k=i<4?i+12:15;k>=j+4;k--)
-	  if((nv&(a[i]|a[j]|a[k]))==nv) {
-	    o(stuff_const(no,nv&a[i]));
-	    o(stuff_const(n2,nv&a[j]));
-	    o(stuff_const(n2,nv&a[k]));
-	    return;
-	  }
-    o(stuff_const(op,v&a[0]));
-    o(stuff_const(o2,v&a[4]));
-    o(stuff_const(o2,v&a[8]));
-    o(stuff_const(o2,v&a[12]));
-  }
-}
-
-unsigned long encbranch(int pos,int addr,int fail)
-{
-  addr-=pos+8;
-  addr/=4;
-  if(addr>=0x1000000 || addr<-0x1000000) {
-    if(fail)
-      error("FIXME: function bigger than 32MB");
-    return 0;
-  }
-  return 0x0A000000|(addr&0xffffff);
-}
-
-int decbranch(int pos)
-{
-  int x;
-  x=*(int *)(cur_text_section->data + pos);
-  x&=0x00ffffff;
-  if(x&0x800000)
-    x-=0x1000000;
-  return x*4+pos+8;
-}
-
-/* output a symbol and patch all calls to it */
-void gsym_addr(int t, int a)
-{
-  unsigned long *x;
-  int lt;
-  while(t) {
-    x=(unsigned long *)(cur_text_section->data + t);
-    t=decbranch(lt=t);
-    if(a==lt+4)
-      *x=0xE1A00000; // nop
-    else {
-      *x &= 0xff000000;
-      *x |= encbranch(lt,a,1);
-    }
-  }
-}
-
-void gsym(int t)
-{
-  gsym_addr(t, ind);
-}
-
-#ifdef TCC_ARM_VFP
-static unsigned long vfpr(int r)
-{
-  if(r<TREG_F0 || r>TREG_F7)
-    error("compiler error! register %i is no vfp register",r);
-  return r-5;
-}
-#else
-static unsigned long fpr(int r)
-{
-  if(r<TREG_F0 || r>TREG_F3)
-    error("compiler error! register %i is no fpa register",r);
-  return r-5;
-}
-#endif
-
-static unsigned long intr(int r)
-{
-  if(r==4)
-    return 12;
-  if((r<0 || r>4) && r!=14)
-    error("compiler error! register %i is no int register",r);
-  return r;
-}
-
-static void calcaddr(unsigned long *base,int *off,int *sgn,int maxoff,unsigned shift)
-{
-  if(*off>maxoff || *off&((1<<shift)-1)) {
-    unsigned long x,y;
-    x=0xE280E000;
-    if(*sgn)
-      x=0xE240E000;
-    x|=(*base)<<16;
-    *base=14; // lr
-    y=stuff_const(x,*off&~maxoff);
-    if(y) {
-      o(y);
-      *off&=maxoff;
-      return;
-    }
-    y=stuff_const(x,(*off+maxoff)&~maxoff);
-    if(y) {
-      o(y);
-      *sgn=!*sgn;
-      *off=((*off+maxoff)&~maxoff)-*off;
-      return;
-    }
-    stuff_const_harder(x,*off&~maxoff);
-    *off&=maxoff;
-  }
-}
-
-static unsigned long mapcc(int cc)
-{
-  switch(cc)
-  {
-    case TOK_ULT:
-      return 0x30000000; /* CC/LO */
-    case TOK_UGE:
-      return 0x20000000; /* CS/HS */
-    case TOK_EQ:
-      return 0x00000000; /* EQ */
-    case TOK_NE:
-      return 0x10000000; /* NE */
-    case TOK_ULE:
-      return 0x90000000; /* LS */
-    case TOK_UGT:
-      return 0x80000000; /* HI */
-    case TOK_Nset:
-      return 0x40000000; /* MI */
-    case TOK_Nclear:
-      return 0x50000000; /* PL */
-    case TOK_LT:
-      return 0xB0000000; /* LT */
-    case TOK_GE:
-      return 0xA0000000; /* GE */
-    case TOK_LE:
-      return 0xD0000000; /* LE */
-    case TOK_GT:
-      return 0xC0000000; /* GT */
-  }
-  error("unexpected condition code");
-  return 0xE0000000; /* AL */
-}
-
-static int negcc(int cc)
-{
-  switch(cc)
-  {
-    case TOK_ULT:
-      return TOK_UGE;
-    case TOK_UGE:
-      return TOK_ULT;
-    case TOK_EQ:
-      return TOK_NE;
-    case TOK_NE:
-      return TOK_EQ;
-    case TOK_ULE:
-      return TOK_UGT;
-    case TOK_UGT:
-      return TOK_ULE;
-    case TOK_Nset:
-      return TOK_Nclear;
-    case TOK_Nclear:
-      return TOK_Nset;
-    case TOK_LT:
-      return TOK_GE;
-    case TOK_GE:
-      return TOK_LT;
-    case TOK_LE:
-      return TOK_GT;
-    case TOK_GT:
-      return TOK_LE;
-  }
-  error("unexpected condition code");
-  return TOK_NE;
-}
-
-/* load 'r' from value 'sv' */
-void load(int r, SValue *sv)
-{
-  int v, ft, fc, fr, sign;
-  unsigned long op;
-  SValue v1;
-
-  fr = sv->r;
-  ft = sv->type.t;
-  fc = sv->c.ul;
-
-  if(fc>=0)
-    sign=0;
-  else {
-    sign=1;
-    fc=-fc;
-  }
-  
-  v = fr & VT_VALMASK;
-  if (fr & VT_LVAL) {
-    unsigned long base=0xB; // fp
-    if(v == VT_LLOCAL) {
-      v1.type.t = VT_PTR;
-      v1.r = VT_LOCAL | VT_LVAL;
-      v1.c.ul = sv->c.ul;
-      load(base=14 /* lr */, &v1);
-      fc=sign=0;
-      v=VT_LOCAL;
-    } else if(v == VT_CONST) {
-      v1.type.t = VT_PTR;
-      v1.r = fr&~VT_LVAL;
-      v1.c.ul = sv->c.ul;
-      v1.sym=sv->sym;
-      load(base=14, &v1);
-      fc=sign=0;
-      v=VT_LOCAL;
-    } else if(v < VT_CONST) {
-      base=intr(v);
-      fc=sign=0;
-      v=VT_LOCAL;
-    }
-    if(v == VT_LOCAL) {
-      if(is_float(ft)) {
-	calcaddr(&base,&fc,&sign,1020,2);
-#ifdef TCC_ARM_VFP
-        op=0xED100A00; /* flds */
-        if(!sign)
-          op|=0x800000;
-        if ((ft & VT_BTYPE) != VT_FLOAT)
-          op|=0x100;   /* flds -> fldd */
-        o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
-#else
-	op=0xED100100;
-	if(!sign)
-	  op|=0x800000;
-#if LDOUBLE_SIZE == 8
-	if ((ft & VT_BTYPE) != VT_FLOAT)
-	  op|=0x8000;
-#else
-	if ((ft & VT_BTYPE) == VT_DOUBLE)
-	  op|=0x8000;
-	else if ((ft & VT_BTYPE) == VT_LDOUBLE)
-	  op|=0x400000;
-#endif
-	o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
-#endif
-      } else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE
-                || (ft & VT_BTYPE) == VT_SHORT) {
-	calcaddr(&base,&fc,&sign,255,0);
-	op=0xE1500090;
-	if ((ft & VT_BTYPE) == VT_SHORT)
-	  op|=0x20;
-	if ((ft & VT_UNSIGNED) == 0)
-	  op|=0x40;
-	if(!sign)
-	  op|=0x800000;
-	o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));
-      } else {
-	calcaddr(&base,&fc,&sign,4095,0);
-	op=0xE5100000;
-	if(!sign)
-	  op|=0x800000;
-        if ((ft & VT_BTYPE) == VT_BYTE)
-          op|=0x400000;
-        o(op|(intr(r)<<12)|fc|(base<<16));
-      }
-      return;
-    }
-  } else {
-    if (v == VT_CONST) {
-      op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.ul);
-      if (fr & VT_SYM || !op) {
-        o(0xE59F0000|(intr(r)<<12));
-        o(0xEA000000);
-        if(fr & VT_SYM)
-	  greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
-        o(sv->c.ul);
-      } else
-        o(op);
-      return;
-    } else if (v == VT_LOCAL) {
-      op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.ul);
-      if (fr & VT_SYM || !op) {
-	o(0xE59F0000|(intr(r)<<12));
-	o(0xEA000000);
-	if(fr & VT_SYM) // needed ?
-	  greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
-	o(sv->c.ul);
-	o(0xE08B0000|(intr(r)<<12)|intr(r));
-      } else
-	o(op);
-      return;
-    } else if(v == VT_CMP) {
-      o(mapcc(sv->c.ul)|0x3A00001|(intr(r)<<12));
-      o(mapcc(negcc(sv->c.ul))|0x3A00000|(intr(r)<<12));
-      return;
-    } else if (v == VT_JMP || v == VT_JMPI) {
-      int t;
-      t = v & 1;
-      o(0xE3A00000|(intr(r)<<12)|t);
-      o(0xEA000000);
-      gsym(sv->c.ul);
-      o(0xE3A00000|(intr(r)<<12)|(t^1));
-      return;
-    } else if (v < VT_CONST) {
-      if(is_float(ft))
-#ifdef TCC_ARM_VFP
-        o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */
-#else
-	o(0xEE008180|(fpr(r)<<12)|fpr(v));
-#endif
-      else
-	o(0xE1A00000|(intr(r)<<12)|intr(v));
-      return;
-    }
-  }
-  error("load unimplemented!");
-}
-
-/* store register 'r' in lvalue 'v' */
-void store(int r, SValue *sv)
-{
-  SValue v1;
-  int v, ft, fc, fr, sign;
-  unsigned long op;
-
-  fr = sv->r;
-  ft = sv->type.t;
-  fc = sv->c.ul;
-
-  if(fc>=0)
-    sign=0;
-  else {
-    sign=1;
-    fc=-fc;
-  }
-  
-  v = fr & VT_VALMASK; 
-  if (fr & VT_LVAL || fr == VT_LOCAL) {
-    unsigned long base=0xb;
-    if(v < VT_CONST) {
-      base=intr(v);
-      v=VT_LOCAL;
-      fc=sign=0;
-    } else if(v == VT_CONST) {
-      v1.type.t = ft;
-      v1.r = fr&~VT_LVAL;
-      v1.c.ul = sv->c.ul;
-      v1.sym=sv->sym;
-      load(base=14, &v1);
-      fc=sign=0;
-      v=VT_LOCAL;   
-    }
-    if(v == VT_LOCAL) {
-       if(is_float(ft)) {
-	calcaddr(&base,&fc,&sign,1020,2);
-#ifdef TCC_ARM_VFP
-        op=0xED000A00; /* fsts */
-        if(!sign) 
-          op|=0x800000; 
-        if ((ft & VT_BTYPE) != VT_FLOAT) 
-          op|=0x100;   /* fsts -> fstd */
-        o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
-#else
-	op=0xED000100;
-	if(!sign)
-	  op|=0x800000;
-#if LDOUBLE_SIZE == 8
-	if ((ft & VT_BTYPE) != VT_FLOAT)
-	  op|=0x8000;
-#else
-	if ((ft & VT_BTYPE) == VT_DOUBLE)
-	  op|=0x8000;
-	if ((ft & VT_BTYPE) == VT_LDOUBLE)
-	  op|=0x400000;
-#endif
-	o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
-#endif
-	return;
-      } else if((ft & VT_BTYPE) == VT_SHORT) {
-	calcaddr(&base,&fc,&sign,255,0);
-	op=0xE14000B0;
-	if(!sign)
-	  op|=0x800000;
-	o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));
-      } else {
-	calcaddr(&base,&fc,&sign,4095,0);
-	op=0xE5000000;
-	if(!sign)
-	  op|=0x800000;
-        if ((ft & VT_BTYPE) == VT_BYTE)
-          op|=0x400000;
-        o(op|(intr(r)<<12)|fc|(base<<16));
-      }
-      return;
-    }
-  }
-  error("store unimplemented");
-}
-
-static void gadd_sp(int val)
-{
-  stuff_const_harder(0xE28DD000,val);
-}
-
-/* 'is_jmp' is '1' if it is a jump */
-static void gcall_or_jmp(int is_jmp)
-{
-  int r;
-  if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
-    unsigned long x;
-    /* constant case */
-    x=encbranch(ind,ind+vtop->c.ul,0);
-    if(x) {
-      if (vtop->r & VT_SYM) {
-	/* relocation case */
-	greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);
-      } else
-	put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, 0);
-      o(x|(is_jmp?0xE0000000:0xE1000000));
-    } else {
-      if(!is_jmp)
-	o(0xE28FE004); // add lr,pc,#4
-      o(0xE51FF004);   // ldr pc,[pc,#-4]
-      if (vtop->r & VT_SYM)
-	greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
-      o(vtop->c.ul);
-    }
-  } else {
-    /* otherwise, indirect call */
-    r = gv(RC_INT);
-    if(!is_jmp)
-      o(0xE1A0E00F);       // mov lr,pc
-    o(0xE1A0F000|intr(r)); // mov pc,r
-  }
-}
-
-/* Generate function call. The function address is pushed first, then
-   all the parameters in call order. This functions pops all the
-   parameters and the function address. */
-void gfunc_call(int nb_args)
-{
-  int size, align, r, args_size, i;
-  Sym *func_sym;
-  signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
-  int todo=0xf, keep, plan2[4]={0,0,0,0};
-
-  r = vtop->r & VT_VALMASK;
-  if (r == VT_CMP || (r & ~1) == VT_JMP)
-    gv(RC_INT);
-#ifdef TCC_ARM_EABI
-  if((vtop[-nb_args].type.ref->type.t & VT_BTYPE) == VT_STRUCT
-     && type_size(&vtop[-nb_args].type, &align) <= 4) {
-    SValue tmp;
-    tmp=vtop[-nb_args];
-    vtop[-nb_args]=vtop[-nb_args+1];
-    vtop[-nb_args+1]=tmp;
-    --nb_args;
-  }
-  
-  vpushi(0);
-  vtop->type.t = VT_LLONG;
-  args_size = 0;
-  for(i = nb_args + 1 ; i-- ;) {
-    size = type_size(&vtop[-i].type, &align);
-    if(args_size & (align-1)) {
-      vpushi(0);
-      vtop->type.t = VT_VOID; /* padding */
-      vrott(i+2);
-      args_size += 4;
-      ++nb_args;
-    }
-    args_size += (size + 3) & -4;
-  }
-  vtop--;
-#endif
-  args_size = 0;
-  for(i = nb_args ; i-- && args_size < 16 ;) {
-    switch(vtop[-i].type.t & VT_BTYPE) {
-      case VT_STRUCT:
-      case VT_FLOAT:
-      case VT_DOUBLE:
-      case VT_LDOUBLE:
-      size = type_size(&vtop[-i].type, &align);
-        size = (size + 3) & -4;
-      args_size += size;
-        break;
-      default:
-      plan[nb_args-1-i][0]=args_size/4;
-      args_size += 4;
-      if ((vtop[-i].type.t & VT_BTYPE) == VT_LLONG && args_size < 16) {
-	plan[nb_args-1-i][1]=args_size/4;
-	args_size += 4;
-      }
-    }
-  }
-  args_size = keep = 0;
-  for(i = 0;i < nb_args; i++) {
-    vnrott(keep+1);
-    if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
-      size = type_size(&vtop->type, &align);
-      /* align to stack align size */
-      size = (size + 3) & -4;
-      /* allocate the necessary size on stack */
-      gadd_sp(-size);
-      /* generate structure store */
-      r = get_reg(RC_INT);
-      o(0xE1A0000D|(intr(r)<<12));
-      vset(&vtop->type, r | VT_LVAL, 0);
-      vswap();
-      vstore();
-      vtop--;
-      args_size += size;
-    } else if (is_float(vtop->type.t)) {
-#ifdef TCC_ARM_VFP
-      r=vfpr(gv(RC_FLOAT))<<12;
-      size=4;
-      if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)
-      {
-        size=8;
-        r|=0x101; /* fstms -> fstmd */
-      }
-      o(0xED2D0A01+r);
-#else
-      r=fpr(gv(RC_FLOAT))<<12;
-      if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
-        size = 4;
-      else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
-        size = 8;
-      else
-        size = LDOUBLE_SIZE;
-      
-      if (size == 12)
-	r|=0x400000;
-      else if(size == 8)
-	r|=0x8000;
-
-      o(0xED2D0100|r|(size>>2));
-#endif
-      vtop--;
-      args_size += size;
-    } else {
-      int s;
-      /* simple type (currently always same size) */
-      /* XXX: implicit cast ? */
-      size=4;
-      if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
-	lexpand_nr();
-	s=RC_INT;
-	if(nb_args-i<5 && plan[nb_args-i-1][1]!=-1) {
-	  s=regmask(plan[nb_args-i-1][1]);
-	  todo&=~(1<<plan[nb_args-i-1][1]);
-	}
-	if(s==RC_INT) {
-	  r = gv(s);
-	  o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
-	  vtop--;
-	} else {
-	  plan2[keep]=s;
-	  keep++;
-          vswap();
-	}
-	size = 8;
-      }
-      s=RC_INT;
-      if(nb_args-i<5 && plan[nb_args-i-1][0]!=-1) {
-        s=regmask(plan[nb_args-i-1][0]);
-	todo&=~(1<<plan[nb_args-i-1][0]);
-      }
-#ifdef TCC_ARM_EABI
-      if(vtop->type.t == VT_VOID) {
-        if(s == RC_INT)
-          o(0xE24DD004); /* sub sp,sp,#4 */
-        vtop--;
-      } else
-#endif      
-      if(s == RC_INT) {
-	r = gv(s);
-	o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
-	vtop--;
-      } else {
-	plan2[keep]=s;
-	keep++;
-      }
-      args_size += size;
-    }
-  }
-  for(i=keep;i--;) {
-    gv(plan2[i]);
-    vrott(keep);
-  }
-save_regs(keep); /* save used temporary registers */
-  keep++;
-  if(args_size) {
-    int n;
-    n=args_size/4;
-    if(n>4)
-      n=4;
-    todo&=((1<<n)-1);
-    if(todo) {
-      int i;
-      o(0xE8BD0000|todo);
-      for(i=0;i<4;i++)
-	if(todo&(1<<i)) {
-	  vpushi(0);
-	  vtop->r=i;
-	  keep++;
-	}
-    }
-    args_size-=n*4;
-  }
-  vnrott(keep);
-  func_sym = vtop->type.ref;
-  gcall_or_jmp(0);
-  if (args_size)
-      gadd_sp(args_size);
-#ifdef TCC_ARM_EABI
-  if((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT
-     && type_size(&vtop->type.ref->type, &align) <= 4)
-  {
-    store(REG_IRET,vtop-keep);
-    ++keep;
-  }
-#ifdef TCC_ARM_VFP
-  else if(is_float(vtop->type.ref->type.t)) {
-    if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {
-      o(0xEE000A10); /* fmsr s0,r0 */
-    } else {
-      o(0xEE000B10); /* fmdlr d0,r0 */
-      o(0xEE201B10); /* fmdhr d0,r1 */
-    }
-  }
-#endif
-#endif
-  vtop-=keep;
-  leaffunc = 0;
-}
-
-/* generate function prolog of type 't' */
-void gfunc_prolog(CType *func_type)
-{
-  Sym *sym,*sym2;
-  int n,addr,size,align;
-
-  sym = func_type->ref;
-  func_vt = sym->type;
-  
-  n = 0;
-  addr = 0;
-  if((func_vt.t & VT_BTYPE) == VT_STRUCT
-     && type_size(&func_vt,&align) > 4)
-  {
-    func_vc = addr;
-    addr += 4;
-    n++;
-  }
-  for(sym2=sym->next;sym2 && n<4;sym2=sym2->next) {
-    size = type_size(&sym2->type, &align);
-    n += (size + 3) / 4;
-  }
-  o(0xE1A0C00D); /* mov ip,sp */
-  if(func_type->ref->c == FUNC_ELLIPSIS)
-    n=4;
-  if(n) {
-    if(n>4)
-      n=4;
-#ifdef TCC_ARM_EABI
-    n=(n+1)&-2;
-#endif
-    o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */
-  }
-  o(0xE92D5800); /* save fp, ip, lr */
-  o(0xE28DB00C); /* add fp, sp, #12 */
-  func_sub_sp_offset = ind;
-  o(0xE1A00000); /* nop, leave space for stack adjustment */
-  while ((sym = sym->next)) {
-    CType *type;
-    type = &sym->type;
-    size = type_size(type, &align);
-    size = (size + 3) & -4;
-#ifdef TCC_ARM_EABI
-    addr = (addr + align - 1) & -align;
-#endif
-    sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
-    addr += size;
-  }
-  last_itod_magic=0;
-  leaffunc = 1;
-  loc = -12;
-}
-
-/* generate function epilog */
-void gfunc_epilog(void)
-{
-  unsigned long x;
-  int diff;
-#ifdef TCC_ARM_EABI
-  if(is_float(func_vt.t)) {
-    if((func_vt.t & VT_BTYPE) == VT_FLOAT)
-      o(0xEE100A10); /* fmrs r0, s0 */
-    else {
-      o(0xEE100B10); /* fmrdl r0, d0 */
-      o(0xEE301B10); /* fmrdh r1, d0 */
-    }
-  }
-#endif
-  o(0xE91BA800); /* restore fp, sp, pc */
-  diff = (-loc + 3) & -4;
-#ifdef TCC_ARM_EABI
-  if(!leaffunc)
-    diff = (diff + 7) & -8;
-#endif
-  if(diff > 12) {
-    x=stuff_const(0xE24BD000, diff); /* sub sp,fp,# */
-    if(x)
-      *(unsigned long *)(cur_text_section->data + func_sub_sp_offset) = x;
-    else {
-      unsigned long addr;
-      addr=ind;
-      o(0xE59FC004); /* ldr ip,[pc+4] */
-      o(0xE04BD00C); /* sub sp,fp,ip  */
-      o(0xE1A0F00E); /* mov pc,lr */
-      o(diff);
-      *(unsigned long *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1);
-    }
-  }
-}
-
-/* generate a jump to a label */
-int gjmp(int t)
-{
-  int r;
-  r=ind;
-  o(0xE0000000|encbranch(r,t,1));
-  return r;
-}
-
-/* generate a jump to a fixed address */
-void gjmp_addr(int a)
-{
-  gjmp(a);
-}
-
-/* generate a test. set 'inv' to invert test. Stack entry is popped */
-int gtst(int inv, int t)
-{
-  int v, r;
-  unsigned long op;
-  v = vtop->r & VT_VALMASK;
-  r=ind;
-  if (v == VT_CMP) {
-    op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);
-    op|=encbranch(r,t,1);
-    o(op);
-    t=r;
-  } else if (v == VT_JMP || v == VT_JMPI) {
-    if ((v & 1) == inv) {
-      if(!vtop->c.i)
-	vtop->c.i=t;
-      else {
-	unsigned long *x;
-	int p,lp;
-	if(t) {
-          p = vtop->c.i;
-          do {
-	    p = decbranch(lp=p);
-          } while(p);
-	  x = (unsigned long *)(cur_text_section->data + lp);
-	  *x &= 0xff000000;
-	  *x |= encbranch(lp,t,1);
-	}
-	t = vtop->c.i;
-      }
-    } else {
-      t = gjmp(t);
-      gsym(vtop->c.i);
-    }
-  } else {
-    if (is_float(vtop->type.t)) {
-      r=gv(RC_FLOAT);
-#ifdef TCC_ARM_VFP
-      o(0xEEB50A40|(vfpr(r)<<12)|T2CPR(vtop->type.t)); /* fcmpzX */
-      o(0xEEF1FA10); /* fmstat */
-#else
-      o(0xEE90F118|(fpr(r)<<16));
-#endif
-      vtop->r = VT_CMP;
-      vtop->c.i = TOK_NE;
-      return gtst(inv, t);
-    } else if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-      /* constant jmp optimization */
-      if ((vtop->c.i != 0) != inv) 
-	t = gjmp(t);
-    } else {
-      v = gv(RC_INT);
-      o(0xE3300000|(intr(v)<<16));
-      vtop->r = VT_CMP;
-      vtop->c.i = TOK_NE;
-      return gtst(inv, t);
-    }   
-  }
-  vtop--;
-  return t;
-}
-
-/* generate an integer binary operation */
-void gen_opi(int op)
-{
-  int c, func = 0;
-  unsigned long opc = 0,r,fr;
-  unsigned short retreg = REG_IRET;
-
-  c=0;
-  switch(op) {
-    case '+':
-      opc = 0x8;
-      c=1;
-      break;
-    case TOK_ADDC1: /* add with carry generation */
-      opc = 0x9;
-      c=1;
-      break;
-    case '-':
-      opc = 0x4;
-      c=1;
-      break;
-    case TOK_SUBC1: /* sub with carry generation */
-      opc = 0x5;
-      c=1;
-      break;
-    case TOK_ADDC2: /* add with carry use */
-      opc = 0xA;
-      c=1;
-      break;
-    case TOK_SUBC2: /* sub with carry use */
-      opc = 0xC;
-      c=1;
-      break;
-    case '&':
-      opc = 0x0;
-      c=1;
-      break;
-    case '^':
-      opc = 0x2;
-      c=1;
-      break;
-    case '|':
-      opc = 0x18;
-      c=1;
-      break;
-    case '*':
-      gv2(RC_INT, RC_INT);
-      r = vtop[-1].r;
-      fr = vtop[0].r;
-      vtop--;
-      o(0xE0000090|(intr(r)<<16)|(intr(r)<<8)|intr(fr));
-      return;
-    case TOK_SHL:
-      opc = 0;
-      c=2;
-      break;
-    case TOK_SHR:
-      opc = 1;
-      c=2;
-      break;
-    case TOK_SAR:
-      opc = 2;
-      c=2;
-      break;
-    case '/':
-    case TOK_PDIV:
-      func=TOK___divsi3;
-      c=3;
-      break;
-    case TOK_UDIV:
-      func=TOK___udivsi3;
-      c=3;
-      break;
-    case '%':
-#ifdef TCC_ARM_EABI
-      func=TOK___aeabi_idivmod;
-      retreg=REG_LRET;
-#else
-      func=TOK___modsi3;
-#endif
-      c=3;
-      break;
-    case TOK_UMOD:
-#ifdef TCC_ARM_EABI
-      func=TOK___aeabi_uidivmod;
-      retreg=REG_LRET;
-#else
-      func=TOK___umodsi3;
-#endif
-      c=3;
-      break;
-    case TOK_UMULL:
-      gv2(RC_INT, RC_INT);
-      r=intr(vtop[-1].r2=get_reg(RC_INT));
-      c=vtop[-1].r;
-      vtop[-1].r=get_reg_ex(RC_INT,regmask(c));
-      vtop--;
-      o(0xE0800090|(r<<16)|(intr(vtop->r)<<12)|(intr(c)<<8)|intr(vtop[1].r));
-      return;
-    default:
-      opc = 0x15;
-      c=1;
-      break;
-  }
-  switch(c) {
-    case 1:
-      if((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-	if(opc == 4 || opc == 5 || opc == 0xc) {
-	  vswap();
-	  opc|=2; // sub -> rsb
-	}
-      }
-      if ((vtop->r & VT_VALMASK) == VT_CMP ||
-          (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
-        gv(RC_INT);
-      vswap();
-      c=intr(gv(RC_INT));
-      vswap();
-      opc=0xE0000000|(opc<<20)|(c<<16);
-      if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-	unsigned long x;
-	x=stuff_const(opc|0x2000000,vtop->c.i);
-	if(x) {
-	  r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
-	  o(x|(r<<12));
-	  goto done;
-	}
-      }
-      fr=intr(gv(RC_INT));
-      r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
-      o(opc|(r<<12)|fr);
-done:
-      vtop--;
-      if (op >= TOK_ULT && op <= TOK_GT) {
-        vtop->r = VT_CMP;
-        vtop->c.i = op;
-      }
-      break;
-    case 2:
-      opc=0xE1A00000|(opc<<5);
-      if ((vtop->r & VT_VALMASK) == VT_CMP ||
-          (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
-        gv(RC_INT);
-      vswap();
-      r=intr(gv(RC_INT));
-      vswap();
-      opc|=r;
-      if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-	fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
-	c = vtop->c.i & 0x1f;
-	o(opc|(c<<7)|(fr<<12));
-      } else {
-        fr=intr(gv(RC_INT));
-	c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
-	o(opc|(c<<12)|(fr<<8)|0x10);
-      }
-      vtop--;
-      break;
-    case 3:
-      vpush_global_sym(&func_old_type, func);
-      vrott(3);
-      gfunc_call(2);
-      vpushi(0);
-      vtop->r = retreg;
-      break;
-    default:
-      error("gen_opi %i unimplemented!",op);
-  }
-}
-
-#ifdef TCC_ARM_VFP
-static int is_zero(int i)
-{
-  if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
-    return 0;
-  if (vtop[i].type.t == VT_FLOAT)
-    return (vtop[i].c.f == 0.f);
-  else if (vtop[i].type.t == VT_DOUBLE)
-    return (vtop[i].c.d == 0.0);
-  return (vtop[i].c.ld == 0.l);
-}
-
-/* generate a floating point operation 'v = t1 op t2' instruction. The
- *    two operands are guaranted to have the same floating point type */
-void gen_opf(int op)
-{
-  unsigned long x;
-  int fneg=0,r;
-  x=0xEE000A00|T2CPR(vtop->type.t);
-  switch(op) {
-    case '+':
-      if(is_zero(-1))
-        vswap();
-      if(is_zero(0)) {
-        vtop--;
-        return;
-      }
-      x|=0x300000;
-      break;
-    case '-':
-      x|=0x300040;
-      if(is_zero(0)) {
-        vtop--;
-        return;
-      }
-      if(is_zero(-1)) {
-        x|=0x810000; /* fsubX -> fnegX */
-        vswap();
-        vtop--;
-        fneg=1;
-      }
-      break;
-    case '*':
-      x|=0x200000;
-      break;
-    case '/':
-      x|=0x800000;
-      break;
-    default:
-      if(op < TOK_ULT && op > TOK_GT) {
-        error("unknown fp op %x!",op);
-        return;
-      }
-      if(is_zero(-1)) {
-        vswap();
-        switch(op) {
-          case TOK_LT: op=TOK_GT; break;
-          case TOK_GE: op=TOK_ULE; break;
-          case TOK_LE: op=TOK_GE; break;
-          case TOK_GT: op=TOK_ULT; break;
-        }
-      }
-      x|=0xB40040; /* fcmpX */
-      if(op!=TOK_EQ && op!=TOK_NE)
-        x|=0x80; /* fcmpX -> fcmpeX */
-      if(is_zero(0)) {
-        vtop--;
-        o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */
-      } else {
-        x|=vfpr(gv(RC_FLOAT));
-        vswap();
-        o(x|(vfpr(gv(RC_FLOAT))<<12));
-        vtop--;
-      }
-      o(0xEEF1FA10); /* fmstat */
-
-      switch(op) {
-        case TOK_LE: op=TOK_ULE; break;
-        case TOK_LT: op=TOK_ULT; break;
-        case TOK_UGE: op=TOK_GE; break;
-        case TOK_UGT: op=TOK_GT; break;
-      }
-      
-      vtop->r = VT_CMP;
-      vtop->c.i = op;
-      return;
-  }
-  r=gv(RC_FLOAT);
-  x|=vfpr(r);
-  r=regmask(r);
-  if(!fneg) {
-    int r2;
-    vswap();
-    r2=gv(RC_FLOAT);
-    x|=vfpr(r2)<<16;
-    r|=regmask(r2);
-  }
-  vtop->r=get_reg_ex(RC_FLOAT,r);
-  if(!fneg)
-    vtop--;
-  o(x|(vfpr(vtop->r)<<12));
-}
-
-#else
-static int is_fconst()
-{
-  long double f;
-  int r;
-  if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
-    return 0;
-  if (vtop->type.t == VT_FLOAT)
-    f = vtop->c.f;
-  else if (vtop->type.t == VT_DOUBLE)
-    f = vtop->c.d;
-  else
-    f = vtop->c.ld;
-  if(!ieee_finite(f))
-    return 0;
-  r=0x8;
-  if(f<0.0) {
-    r=0x18;
-    f=-f;
-  }
-  if(f==0.0)
-    return r;
-  if(f==1.0)
-    return r|1;
-  if(f==2.0)
-    return r|2;
-  if(f==3.0)
-    return r|3;
-  if(f==4.0)
-    return r|4;
-  if(f==5.0)
-    return r|5;
-  if(f==0.5)
-    return r|6;
-  if(f==10.0)
-    return r|7;
-  return 0;
-}
-
-/* generate a floating point operation 'v = t1 op t2' instruction. The
-   two operands are guaranted to have the same floating point type */
-void gen_opf(int op)
-{
-  unsigned long x;
-  int r,r2,c1,c2;
-  //fputs("gen_opf\n",stderr);
-  vswap();
-  c1 = is_fconst();
-  vswap();
-  c2 = is_fconst();
-  x=0xEE000100;
-#if LDOUBLE_SIZE == 8
-  if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)
-    x|=0x80;
-#else
-  if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
-    x|=0x80;
-  else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)
-    x|=0x80000;
-#endif
-  switch(op)
-  {
-    case '+':
-      if(!c2) {
-	vswap();
-	c2=c1;
-      }
-      vswap();
-      r=fpr(gv(RC_FLOAT));
-      vswap();
-      if(c2) {
-	if(c2>0xf)
-	  x|=0x200000; // suf
-	r2=c2&0xf;
-      } else {
-	r2=fpr(gv(RC_FLOAT));
-      }
-      break;
-    case '-':
-      if(c2) {
-	if(c2<=0xf)
-	  x|=0x200000; // suf
-	r2=c2&0xf;
-	vswap();
-	r=fpr(gv(RC_FLOAT));
-	vswap();
-      } else if(c1 && c1<=0xf) {
-	x|=0x300000; // rsf
-	r2=c1;
-	r=fpr(gv(RC_FLOAT));
-	vswap();
-      } else {
-	x|=0x200000; // suf
-	vswap();
-	r=fpr(gv(RC_FLOAT));
-	vswap();
-	r2=fpr(gv(RC_FLOAT));
-      }
-      break;
-    case '*':
-      if(!c2 || c2>0xf) {
-	vswap();
-	c2=c1;
-      }
-      vswap();
-      r=fpr(gv(RC_FLOAT));
-      vswap();
-      if(c2 && c2<=0xf)
-	r2=c2;
-      else
-	r2=fpr(gv(RC_FLOAT));
-      x|=0x100000; // muf
-      break;
-    case '/':
-      if(c2 && c2<=0xf) {
-	x|=0x400000; // dvf
-	r2=c2;
-	vswap();
-	r=fpr(gv(RC_FLOAT));
-	vswap();
-      } else if(c1 && c1<=0xf) {
-	x|=0x500000; // rdf
-	r2=c1;
-	r=fpr(gv(RC_FLOAT));
-	vswap();
-      } else {
-	x|=0x400000; // dvf
-	vswap();
-	r=fpr(gv(RC_FLOAT));
-	vswap();
-	r2=fpr(gv(RC_FLOAT));
-      }     
-      break;
-    default:
-      if(op >= TOK_ULT && op <= TOK_GT) {
-	x|=0xd0f110; // cmfe
-/* bug (intention?) in Linux FPU emulator
-   doesn't set carry if equal */
-	switch(op) {
-	  case TOK_ULT:
-	  case TOK_UGE:
-	  case TOK_ULE:
-	  case TOK_UGT:
-            error("unsigned comparision on floats?");
-	    break;
-	  case TOK_LT:
-            op=TOK_Nset;
-	    break;
-	  case TOK_LE:
-            op=TOK_ULE; /* correct in unordered case only if AC bit in FPSR set */
-	    break;
-	  case TOK_EQ:
-	  case TOK_NE:
-	    x&=~0x400000; // cmfe -> cmf
-	    break;
-	}
-	if(c1 && !c2) {
-	  c2=c1;
-	  vswap();
-	  switch(op) {
-            case TOK_Nset:
-              op=TOK_GT;
-	      break;
-            case TOK_GE:
-	      op=TOK_ULE;
-	      break;
-	    case TOK_ULE:
-              op=TOK_GE;
-	      break;
-            case TOK_GT:
-              op=TOK_Nset;
-	      break;
-	  }
-	}
-	vswap();
-	r=fpr(gv(RC_FLOAT));
-	vswap();
-	if(c2) {
-	  if(c2>0xf)
-	    x|=0x200000;
-	  r2=c2&0xf;
-	} else {
-	  r2=fpr(gv(RC_FLOAT));
-	}
-	vtop[-1].r = VT_CMP;
-	vtop[-1].c.i = op;
-      } else {
-        error("unknown fp op %x!",op);
-	return;
-      }
-  }
-  if(vtop[-1].r == VT_CMP)
-    c1=15;
-  else {
-    c1=vtop->r;
-    if(r2&0x8)
-      c1=vtop[-1].r;
-    vtop[-1].r=get_reg_ex(RC_FLOAT,two2mask(vtop[-1].r,c1));
-    c1=fpr(vtop[-1].r);
-  }
-  vtop--;
-  o(x|(r<<16)|(c1<<12)|r2);
-}
-#endif
-
-/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
-   and 'long long' cases. */
-void gen_cvt_itof1(int t)
-{
-  int r,r2,bt;
-  bt=vtop->type.t & VT_BTYPE;
-  if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) {
-#ifndef TCC_ARM_VFP
-    unsigned int dsize=0;
-#endif
-    r=intr(gv(RC_INT));
-#ifdef TCC_ARM_VFP
-    r2=vfpr(vtop->r=get_reg(RC_FLOAT));
-    o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */
-    r2<<=12;
-    if(!(vtop->type.t & VT_UNSIGNED))
-      r2|=0x80;                /* fuitoX -> fsituX */
-    o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/
-#else
-    r2=fpr(vtop->r=get_reg(RC_FLOAT));
-    if((t & VT_BTYPE) != VT_FLOAT)
-      dsize=0x80;    /* flts -> fltd */
-    o(0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */
-    if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) {
-      unsigned int off=0;
-      o(0xE3500000|(r<<12));        /* cmp */
-      r=fpr(get_reg(RC_FLOAT));
-      if(last_itod_magic) {
-	off=ind+8-last_itod_magic;
-	off/=4;
-	if(off>255)
-	  off=0;
-      }
-      o(0xBD1F0100|(r<<12)|off);    /* ldflts */
-      if(!off) {
-        o(0xEA000000);              /* b */
-        last_itod_magic=ind;
-        o(0x4F800000);              /* 4294967296.0f */
-      }
-      o(0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */
-    }
-#endif
-    return;
-  } else if(bt == VT_LLONG) {
-    int func;
-    CType *func_type = 0;
-    if((t & VT_BTYPE) == VT_FLOAT) {
-      func_type = &func_float_type;
-      if(vtop->type.t & VT_UNSIGNED)
-        func=TOK___floatundisf;
-      else
-        func=TOK___floatdisf;
-#if LDOUBLE_SIZE != 8
-    } else if((t & VT_BTYPE) == VT_LDOUBLE) {
-      func_type = &func_ldouble_type;
-      if(vtop->type.t & VT_UNSIGNED)
-        func=TOK___floatundixf;
-      else
-        func=TOK___floatdixf;
-    } else if((t & VT_BTYPE) == VT_DOUBLE) {
-#else
-    } else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) {
-#endif
-      func_type = &func_double_type;
-      if(vtop->type.t & VT_UNSIGNED)
-        func=TOK___floatundidf;
-      else
-        func=TOK___floatdidf;
-    }
-    if(func_type) {
-      vpush_global_sym(func_type, func);
-      vswap();
-      gfunc_call(1);
-      vpushi(0);
-      vtop->r=TREG_F0;
-      return;
-    }
-  }
-  error("unimplemented gen_cvt_itof %x!",vtop->type.t);
-}
-
-/* convert fp to int 't' type */
-void gen_cvt_ftoi(int t)
-{
-  int r,r2,u,func=0;
-  u=t&VT_UNSIGNED;
-  t&=VT_BTYPE;
-  r2=vtop->type.t & VT_BTYPE;
-  if(t==VT_INT) {
-#ifdef TCC_ARM_VFP
-    r=vfpr(gv(RC_FLOAT));
-    u=u?0:0x10000;
-    o(0xEEBC0A40|(r<<12)|r|T2CPR(r2)); /* ftoXiY */
-    r2=intr(vtop->r=get_reg(RC_INT));
-    o(0xEE100A10|(r<<16)|(r2<<12));
-    return;
-#else
-    if(u) {
-      if(r2 == VT_FLOAT)
-        func=TOK___fixunssfsi;
-#if LDOUBLE_SIZE != 8
-      else if(r2 == VT_LDOUBLE)
-	func=TOK___fixunsxfsi;
-      else if(r2 == VT_DOUBLE)
-#else
-      else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
-#endif
-	func=TOK___fixunsdfsi;
-    } else {
-      r=fpr(gv(RC_FLOAT));
-      r2=intr(vtop->r=get_reg(RC_INT));
-      o(0xEE100170|(r2<<12)|r);
-      return;
-    }
-#endif
-  } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1
-    if(r2 == VT_FLOAT)
-      func=TOK___fixsfdi;
-#if LDOUBLE_SIZE != 8
-    else if(r2 == VT_LDOUBLE)
-      func=TOK___fixxfdi;
-    else if(r2 == VT_DOUBLE)
-#else
-    else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
-#endif
-      func=TOK___fixdfdi;
-  }
-  if(func) {
-    vpush_global_sym(&func_old_type, func);
-    vswap();
-    gfunc_call(1);
-    vpushi(0);
-    if(t == VT_LLONG)
-      vtop->r2 = REG_LRET;
-    vtop->r = REG_IRET;
-    return;
-  }
-  error("unimplemented gen_cvt_ftoi!");
-}
-
-/* convert from one floating point type to another */
-void gen_cvt_ftof(int t)
-{
-#ifdef TCC_ARM_VFP
-  if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) {
-    int r=vfpr(gv(RC_FLOAT));
-    o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t));
-  }
-#else
-  /* all we have to do on i386 and FPA ARM is to put the float in a register */
-  gv(RC_FLOAT);
-#endif
-}
-
-/* computed goto support */
-void ggoto(void)
-{
-  gcall_or_jmp(1);
-  vtop--;
-}
-
-/* end of ARM code generator */
-/*************************************************************/
-

+ 0 - 2548
src/modules/native/tcc/libtcc/c67-gen.c

@@ -1,2548 +0,0 @@
-/*
- *  TMS320C67xx code generator for TCC
- * 
- *  Copyright (c) 2001, 2002 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-//#define ASSEMBLY_LISTING_C67
-
-/* number of available registers */
-#define NB_REGS            24
-
-/* a register can belong to several classes. The classes must be
-   sorted from more general to more precise (see gv2() code which does
-   assumptions on it). */
-#define RC_INT     0x0001	/* generic integer register */
-#define RC_FLOAT   0x0002	/* generic float register */
-#define RC_EAX     0x0004
-#define RC_ST0     0x0008
-#define RC_ECX     0x0010
-#define RC_EDX     0x0020
-#define RC_INT_BSIDE  0x00000040	/* generic integer register  on b side */
-#define RC_C67_A4     0x00000100
-#define RC_C67_A5     0x00000200
-#define RC_C67_B4     0x00000400
-#define RC_C67_B5     0x00000800
-#define RC_C67_A6     0x00001000
-#define RC_C67_A7     0x00002000
-#define RC_C67_B6     0x00004000
-#define RC_C67_B7     0x00008000
-#define RC_C67_A8     0x00010000
-#define RC_C67_A9     0x00020000
-#define RC_C67_B8     0x00040000
-#define RC_C67_B9     0x00080000
-#define RC_C67_A10    0x00100000
-#define RC_C67_A11    0x00200000
-#define RC_C67_B10    0x00400000
-#define RC_C67_B11    0x00800000
-#define RC_C67_A12    0x01000000
-#define RC_C67_A13    0x02000000
-#define RC_C67_B12    0x04000000
-#define RC_C67_B13    0x08000000
-#define RC_IRET    RC_C67_A4	/* function return: integer register */
-#define RC_LRET    RC_C67_A5	/* function return: second integer register */
-#define RC_FRET    RC_C67_A4	/* function return: float register */
-
-/* pretty names for the registers */
-enum {
-    TREG_EAX = 0,		// really A2
-    TREG_ECX,			// really A3
-    TREG_EDX,			// really B0
-    TREG_ST0,			// really B1
-    TREG_C67_A4,
-    TREG_C67_A5,
-    TREG_C67_B4,
-    TREG_C67_B5,
-    TREG_C67_A6,
-    TREG_C67_A7,
-    TREG_C67_B6,
-    TREG_C67_B7,
-    TREG_C67_A8,
-    TREG_C67_A9,
-    TREG_C67_B8,
-    TREG_C67_B9,
-    TREG_C67_A10,
-    TREG_C67_A11,
-    TREG_C67_B10,
-    TREG_C67_B11,
-    TREG_C67_A12,
-    TREG_C67_A13,
-    TREG_C67_B12,
-    TREG_C67_B13,
-};
-
-int reg_classes[NB_REGS] = {
-						/* eax */ RC_INT | RC_FLOAT | RC_EAX,
-						// only allow even regs for floats (allow for doubles)
-    /* ecx */ RC_INT | RC_ECX,
-								/* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
-								// only allow even regs for floats (allow for doubles)
-    /* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0,
-    /* A4  */ RC_C67_A4,
-    /* A5  */ RC_C67_A5,
-    /* B4  */ RC_C67_B4,
-    /* B5  */ RC_C67_B5,
-    /* A6  */ RC_C67_A6,
-    /* A7  */ RC_C67_A7,
-    /* B6  */ RC_C67_B6,
-    /* B7  */ RC_C67_B7,
-    /* A8  */ RC_C67_A8,
-    /* A9  */ RC_C67_A9,
-    /* B8  */ RC_C67_B8,
-    /* B9  */ RC_C67_B9,
-    /* A10  */ RC_C67_A10,
-    /* A11  */ RC_C67_A11,
-    /* B10  */ RC_C67_B10,
-    /* B11  */ RC_C67_B11,
-    /* A12  */ RC_C67_A10,
-    /* A13  */ RC_C67_A11,
-    /* B12  */ RC_C67_B10,
-    /* B13  */ RC_C67_B11
-};
-
-/* return registers for function */
-#define REG_IRET TREG_C67_A4	/* single word int return register */
-#define REG_LRET TREG_C67_A5	/* second word return register (for long long) */
-#define REG_FRET TREG_C67_A4	/* float return register */
-
-
-#define ALWAYS_ASSERT(x) \
-do {\
-   if (!(x))\
-       error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
-} while (0)
-
-// although tcc thinks it is passing parameters on the stack,
-// the C67 really passes up to the first 10 params in special
-// regs or regs pairs (for 64 bit params).  So keep track of
-// the stack offsets so we can translate to the appropriate 
-// reg (pair)
-
-
-#define NoCallArgsPassedOnStack 10
-int NoOfCurFuncArgs;
-int TranslateStackToReg[NoCallArgsPassedOnStack];
-int ParamLocOnStack[NoCallArgsPassedOnStack];
-int TotalBytesPushedOnStack;
-
-/* defined if function parameters must be evaluated in reverse order */
-
-//#define INVERT_FUNC_PARAMS
-
-/* defined if structures are passed as pointers. Otherwise structures
-   are directly pushed on stack. */
-//#define FUNC_STRUCT_PARAM_AS_PTR
-
-/* pointer size, in bytes */
-#define PTR_SIZE 4
-
-/* long double size and alignment, in bytes */
-#define LDOUBLE_SIZE  12
-#define LDOUBLE_ALIGN 4
-/* maximum alignment (for aligned attribute support) */
-#define MAX_ALIGN     8
-
-/******************************************************/
-/* ELF defines */
-
-#define EM_TCC_TARGET EM_C60
-
-/* relocation type for 32 bit data relocation */
-#define R_DATA_32   R_C60_32
-#define R_JMP_SLOT  R_C60_JMP_SLOT
-#define R_COPY      R_C60_COPY
-
-#define ELF_START_ADDR 0x00000400
-#define ELF_PAGE_SIZE  0x1000
-
-/******************************************************/
-
-static unsigned long func_sub_sp_offset;
-static int func_ret_sub;
-
-
-static BOOL C67_invert_test;
-static int C67_compare_reg;
-
-#ifdef ASSEMBLY_LISTING_C67
-FILE *f = NULL;
-#endif
-
-
-void C67_g(int c)
-{
-    int ind1;
-
-#ifdef ASSEMBLY_LISTING_C67
-    fprintf(f, " %08X", c);
-#endif
-    ind1 = ind + 4;
-    if (ind1 > (int) cur_text_section->data_allocated)
-	section_realloc(cur_text_section, ind1);
-    cur_text_section->data[ind] = c & 0xff;
-    cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
-    cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
-    cur_text_section->data[ind + 3] = (c >> 24) & 0xff;
-    ind = ind1;
-}
-
-
-/* output a symbol and patch all calls to it */
-void gsym_addr(int t, int a)
-{
-    int n, *ptr;
-    while (t) {
-	ptr = (int *) (cur_text_section->data + t);
-	{
-	    Sym *sym;
-
-	    // extract 32 bit address from MVKH/MVKL
-	    n = ((*ptr >> 7) & 0xffff);
-	    n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
-
-	    // define a label that will be relocated
-
-	    sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
-	    greloc(cur_text_section, sym, t, R_C60LO16);
-	    greloc(cur_text_section, sym, t + 4, R_C60HI16);
-
-	    // clear out where the pointer was
-
-	    *ptr &= ~(0xffff << 7);
-	    *(ptr + 1) &= ~(0xffff << 7);
-	}
-	t = n;
-    }
-}
-
-void gsym(int t)
-{
-    gsym_addr(t, ind);
-}
-
-// these are regs that tcc doesn't really know about, 
-// but asign them unique values so the mapping routines
-// can distinquish them
-
-#define C67_A0 105
-#define C67_SP 106
-#define C67_B3 107
-#define C67_FP 108
-#define C67_B2 109
-#define C67_CREG_ZERO -1	// Special code for no condition reg test
-
-
-int ConvertRegToRegClass(int r)
-{
-    // only works for A4-B13
-
-    return RC_C67_A4 << (r - TREG_C67_A4);
-}
-
-
-// map TCC reg to C67 reg number
-
-int C67_map_regn(int r)
-{
-    if (r == 0)			// normal tcc regs
-	return 0x2;		// A2
-    else if (r == 1)		// normal tcc regs
-	return 3;		// A3
-    else if (r == 2)		// normal tcc regs
-	return 0;		// B0
-    else if (r == 3)		// normal tcc regs
-	return 1;		// B1
-    else if (r >= TREG_C67_A4 && r <= TREG_C67_B13)	// these form a pattern of alt pairs
-	return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;
-    else if (r == C67_A0)
-	return 0;		// set to A0 (offset reg)
-    else if (r == C67_B2)
-	return 2;		// set to B2 (offset reg)
-    else if (r == C67_B3)
-	return 3;		// set to B3 (return address reg)
-    else if (r == C67_SP)
-	return 15;		// set to SP (B15) (offset reg)
-    else if (r == C67_FP)
-	return 15;		// set to FP (A15) (offset reg)
-    else if (r == C67_CREG_ZERO)
-	return 0;		// Special code for no condition reg test
-    else
-	ALWAYS_ASSERT(FALSE);
-
-    return 0;
-}
-
-// mapping from tcc reg number to 
-// C67 register to condition code field
-//
-// valid condition code regs are:
-//
-// tcc reg 2 ->B0 -> 1
-// tcc reg 3 ->B1 -> 2
-// tcc reg 0 -> A2 -> 5
-// tcc reg 1 -> A3 -> X
-// tcc reg      B2 -> 3
-
-int C67_map_regc(int r)
-{
-    if (r == 0)			// normal tcc regs
-	return 0x5;
-    else if (r == 2)		// normal tcc regs
-	return 0x1;
-    else if (r == 3)		// normal tcc regs
-	return 0x2;
-    else if (r == C67_B2)	// normal tcc regs
-	return 0x3;
-    else if (r == C67_CREG_ZERO)
-	return 0;		// Special code for no condition reg test
-    else
-	ALWAYS_ASSERT(FALSE);
-
-    return 0;
-}
-
-
-// map TCC reg to C67 reg side A or B
-
-int C67_map_regs(int r)
-{
-    if (r == 0)			// normal tcc regs
-	return 0x0;
-    else if (r == 1)		// normal tcc regs
-	return 0x0;
-    else if (r == 2)		// normal tcc regs
-	return 0x1;
-    else if (r == 3)		// normal tcc regs
-	return 0x1;
-    else if (r >= TREG_C67_A4 && r <= TREG_C67_B13)	// these form a pattern of alt pairs
-	return (r & 2) >> 1;
-    else if (r == C67_A0)
-	return 0;		// set to A side 
-    else if (r == C67_B2)
-	return 1;		// set to B side 
-    else if (r == C67_B3)
-	return 1;		// set to B side
-    else if (r == C67_SP)
-	return 0x1;		// set to SP (B15) B side 
-    else if (r == C67_FP)
-	return 0x0;		// set to FP (A15) A side 
-    else
-	ALWAYS_ASSERT(FALSE);
-
-    return 0;
-}
-
-int C67_map_S12(char *s)
-{
-    if (strstr(s, ".S1") != NULL)
-	return 0;
-    else if (strcmp(s, ".S2"))
-	return 1;
-    else
-	ALWAYS_ASSERT(FALSE);
-
-    return 0;
-}
-
-int C67_map_D12(char *s)
-{
-    if (strstr(s, ".D1") != NULL)
-	return 0;
-    else if (strcmp(s, ".D2"))
-	return 1;
-    else
-	ALWAYS_ASSERT(FALSE);
-
-    return 0;
-}
-
-
-
-void C67_asm(char *s, int a, int b, int c)
-{
-    BOOL xpath;
-
-#ifdef ASSEMBLY_LISTING_C67
-    if (!f) {
-	f = fopen("TCC67_out.txt", "wt");
-    }
-    fprintf(f, "%04X ", ind);
-#endif
-
-    if (strstr(s, "MVKL") == s) {
-	C67_g((C67_map_regn(b) << 23) |
-	      ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));
-    } else if (strstr(s, "MVKH") == s) {
-	C67_g((C67_map_regn(b) << 23) |
-	      (((a >> 16) & 0xffff) << 7) |
-	      (0x1a << 2) | (C67_map_regs(b) << 1));
-    } else if (strstr(s, "STW.D SP POST DEC") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//src
-	      (15 << 18) |	//SP B15
-	      (2 << 13) |	//ucst5 (must keep 8 byte boundary !!)
-	      (0xa << 9) |	//mode a = post dec ucst
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (1 << 7) |	//y D1/D2 use B side
-	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of src
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "STB.D *+SP[A0]") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//src
-	      (15 << 18) |	//base reg A15
-	      (0 << 13) |	//offset reg A0
-	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (0 << 7) |	//y D1/D2 A side
-	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of src
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "STH.D *+SP[A0]") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//src
-	      (15 << 18) |	//base reg A15
-	      (0 << 13) |	//offset reg A0
-	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (0 << 7) |	//y D1/D2 A side
-	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of src
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "STB.D *+SP[A0]") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//src
-	      (15 << 18) |	//base reg A15
-	      (0 << 13) |	//offset reg A0
-	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (0 << 7) |	//y D1/D2 A side
-	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of src
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "STH.D *+SP[A0]") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//src
-	      (15 << 18) |	//base reg A15
-	      (0 << 13) |	//offset reg A0
-	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (0 << 7) |	//y D1/D2 A side
-	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of src
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "STW.D *+SP[A0]") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//src
-	      (15 << 18) |	//base reg A15
-	      (0 << 13) |	//offset reg A0
-	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (0 << 7) |	//y D1/D2 A side
-	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of src
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "STW.D *") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//src
-	      (C67_map_regn(b) << 18) |	//base reg A0
-	      (0 << 13) |	//cst5
-	      (1 << 9) |	//mode 1 = pos cst offset
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
-	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of src
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "STH.D *") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//src
-	      (C67_map_regn(b) << 18) |	//base reg A0
-	      (0 << 13) |	//cst5
-	      (1 << 9) |	//mode 1 = pos cst offset
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
-	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of src
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "STB.D *") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//src
-	      (C67_map_regn(b) << 18) |	//base reg A0
-	      (0 << 13) |	//cst5
-	      (1 << 9) |	//mode 1 = pos cst offset
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
-	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of src
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "STW.D +*") == s) {
-	ALWAYS_ASSERT(c < 32);
-	C67_g((C67_map_regn(a) << 23) |	//src
-	      (C67_map_regn(b) << 18) |	//base reg A0
-	      (c << 13) |	//cst5
-	      (1 << 9) |	//mode 1 = pos cst offset
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
-	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of src
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDW.D SP PRE INC") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//dst
-	      (15 << 18) |	//base reg B15
-	      (2 << 13) |	//ucst5 (must keep 8 byte boundary)
-	      (9 << 9) |	//mode 9 = pre inc ucst5
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (1 << 7) |	//y D1/D2  B side
-	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDDW.D SP PRE INC") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//dst
-	      (15 << 18) |	//base reg B15
-	      (1 << 13) |	//ucst5 (must keep 8 byte boundary)
-	      (9 << 9) |	//mode 9 = pre inc ucst5
-	      (1 << 8) |	//r (LDDW bit 1)
-	      (1 << 7) |	//y D1/D2  B side
-	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDW.D *+SP[A0]") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//dst
-	      (15 << 18) |	//base reg A15
-	      (0 << 13) |	//offset reg A0
-	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (0 << 7) |	//y D1/D2  A side
-	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDDW.D *+SP[A0]") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//dst
-	      (15 << 18) |	//base reg A15
-	      (0 << 13) |	//offset reg A0
-	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
-	      (1 << 8) |	//r (LDDW bit 1)
-	      (0 << 7) |	//y D1/D2  A side
-	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDH.D *+SP[A0]") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//dst
-	      (15 << 18) |	//base reg A15
-	      (0 << 13) |	//offset reg A0
-	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (0 << 7) |	//y D1/D2  A side
-	      (4 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDB.D *+SP[A0]") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//dst
-	      (15 << 18) |	//base reg A15
-	      (0 << 13) |	//offset reg A0
-	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (0 << 7) |	//y D1/D2  A side
-	      (2 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDHU.D *+SP[A0]") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//dst
-	      (15 << 18) |	//base reg A15
-	      (0 << 13) |	//offset reg A0
-	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (0 << 7) |	//y D1/D2  A side
-	      (0 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDBU.D *+SP[A0]") == s) {
-	C67_g((C67_map_regn(a) << 23) |	//dst
-	      (15 << 18) |	//base reg A15
-	      (0 << 13) |	//offset reg A0
-	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (0 << 7) |	//y D1/D2  A side
-	      (1 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(a) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDW.D *") == s) {
-	C67_g((C67_map_regn(b) << 23) |	//dst
-	      (C67_map_regn(a) << 18) |	//base reg A15
-	      (0 << 13) |	//cst5
-	      (1 << 9) |	//mode 1 = pos cst offset
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
-	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(b) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDDW.D *") == s) {
-	C67_g((C67_map_regn(b) << 23) |	//dst
-	      (C67_map_regn(a) << 18) |	//base reg A15
-	      (0 << 13) |	//cst5
-	      (1 << 9) |	//mode 1 = pos cst offset
-	      (1 << 8) |	//r (LDDW bit 1)
-	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
-	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(b) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDH.D *") == s) {
-	C67_g((C67_map_regn(b) << 23) |	//dst
-	      (C67_map_regn(a) << 18) |	//base reg A15
-	      (0 << 13) |	//cst5
-	      (1 << 9) |	//mode 1 = pos cst offset
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
-	      (4 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(b) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDB.D *") == s) {
-	C67_g((C67_map_regn(b) << 23) |	//dst
-	      (C67_map_regn(a) << 18) |	//base reg A15
-	      (0 << 13) |	//cst5
-	      (1 << 9) |	//mode 1 = pos cst offset
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
-	      (2 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(b) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDHU.D *") == s) {
-	C67_g((C67_map_regn(b) << 23) |	//dst
-	      (C67_map_regn(a) << 18) |	//base reg A15
-	      (0 << 13) |	//cst5
-	      (1 << 9) |	//mode 1 = pos cst offset
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
-	      (0 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(b) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDBU.D *") == s) {
-	C67_g((C67_map_regn(b) << 23) |	//dst
-	      (C67_map_regn(a) << 18) |	//base reg A15
-	      (0 << 13) |	//cst5
-	      (1 << 9) |	//mode 1 = pos cst offset
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
-	      (1 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(b) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "LDW.D +*") == s) {
-	C67_g((C67_map_regn(b) << 23) |	//dst
-	      (C67_map_regn(a) << 18) |	//base reg A15
-	      (1 << 13) |	//cst5
-	      (1 << 9) |	//mode 1 = pos cst offset
-	      (0 << 8) |	//r (LDDW bit 0)
-	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
-	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 
-	      (1 << 2) |	//opcode
-	      (C67_map_regs(b) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "CMPLTSP") == s) {
-	xpath = C67_map_regs(a) ^ C67_map_regs(b);
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1
-	      (xpath << 12) |	//x use cross path for src2
-	      (0x3a << 6) |	//opcode
-	      (0x8 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side for reg c
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "CMPGTSP") == s) {
-	xpath = C67_map_regs(a) ^ C67_map_regs(b);
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1
-	      (xpath << 12) |	//x use cross path for src2
-	      (0x39 << 6) |	//opcode
-	      (0x8 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side for reg c
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "CMPEQSP") == s) {
-	xpath = C67_map_regs(a) ^ C67_map_regs(b);
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1
-	      (xpath << 12) |	//x use cross path for src2
-	      (0x38 << 6) |	//opcode
-	      (0x8 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side for reg c
-	      (0 << 0));	//parallel
-    }
-
-    else if (strstr(s, "CMPLTDP") == s) {
-	xpath = C67_map_regs(a) ^ C67_map_regs(b);
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1
-	      (xpath << 12) |	//x use cross path for src2
-	      (0x2a << 6) |	//opcode
-	      (0x8 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side for reg c
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "CMPGTDP") == s) {
-	xpath = C67_map_regs(a) ^ C67_map_regs(b);
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1
-	      (xpath << 12) |	//x use cross path for src2
-	      (0x29 << 6) |	//opcode
-	      (0x8 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side for reg c
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "CMPEQDP") == s) {
-	xpath = C67_map_regs(a) ^ C67_map_regs(b);
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1
-	      (xpath << 12) |	//x use cross path for src2
-	      (0x28 << 6) |	//opcode
-	      (0x8 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side for reg c
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "CMPLT") == s) {
-	xpath = C67_map_regs(a) ^ C67_map_regs(b);
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1
-	      (xpath << 12) |	//x use cross path for src2
-	      (0x57 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side for reg c
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "CMPGT") == s) {
-	xpath = C67_map_regs(a) ^ C67_map_regs(b);
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1
-	      (xpath << 12) |	//x use cross path for src2
-	      (0x47 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side for reg c
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "CMPEQ") == s) {
-	xpath = C67_map_regs(a) ^ C67_map_regs(b);
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1
-	      (xpath << 12) |	//x use cross path for src2
-	      (0x53 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side for reg c
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "CMPLTU") == s) {
-	xpath = C67_map_regs(a) ^ C67_map_regs(b);
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1
-	      (xpath << 12) |	//x use cross path for src2
-	      (0x5f << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side for reg c
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "CMPGTU") == s) {
-	xpath = C67_map_regs(a) ^ C67_map_regs(b);
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1
-	      (xpath << 12) |	//x use cross path for src2
-	      (0x4f << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side for reg c
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "B DISP") == s) {
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//z
-	      (a << 7) |	//cnst
-	      (0x4 << 2) |	//opcode fixed
-	      (0 << 1) |	//S0/S1
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "B.") == s) {
-	xpath = C67_map_regs(c) ^ 1;
-
-	C67_g((C67_map_regc(b) << 29) |	//creg
-	      (a << 28) |	//inv
-	      (0 << 23) |	//dst
-	      (C67_map_regn(c) << 18) |	//src2
-	      (0 << 13) |	//
-	      (xpath << 12) |	//x cross path if !B side
-	      (0xd << 6) |	//opcode
-	      (0x8 << 2) |	//opcode fixed
-	      (1 << 1) |	//must be S2
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "MV.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (0 << 13) |	//src1 (cst5)
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x2 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "SPTRUNC.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (0 << 13) |	//src1 NA
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0xb << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "DPTRUNC.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      ((C67_map_regn(b) + 1) << 18) |	//src2   WEIRD CPU must specify odd reg for some reason
-	      (0 << 13) |	//src1 NA
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x1 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "INTSP.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2   
-	      (0 << 13) |	//src1 NA
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x4a << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "INTSPU.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2  
-	      (0 << 13) |	//src1 NA
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x49 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "INTDP.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2  
-	      (0 << 13) |	//src1 NA
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x39 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "INTDPU.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      ((C67_map_regn(b) + 1) << 18) |	//src2   WEIRD CPU must specify odd reg for some reason
-	      (0 << 13) |	//src1 NA
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x3b << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "SPDP.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (0 << 13) |	//src1 NA
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x2 << 6) |	//opcode
-	      (0x8 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "DPSP.L") == s) {
-	ALWAYS_ASSERT(C67_map_regs(b) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      ((C67_map_regn(b) + 1) << 18) |	//src2 WEIRD CPU must specify odd reg for some reason
-	      (0 << 13) |	//src1 NA
-	      (0 << 12) |	//x cross path if opposite sides
-	      (0x9 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "ADD.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x3 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "SUB.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x7 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "OR.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x7f << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "AND.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x7b << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "XOR.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x6f << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "ADDSP.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x10 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "ADDDP.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x18 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "SUBSP.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x11 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "SUBDP.L") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x19 << 5) |	//opcode
-	      (0x6 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "MPYSP.M") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x1c << 7) |	//opcode
-	      (0x0 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "MPYDP.M") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x0e << 7) |	//opcode
-	      (0x0 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "MPYI.M") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1 (cst5)
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x4 << 7) |	//opcode
-	      (0x0 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "SHR.S") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x37 << 6) |	//opcode
-	      (0x8 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "SHRU.S") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x27 << 6) |	//opcode
-	      (0x8 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "SHL.S") == s) {
-	xpath = C67_map_regs(b) ^ C67_map_regs(c);
-
-	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(c) << 23) |	//dst
-	      (C67_map_regn(b) << 18) |	//src2
-	      (C67_map_regn(a) << 13) |	//src1 
-	      (xpath << 12) |	//x cross path if opposite sides
-	      (0x33 << 6) |	//opcode
-	      (0x8 << 2) |	//opcode fixed
-	      (C67_map_regs(c) << 1) |	//side of dest
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "||ADDK") == s) {
-	xpath = 0;		// no xpath required just use the side of the src/dst
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(b) << 23) |	//dst
-	      (a << 07) |	//scst16
-	      (0x14 << 2) |	//opcode fixed
-	      (C67_map_regs(b) << 1) |	//side of dst
-	      (1 << 0));	//parallel
-    } else if (strstr(s, "ADDK") == s) {
-	xpath = 0;		// no xpath required just use the side of the src/dst
-
-	C67_g((0 << 29) |	//creg
-	      (0 << 28) |	//inv
-	      (C67_map_regn(b) << 23) |	//dst
-	      (a << 07) |	//scst16
-	      (0x14 << 2) |	//opcode fixed
-	      (C67_map_regs(b) << 1) |	//side of dst
-	      (0 << 0));	//parallel
-    } else if (strstr(s, "NOP") == s) {
-	C67_g(((a - 1) << 13) |	//no of cycles
-	      (0 << 0));	//parallel
-    } else
-	ALWAYS_ASSERT(FALSE);
-
-#ifdef ASSEMBLY_LISTING_C67
-    fprintf(f, " %s %d %d %d\n", s, a, b, c);
-#endif
-
-}
-
-//r=reg to load, fr=from reg, symbol for relocation, constant
-
-void C67_MVKL(int r, int fc)
-{
-    C67_asm("MVKL.", fc, r, 0);
-}
-
-void C67_MVKH(int r, int fc)
-{
-    C67_asm("MVKH.", fc, r, 0);
-}
-
-void C67_STB_SP_A0(int r)
-{
-    C67_asm("STB.D *+SP[A0]", r, 0, 0);	// STB  r,*+SP[A0]
-}
-
-void C67_STH_SP_A0(int r)
-{
-    C67_asm("STH.D *+SP[A0]", r, 0, 0);	// STH  r,*+SP[A0]
-}
-
-void C67_STW_SP_A0(int r)
-{
-    C67_asm("STW.D *+SP[A0]", r, 0, 0);	// STW  r,*+SP[A0]
-}
-
-void C67_STB_PTR(int r, int r2)
-{
-    C67_asm("STB.D *", r, r2, 0);	// STB  r, *r2
-}
-
-void C67_STH_PTR(int r, int r2)
-{
-    C67_asm("STH.D *", r, r2, 0);	// STH  r, *r2
-}
-
-void C67_STW_PTR(int r, int r2)
-{
-    C67_asm("STW.D *", r, r2, 0);	// STW  r, *r2
-}
-
-void C67_STW_PTR_PRE_INC(int r, int r2, int n)
-{
-    C67_asm("STW.D +*", r, r2, n);	// STW  r, *+r2
-}
-
-void C67_PUSH(int r)
-{
-    C67_asm("STW.D SP POST DEC", r, 0, 0);	// STW  r,*SP--
-}
-
-void C67_LDW_SP_A0(int r)
-{
-    C67_asm("LDW.D *+SP[A0]", r, 0, 0);	// LDW  *+SP[A0],r
-}
-
-void C67_LDDW_SP_A0(int r)
-{
-    C67_asm("LDDW.D *+SP[A0]", r, 0, 0);	// LDDW  *+SP[A0],r
-}
-
-void C67_LDH_SP_A0(int r)
-{
-    C67_asm("LDH.D *+SP[A0]", r, 0, 0);	// LDH  *+SP[A0],r
-}
-
-void C67_LDB_SP_A0(int r)
-{
-    C67_asm("LDB.D *+SP[A0]", r, 0, 0);	// LDB  *+SP[A0],r
-}
-
-void C67_LDHU_SP_A0(int r)
-{
-    C67_asm("LDHU.D *+SP[A0]", r, 0, 0);	// LDHU  *+SP[A0],r
-}
-
-void C67_LDBU_SP_A0(int r)
-{
-    C67_asm("LDBU.D *+SP[A0]", r, 0, 0);	// LDBU  *+SP[A0],r
-}
-
-void C67_LDW_PTR(int r, int r2)
-{
-    C67_asm("LDW.D *", r, r2, 0);	// LDW  *r,r2
-}
-
-void C67_LDDW_PTR(int r, int r2)
-{
-    C67_asm("LDDW.D *", r, r2, 0);	// LDDW  *r,r2
-}
-
-void C67_LDH_PTR(int r, int r2)
-{
-    C67_asm("LDH.D *", r, r2, 0);	// LDH  *r,r2
-}
-
-void C67_LDB_PTR(int r, int r2)
-{
-    C67_asm("LDB.D *", r, r2, 0);	// LDB  *r,r2
-}
-
-void C67_LDHU_PTR(int r, int r2)
-{
-    C67_asm("LDHU.D *", r, r2, 0);	// LDHU  *r,r2
-}
-
-void C67_LDBU_PTR(int r, int r2)
-{
-    C67_asm("LDBU.D *", r, r2, 0);	// LDBU  *r,r2
-}
-
-void C67_LDW_PTR_PRE_INC(int r, int r2)
-{
-    C67_asm("LDW.D +*", r, r2, 0);	// LDW  *+r,r2
-}
-
-void C67_POP(int r)
-{
-    C67_asm("LDW.D SP PRE INC", r, 0, 0);	// LDW  *++SP,r
-}
-
-void C67_POP_DW(int r)
-{
-    C67_asm("LDDW.D SP PRE INC", r, 0, 0);	// LDDW  *++SP,r
-}
-
-void C67_CMPLT(int s1, int s2, int dst)
-{
-    C67_asm("CMPLT.L1", s1, s2, dst);
-}
-
-void C67_CMPGT(int s1, int s2, int dst)
-{
-    C67_asm("CMPGT.L1", s1, s2, dst);
-}
-
-void C67_CMPEQ(int s1, int s2, int dst)
-{
-    C67_asm("CMPEQ.L1", s1, s2, dst);
-}
-
-void C67_CMPLTU(int s1, int s2, int dst)
-{
-    C67_asm("CMPLTU.L1", s1, s2, dst);
-}
-
-void C67_CMPGTU(int s1, int s2, int dst)
-{
-    C67_asm("CMPGTU.L1", s1, s2, dst);
-}
-
-
-void C67_CMPLTSP(int s1, int s2, int dst)
-{
-    C67_asm("CMPLTSP.S1", s1, s2, dst);
-}
-
-void C67_CMPGTSP(int s1, int s2, int dst)
-{
-    C67_asm("CMPGTSP.S1", s1, s2, dst);
-}
-
-void C67_CMPEQSP(int s1, int s2, int dst)
-{
-    C67_asm("CMPEQSP.S1", s1, s2, dst);
-}
-
-void C67_CMPLTDP(int s1, int s2, int dst)
-{
-    C67_asm("CMPLTDP.S1", s1, s2, dst);
-}
-
-void C67_CMPGTDP(int s1, int s2, int dst)
-{
-    C67_asm("CMPGTDP.S1", s1, s2, dst);
-}
-
-void C67_CMPEQDP(int s1, int s2, int dst)
-{
-    C67_asm("CMPEQDP.S1", s1, s2, dst);
-}
-
-
-void C67_IREG_B_REG(int inv, int r1, int r2)	// [!R] B  r2
-{
-    C67_asm("B.S2", inv, r1, r2);
-}
-
-
-// call with how many 32 bit words to skip
-// (0 would branch to the branch instruction)
-
-void C67_B_DISP(int disp)	//  B  +2  Branch with constant displacement
-{
-    // Branch point is relative to the 8 word fetch packet
-    //
-    // we will assume the text section always starts on an 8 word (32 byte boundary)
-    //
-    // so add in how many words into the fetch packet the branch is
-
-
-    C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
-}
-
-void C67_NOP(int n)
-{
-    C67_asm("NOP", n, 0, 0);
-}
-
-void C67_ADDK(int n, int r)
-{
-    ALWAYS_ASSERT(abs(n) < 32767);
-
-    C67_asm("ADDK", n, r, 0);
-}
-
-void C67_ADDK_PARALLEL(int n, int r)
-{
-    ALWAYS_ASSERT(abs(n) < 32767);
-
-    C67_asm("||ADDK", n, r, 0);
-}
-
-void C67_Adjust_ADDK(int *inst, int n)
-{
-    ALWAYS_ASSERT(abs(n) < 32767);
-
-    *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
-}
-
-void C67_MV(int r, int v)
-{
-    C67_asm("MV.L", 0, r, v);
-}
-
-
-void C67_DPTRUNC(int r, int v)
-{
-    C67_asm("DPTRUNC.L", 0, r, v);
-}
-
-void C67_SPTRUNC(int r, int v)
-{
-    C67_asm("SPTRUNC.L", 0, r, v);
-}
-
-void C67_INTSP(int r, int v)
-{
-    C67_asm("INTSP.L", 0, r, v);
-}
-
-void C67_INTDP(int r, int v)
-{
-    C67_asm("INTDP.L", 0, r, v);
-}
-
-void C67_INTSPU(int r, int v)
-{
-    C67_asm("INTSPU.L", 0, r, v);
-}
-
-void C67_INTDPU(int r, int v)
-{
-    C67_asm("INTDPU.L", 0, r, v);
-}
-
-void C67_SPDP(int r, int v)
-{
-    C67_asm("SPDP.L", 0, r, v);
-}
-
-void C67_DPSP(int r, int v)	// note regs must be on the same side
-{
-    C67_asm("DPSP.L", 0, r, v);
-}
-
-void C67_ADD(int r, int v)
-{
-    C67_asm("ADD.L", v, r, v);
-}
-
-void C67_SUB(int r, int v)
-{
-    C67_asm("SUB.L", v, r, v);
-}
-
-void C67_AND(int r, int v)
-{
-    C67_asm("AND.L", v, r, v);
-}
-
-void C67_OR(int r, int v)
-{
-    C67_asm("OR.L", v, r, v);
-}
-
-void C67_XOR(int r, int v)
-{
-    C67_asm("XOR.L", v, r, v);
-}
-
-void C67_ADDSP(int r, int v)
-{
-    C67_asm("ADDSP.L", v, r, v);
-}
-
-void C67_SUBSP(int r, int v)
-{
-    C67_asm("SUBSP.L", v, r, v);
-}
-
-void C67_MPYSP(int r, int v)
-{
-    C67_asm("MPYSP.M", v, r, v);
-}
-
-void C67_ADDDP(int r, int v)
-{
-    C67_asm("ADDDP.L", v, r, v);
-}
-
-void C67_SUBDP(int r, int v)
-{
-    C67_asm("SUBDP.L", v, r, v);
-}
-
-void C67_MPYDP(int r, int v)
-{
-    C67_asm("MPYDP.M", v, r, v);
-}
-
-void C67_MPYI(int r, int v)
-{
-    C67_asm("MPYI.M", v, r, v);
-}
-
-void C67_SHL(int r, int v)
-{
-    C67_asm("SHL.S", r, v, v);
-}
-
-void C67_SHRU(int r, int v)
-{
-    C67_asm("SHRU.S", r, v, v);
-}
-
-void C67_SHR(int r, int v)
-{
-    C67_asm("SHR.S", r, v, v);
-}
-
-
-
-/* load 'r' from value 'sv' */
-void load(int r, SValue * sv)
-{
-    int v, t, ft, fc, fr, size = 0, element;
-    BOOL Unsigned = false;
-    SValue v1;
-
-    fr = sv->r;
-    ft = sv->type.t;
-    fc = sv->c.ul;
-
-    v = fr & VT_VALMASK;
-    if (fr & VT_LVAL) {
-	if (v == VT_LLOCAL) {
-	    v1.type.t = VT_INT;
-	    v1.r = VT_LOCAL | VT_LVAL;
-	    v1.c.ul = fc;
-	    load(r, &v1);
-	    fr = r;
-	} else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
-	    error("long double not supported");
-	} else if ((ft & VT_TYPE) == VT_BYTE) {
-	    size = 1;
-	} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
-	    size = 1;
-	    Unsigned = TRUE;
-	} else if ((ft & VT_TYPE) == VT_SHORT) {
-	    size = 2;
-	} else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
-	    size = 2;
-	    Unsigned = TRUE;
-	} else if ((ft & VT_BTYPE) == VT_DOUBLE) {
-	    size = 8;
-	} else {
-	    size = 4;
-	}
-
-	// check if fc is a positive reference on the stack, 
-	// if it is tcc is referencing what it thinks is a parameter
-	// on the stack, so check if it is really in a register.
-
-
-	if (v == VT_LOCAL && fc > 0) {
-	    int stack_pos = 8;
-
-	    for (t = 0; t < NoCallArgsPassedOnStack; t++) {
-		if (fc == stack_pos)
-		    break;
-
-		stack_pos += TranslateStackToReg[t];
-	    }
-
-	    // param has been pushed on stack, get it like a local var
-
-	    fc = ParamLocOnStack[t] - 8;
-	}
-
-	if ((fr & VT_VALMASK) < VT_CONST)	// check for pure indirect
-	{
-	    if (size == 1) {
-		if (Unsigned)
-		    C67_LDBU_PTR(v, r);	// LDBU  *v,r
-		else
-		    C67_LDB_PTR(v, r);	// LDB  *v,r
-	    } else if (size == 2) {
-		if (Unsigned)
-		    C67_LDHU_PTR(v, r);	// LDHU  *v,r
-		else
-		    C67_LDH_PTR(v, r);	// LDH  *v,r
-	    } else if (size == 4) {
-		C67_LDW_PTR(v, r);	// LDW  *v,r
-	    } else if (size == 8) {
-		C67_LDDW_PTR(v, r);	// LDDW  *v,r
-	    }
-
-	    C67_NOP(4);		// NOP 4
-	    return;
-	} else if (fr & VT_SYM) {
-	    greloc(cur_text_section, sv->sym, ind, R_C60LO16);	// rem the inst need to be patched
-	    greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
-
-
-	    C67_MVKL(C67_A0, fc);	//r=reg to load,  constant
-	    C67_MVKH(C67_A0, fc);	//r=reg to load,  constant
-
-
-	    if (size == 1) {
-		if (Unsigned)
-		    C67_LDBU_PTR(C67_A0, r);	// LDBU  *A0,r
-		else
-		    C67_LDB_PTR(C67_A0, r);	// LDB  *A0,r
-	    } else if (size == 2) {
-		if (Unsigned)
-		    C67_LDHU_PTR(C67_A0, r);	// LDHU  *A0,r
-		else
-		    C67_LDH_PTR(C67_A0, r);	// LDH  *A0,r
-	    } else if (size == 4) {
-		C67_LDW_PTR(C67_A0, r);	// LDW  *A0,r
-	    } else if (size == 8) {
-		C67_LDDW_PTR(C67_A0, r);	// LDDW  *A0,r
-	    }
-
-	    C67_NOP(4);		// NOP 4
-	    return;
-	} else {
-	    element = size;
-
-	    // divide offset in bytes to create element index
-	    C67_MVKL(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
-	    C67_MVKH(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
-
-	    if (size == 1) {
-		if (Unsigned)
-		    C67_LDBU_SP_A0(r);	// LDBU  r, SP[A0]
-		else
-		    C67_LDB_SP_A0(r);	// LDB  r, SP[A0]
-	    } else if (size == 2) {
-		if (Unsigned)
-		    C67_LDHU_SP_A0(r);	// LDHU  r, SP[A0]
-		else
-		    C67_LDH_SP_A0(r);	// LDH  r, SP[A0]
-	    } else if (size == 4) {
-		C67_LDW_SP_A0(r);	// LDW  r, SP[A0]
-	    } else if (size == 8) {
-		C67_LDDW_SP_A0(r);	// LDDW  r, SP[A0]
-	    }
-
-
-	    C67_NOP(4);		// NOP 4
-	    return;
-	}
-    } else {
-	if (v == VT_CONST) {
-	    if (fr & VT_SYM) {
-		greloc(cur_text_section, sv->sym, ind, R_C60LO16);	// rem the inst need to be patched
-		greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
-	    }
-	    C67_MVKL(r, fc);	//r=reg to load, constant
-	    C67_MVKH(r, fc);	//r=reg to load, constant
-	} else if (v == VT_LOCAL) {
-	    C67_MVKL(r, fc + 8);	//r=reg to load, constant C67 stack points to next free
-	    C67_MVKH(r, fc + 8);	//r=reg to load, constant
-	    C67_ADD(C67_FP, r);	// MV v,r   v -> r
-	} else if (v == VT_CMP) {
-	    C67_MV(C67_compare_reg, r);	// MV v,r   v -> r
-	} else if (v == VT_JMP || v == VT_JMPI) {
-	    t = v & 1;
-	    C67_B_DISP(4);	//  Branch with constant displacement, skip over this branch, load, nop, load
-	    C67_MVKL(r, t);	//  r=reg to load, 0 or 1 (do this while branching)
-	    C67_NOP(4);		//  NOP 4
-	    gsym(fc);		//  modifies other branches to branch here
-	    C67_MVKL(r, t ^ 1);	//  r=reg to load, 0 or 1
-	} else if (v != r) {
-	    C67_MV(v, r);	// MV v,r   v -> r
-
-	    if ((ft & VT_BTYPE) == VT_DOUBLE)
-		C67_MV(v + 1, r + 1);	// MV v,r   v -> r
-	}
-    }
-}
-
-
-/* store register 'r' in lvalue 'v' */
-void store(int r, SValue * v)
-{
-    int fr, bt, ft, fc, size, t, element;
-
-    ft = v->type.t;
-    fc = v->c.ul;
-    fr = v->r & VT_VALMASK;
-    bt = ft & VT_BTYPE;
-    /* XXX: incorrect if float reg to reg */
-
-    if (bt == VT_LDOUBLE) {
-	error("long double not supported");
-    } else {
-	if (bt == VT_SHORT)
-	    size = 2;
-	else if (bt == VT_BYTE)
-	    size = 1;
-	else if (bt == VT_DOUBLE)
-	    size = 8;
-	else
-	    size = 4;
-
-	if ((v->r & VT_VALMASK) == VT_CONST) {
-	    /* constant memory reference */
-
-	    if (v->r & VT_SYM) {
-		greloc(cur_text_section, v->sym, ind, R_C60LO16);	// rem the inst need to be patched
-		greloc(cur_text_section, v->sym, ind + 4, R_C60HI16);
-	    }
-	    C67_MVKL(C67_A0, fc);	//r=reg to load,  constant
-	    C67_MVKH(C67_A0, fc);	//r=reg to load,  constant
-
-	    if (size == 1)
-		C67_STB_PTR(r, C67_A0);	// STB  r, *A0
-	    else if (size == 2)
-		C67_STH_PTR(r, C67_A0);	// STH  r, *A0
-	    else if (size == 4 || size == 8)
-		C67_STW_PTR(r, C67_A0);	// STW  r, *A0
-
-	    if (size == 8)
-		C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1);	// STW  r, *+A0[1]
-	} else if ((v->r & VT_VALMASK) == VT_LOCAL) {
-	    // check case of storing to passed argument that
-	    // tcc thinks is on the stack but for C67 is
-	    // passed as a reg.  However it may have been
-	    // saved to the stack, if that reg was required
-	    // for a call to a child function
-
-	    if (fc > 0)		// argument ??
-	    {
-		// walk through sizes and figure which param
-
-		int stack_pos = 8;
-
-		for (t = 0; t < NoCallArgsPassedOnStack; t++) {
-		    if (fc == stack_pos)
-			break;
-
-		    stack_pos += TranslateStackToReg[t];
-		}
-
-		// param has been pushed on stack, get it like a local var
-		fc = ParamLocOnStack[t] - 8;
-	    }
-
-	    if (size == 8)
-		element = 4;
-	    else
-		element = size;
-
-	    // divide offset in bytes to create word index
-	    C67_MVKL(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
-	    C67_MVKH(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
-
-
-
-	    if (size == 1)
-		C67_STB_SP_A0(r);	// STB  r, SP[A0]
-	    else if (size == 2)
-		C67_STH_SP_A0(r);	// STH  r, SP[A0]
-	    else if (size == 4 || size == 8)
-		C67_STW_SP_A0(r);	// STW  r, SP[A0]
-
-	    if (size == 8) {
-		C67_ADDK(1, C67_A0);	//  ADDK 1,A0
-		C67_STW_SP_A0(r + 1);	//  STW  r, SP[A0]
-	    }
-	} else {
-	    if (size == 1)
-		C67_STB_PTR(r, fr);	// STB  r, *fr
-	    else if (size == 2)
-		C67_STH_PTR(r, fr);	// STH  r, *fr
-	    else if (size == 4 || size == 8)
-		C67_STW_PTR(r, fr);	// STW  r, *fr
-
-	    if (size == 8) {
-		C67_STW_PTR_PRE_INC(r + 1, fr, 1);	// STW  r, *+fr[1]
-	    }
-	}
-    }
-}
-
-/* 'is_jmp' is '1' if it is a jump */
-static void gcall_or_jmp(int is_jmp)
-{
-    int r;
-    Sym *sym;
-
-    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
-	/* constant case */
-	if (vtop->r & VT_SYM) {
-	    /* relocation case */
-
-	    // get add into A0, then start the jump B3
-
-	    greloc(cur_text_section, vtop->sym, ind, R_C60LO16);	// rem the inst need to be patched
-	    greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);
-
-	    C67_MVKL(C67_A0, 0);	//r=reg to load, constant
-	    C67_MVKH(C67_A0, 0);	//r=reg to load, constant
-	    C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0);	//  B.S2x  A0
-
-	    if (is_jmp) {
-		C67_NOP(5);	// simple jump, just put NOP
-	    } else {
-		// Call, must load return address into B3 during delay slots
-
-		sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0);	// symbol for return address
-		greloc(cur_text_section, sym, ind, R_C60LO16);	// rem the inst need to be patched
-		greloc(cur_text_section, sym, ind + 4, R_C60HI16);
-		C67_MVKL(C67_B3, 0);	//r=reg to load, constant
-		C67_MVKH(C67_B3, 0);	//r=reg to load, constant
-		C67_NOP(3);	// put remaining NOPs
-	    }
-	} else {
-	    /* put an empty PC32 relocation */
-	    ALWAYS_ASSERT(FALSE);
-	}
-    } else {
-	/* otherwise, indirect call */
-	r = gv(RC_INT);
-	C67_IREG_B_REG(0, C67_CREG_ZERO, r);	//  B.S2x  r
-
-	if (is_jmp) {
-	    C67_NOP(5);		// simple jump, just put NOP
-	} else {
-	    // Call, must load return address into B3 during delay slots
-
-	    sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0);	// symbol for return address
-	    greloc(cur_text_section, sym, ind, R_C60LO16);	// rem the inst need to be patched
-	    greloc(cur_text_section, sym, ind + 4, R_C60HI16);
-	    C67_MVKL(C67_B3, 0);	//r=reg to load, constant
-	    C67_MVKH(C67_B3, 0);	//r=reg to load, constant
-	    C67_NOP(3);		// put remaining NOPs
-	}
-    }
-}
-
-/* generate function call with address in (vtop->t, vtop->c) and free function
-   context. Stack entry is popped */
-void gfunc_call(int nb_args)
-{
-    int i, r, size = 0;
-    int args_sizes[NoCallArgsPassedOnStack];
-
-    if (nb_args > NoCallArgsPassedOnStack) {
-	error("more than 10 function params not currently supported");
-	// handle more than 10, put some on the stack
-    }
-
-    for (i = 0; i < nb_args; i++) {
-	if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
-	    ALWAYS_ASSERT(FALSE);
-	} else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
-	    ALWAYS_ASSERT(FALSE);
-	} else {
-	    /* simple type (currently always same size) */
-	    /* XXX: implicit cast ? */
-
-
-	    if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
-		error("long long not supported");
-	    } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
-		error("long double not supported");
-	    } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
-		size = 8;
-	    } else {
-		size = 4;
-	    }
-
-	    // put the parameter into the corresponding reg (pair)
-
-	    r = gv(RC_C67_A4 << (2 * i));
-
-	    // must put on stack because with 1 pass compiler , no way to tell
-	    // if an up coming nested call might overwrite these regs
-
-	    C67_PUSH(r);
-
-	    if (size == 8) {
-		C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3);	// STW  r, *+SP[3] (go back and put the other)
-	    }
-	    args_sizes[i] = size;
-	}
-	vtop--;
-    }
-    // POP all the params on the stack into registers for the
-    // immediate call (in reverse order)
-
-    for (i = nb_args - 1; i >= 0; i--) {
-
-	if (args_sizes[i] == 8)
-	    C67_POP_DW(TREG_C67_A4 + i * 2);
-	else
-	    C67_POP(TREG_C67_A4 + i * 2);
-    }
-    gcall_or_jmp(0);
-    vtop--;
-}
-
-
-// to be compatible with Code Composer for the C67
-// the first 10 parameters must be passed in registers
-// (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
-// ending with B12:B13.
-//
-// When a call is made, if the caller has its parameters
-// in regs A4-B13 these must be saved before/as the call 
-// parameters are loaded and restored upon return (or if/when needed).
-
-/* generate function prolog of type 't' */
-void gfunc_prolog(CType * func_type)
-{
-    int addr, align, size, func_call, i;
-    Sym *sym;
-    CType *type;
-
-    sym = func_type->ref;
-    func_call = sym->r;
-    addr = 8;
-    /* if the function returns a structure, then add an
-       implicit pointer parameter */
-    func_vt = sym->type;
-    if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
-	func_vc = addr;
-	addr += 4;
-    }
-
-    NoOfCurFuncArgs = 0;
-
-    /* define parameters */
-    while ((sym = sym->next) != NULL) {
-	type = &sym->type;
-	sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
-	size = type_size(type, &align);
-	size = (size + 3) & ~3;
-
-	// keep track of size of arguments so
-	// we can translate where tcc thinks they
-	// are on the stack into the appropriate reg
-
-	TranslateStackToReg[NoOfCurFuncArgs] = size;
-	NoOfCurFuncArgs++;
-
-#ifdef FUNC_STRUCT_PARAM_AS_PTR
-	/* structs are passed as pointer */
-	if ((type->t & VT_BTYPE) == VT_STRUCT) {
-	    size = 4;
-	}
-#endif
-	addr += size;
-    }
-    func_ret_sub = 0;
-    /* pascal type call ? */
-    if (func_call == FUNC_STDCALL)
-	func_ret_sub = addr - 8;
-
-    C67_MV(C67_FP, C67_A0);	//  move FP -> A0
-    C67_MV(C67_SP, C67_FP);	//  move SP -> FP
-
-    // place all the args passed in regs onto the stack
-
-    loc = 0;
-    for (i = 0; i < NoOfCurFuncArgs; i++) {
-
-	ParamLocOnStack[i] = loc;	// remember where the param is
-	loc += -8;
-
-	C67_PUSH(TREG_C67_A4 + i * 2);
-
-	if (TranslateStackToReg[i] == 8) {
-	    C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3);	// STW  r, *+SP[1] (go back and put the other)
-	}
-    }
-
-    TotalBytesPushedOnStack = -loc;
-
-    func_sub_sp_offset = ind;	// remember where we put the stack instruction 
-    C67_ADDK(0, C67_SP);	//  ADDK.L2 loc,SP  (just put zero temporarily)
-
-    C67_PUSH(C67_A0);
-    C67_PUSH(C67_B3);
-}
-
-/* generate function epilog */
-void gfunc_epilog(void)
-{
-    {
-	int local = (-loc + 7) & -8;	// stack must stay aligned to 8 bytes for LDDW instr
-	C67_POP(C67_B3);
-	C67_NOP(4);		// NOP wait for load
-	C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3);	//  B.S2  B3
-	C67_POP(C67_FP);
-	C67_ADDK(local, C67_SP);	//  ADDK.L2 loc,SP  
-	C67_Adjust_ADDK((int *) (cur_text_section->data +
-				 func_sub_sp_offset),
-			-local + TotalBytesPushedOnStack);
-	C67_NOP(3);		// NOP 
-    }
-}
-
-/* generate a jump to a label */
-int gjmp(int t)
-{
-    int ind1 = ind;
-
-    C67_MVKL(C67_A0, t);	//r=reg to load,  constant
-    C67_MVKH(C67_A0, t);	//r=reg to load,  constant
-    C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0);	// [!R] B.S2x  A0
-    C67_NOP(5);
-    return ind1;
-}
-
-/* generate a jump to a fixed address */
-void gjmp_addr(int a)
-{
-    Sym *sym;
-    // I guess this routine is used for relative short
-    // local jumps, for now just handle it as the general
-    // case
-
-    // define a label that will be relocated
-
-    sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
-    greloc(cur_text_section, sym, ind, R_C60LO16);
-    greloc(cur_text_section, sym, ind + 4, R_C60HI16);
-
-    gjmp(0);			// place a zero there later the symbol will be added to it
-}
-
-/* generate a test. set 'inv' to invert test. Stack entry is popped */
-int gtst(int inv, int t)
-{
-    int ind1, n;
-    int v, *p;
-
-    v = vtop->r & VT_VALMASK;
-    if (v == VT_CMP) {
-	/* fast case : can jump directly since flags are set */
-	// C67 uses B2 sort of as flags register
-	ind1 = ind;
-	C67_MVKL(C67_A0, t);	//r=reg to load, constant
-	C67_MVKH(C67_A0, t);	//r=reg to load, constant
-
-	if (C67_compare_reg != TREG_EAX &&	// check if not already in a conditional test reg
-	    C67_compare_reg != TREG_EDX &&
-	    C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
-	    C67_MV(C67_compare_reg, C67_B2);
-	    C67_compare_reg = C67_B2;
-	}
-
-	C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0);	// [!R] B.S2x  A0
-	C67_NOP(5);
-	t = ind1;		//return where we need to patch
-
-    } else if (v == VT_JMP || v == VT_JMPI) {
-	/* && or || optimization */
-	if ((v & 1) == inv) {
-	    /* insert vtop->c jump list in t */
-	    p = &vtop->c.i;
-
-	    // I guess the idea is to traverse to the
-	    // null at the end of the list and store t
-	    // there
-
-	    n = *p;
-	    while (n != 0) {
-		p = (int *) (cur_text_section->data + n);
-
-		// extract 32 bit address from MVKH/MVKL
-		n = ((*p >> 7) & 0xffff);
-		n |= ((*(p + 1) >> 7) & 0xffff) << 16;
-	    }
-	    *p |= (t & 0xffff) << 7;
-	    *(p + 1) |= ((t >> 16) & 0xffff) << 7;
-	    t = vtop->c.i;
-
-	} else {
-	    t = gjmp(t);
-	    gsym(vtop->c.i);
-	}
-    } else {
-	if (is_float(vtop->type.t)) {
-	    vpushi(0);
-	    gen_op(TOK_NE);
-	}
-	if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-	    /* constant jmp optimization */
-	    if ((vtop->c.i != 0) != inv)
-		t = gjmp(t);
-	} else {
-	    // I think we need to get the value on the stack
-	    // into a register, test it, and generate a branch
-	    // return the address of the branch, so it can be
-	    // later patched
-
-	    v = gv(RC_INT);	// get value into a reg 
-	    ind1 = ind;
-	    C67_MVKL(C67_A0, t);	//r=reg to load, constant
-	    C67_MVKH(C67_A0, t);	//r=reg to load, constant
-
-	    if (v != TREG_EAX &&	// check if not already in a conditional test reg
-		v != TREG_EDX && v != TREG_ST0 && v != C67_B2) {
-		C67_MV(v, C67_B2);
-		v = C67_B2;
-	    }
-
-	    C67_IREG_B_REG(inv, v, C67_A0);	// [!R] B.S2x  A0
-	    C67_NOP(5);
-	    t = ind1;		//return where we need to patch
-	    ind1 = ind;
-	}
-    }
-    vtop--;
-    return t;
-}
-
-/* generate an integer binary operation */
-void gen_opi(int op)
-{
-    int r, fr, opc, t;
-
-    switch (op) {
-    case '+':
-    case TOK_ADDC1:		/* add with carry generation */
-	opc = 0;
-      gen_op8:
-
-
-// C67 can't do const compares, must load into a reg
-// so just go to gv2 directly - tktk
-
-
-
-	if (op >= TOK_ULT && op <= TOK_GT)
-	    gv2(RC_INT_BSIDE, RC_INT);	// make sure r (src1) is on the B Side of CPU
-	else
-	    gv2(RC_INT, RC_INT);
-
-	r = vtop[-1].r;
-	fr = vtop[0].r;
-
-	C67_compare_reg = C67_B2;
-
-
-	if (op == TOK_LT) {
-	    C67_CMPLT(r, fr, C67_B2);
-	    C67_invert_test = false;
-	} else if (op == TOK_GE) {
-	    C67_CMPLT(r, fr, C67_B2);
-	    C67_invert_test = true;
-	} else if (op == TOK_GT) {
-	    C67_CMPGT(r, fr, C67_B2);
-	    C67_invert_test = false;
-	} else if (op == TOK_LE) {
-	    C67_CMPGT(r, fr, C67_B2);
-	    C67_invert_test = true;
-	} else if (op == TOK_EQ) {
-	    C67_CMPEQ(r, fr, C67_B2);
-	    C67_invert_test = false;
-	} else if (op == TOK_NE) {
-	    C67_CMPEQ(r, fr, C67_B2);
-	    C67_invert_test = true;
-	} else if (op == TOK_ULT) {
-	    C67_CMPLTU(r, fr, C67_B2);
-	    C67_invert_test = false;
-	} else if (op == TOK_UGE) {
-	    C67_CMPLTU(r, fr, C67_B2);
-	    C67_invert_test = true;
-	} else if (op == TOK_UGT) {
-	    C67_CMPGTU(r, fr, C67_B2);
-	    C67_invert_test = false;
-	} else if (op == TOK_ULE) {
-	    C67_CMPGTU(r, fr, C67_B2);
-	    C67_invert_test = true;
-	} else if (op == '+')
-	    C67_ADD(fr, r);	// ADD  r,fr,r
-	else if (op == '-')
-	    C67_SUB(fr, r);	// SUB  r,fr,r
-	else if (op == '&')
-	    C67_AND(fr, r);	// AND  r,fr,r
-	else if (op == '|')
-	    C67_OR(fr, r);	// OR  r,fr,r
-	else if (op == '^')
-	    C67_XOR(fr, r);	// XOR  r,fr,r
-	else
-	    ALWAYS_ASSERT(FALSE);
-
-	vtop--;
-	if (op >= TOK_ULT && op <= TOK_GT) {
-	    vtop->r = VT_CMP;
-	    vtop->c.i = op;
-	}
-	break;
-    case '-':
-    case TOK_SUBC1:		/* sub with carry generation */
-	opc = 5;
-	goto gen_op8;
-    case TOK_ADDC2:		/* add with carry use */
-	opc = 2;
-	goto gen_op8;
-    case TOK_SUBC2:		/* sub with carry use */
-	opc = 3;
-	goto gen_op8;
-    case '&':
-	opc = 4;
-	goto gen_op8;
-    case '^':
-	opc = 6;
-	goto gen_op8;
-    case '|':
-	opc = 1;
-	goto gen_op8;
-    case '*':
-    case TOK_UMULL:
-	gv2(RC_INT, RC_INT);
-	r = vtop[-1].r;
-	fr = vtop[0].r;
-	vtop--;
-	C67_MPYI(fr, r);	// 32 bit bultiply  fr,r,fr
-	C67_NOP(8);		// NOP 8 for worst case
-	break;
-    case TOK_SHL:
-	gv2(RC_INT_BSIDE, RC_INT_BSIDE);	// shift amount must be on same side as dst
-	r = vtop[-1].r;
-	fr = vtop[0].r;
-	vtop--;
-	C67_SHL(fr, r);		// arithmetic/logical shift
-	break;
-
-    case TOK_SHR:
-	gv2(RC_INT_BSIDE, RC_INT_BSIDE);	// shift amount must be on same side as dst
-	r = vtop[-1].r;
-	fr = vtop[0].r;
-	vtop--;
-	C67_SHRU(fr, r);	// logical shift
-	break;
-
-    case TOK_SAR:
-	gv2(RC_INT_BSIDE, RC_INT_BSIDE);	// shift amount must be on same side as dst
-	r = vtop[-1].r;
-	fr = vtop[0].r;
-	vtop--;
-	C67_SHR(fr, r);		// arithmetic shift
-	break;
-
-    case '/':
-	t = TOK__divi;
-      call_func:
-	vswap();
-	/* call generic idiv function */
-	vpush_global_sym(&func_old_type, t);
-	vrott(3);
-	gfunc_call(2);
-	vpushi(0);
-	vtop->r = REG_IRET;
-	vtop->r2 = VT_CONST;
-	break;
-    case TOK_UDIV:
-    case TOK_PDIV:
-	t = TOK__divu;
-	goto call_func;
-    case '%':
-	t = TOK__remi;
-	goto call_func;
-    case TOK_UMOD:
-	t = TOK__remu;
-	goto call_func;
-
-    default:
-	opc = 7;
-	goto gen_op8;
-    }
-}
-
-/* generate a floating point operation 'v = t1 op t2' instruction. The
-   two operands are guaranted to have the same floating point type */
-/* XXX: need to use ST1 too */
-void gen_opf(int op)
-{
-    int ft, fc, fr, r;
-
-    if (op >= TOK_ULT && op <= TOK_GT)
-	gv2(RC_EDX, RC_EAX);	// make sure src2 is on b side
-    else
-	gv2(RC_FLOAT, RC_FLOAT);	// make sure src2 is on b side
-
-    ft = vtop->type.t;
-    fc = vtop->c.ul;
-    r = vtop->r;
-    fr = vtop[-1].r;
-
-
-    if ((ft & VT_BTYPE) == VT_LDOUBLE)
-	error("long doubles not supported");
-
-    if (op >= TOK_ULT && op <= TOK_GT) {
-
-	r = vtop[-1].r;
-	fr = vtop[0].r;
-
-	C67_compare_reg = C67_B2;
-
-	if (op == TOK_LT) {
-	    if ((ft & VT_BTYPE) == VT_DOUBLE)
-		C67_CMPLTDP(r, fr, C67_B2);
-	    else
-		C67_CMPLTSP(r, fr, C67_B2);
-
-	    C67_invert_test = false;
-	} else if (op == TOK_GE) {
-	    if ((ft & VT_BTYPE) == VT_DOUBLE)
-		C67_CMPLTDP(r, fr, C67_B2);
-	    else
-		C67_CMPLTSP(r, fr, C67_B2);
-
-	    C67_invert_test = true;
-	} else if (op == TOK_GT) {
-	    if ((ft & VT_BTYPE) == VT_DOUBLE)
-		C67_CMPGTDP(r, fr, C67_B2);
-	    else
-		C67_CMPGTSP(r, fr, C67_B2);
-
-	    C67_invert_test = false;
-	} else if (op == TOK_LE) {
-	    if ((ft & VT_BTYPE) == VT_DOUBLE)
-		C67_CMPGTDP(r, fr, C67_B2);
-	    else
-		C67_CMPGTSP(r, fr, C67_B2);
-
-	    C67_invert_test = true;
-	} else if (op == TOK_EQ) {
-	    if ((ft & VT_BTYPE) == VT_DOUBLE)
-		C67_CMPEQDP(r, fr, C67_B2);
-	    else
-		C67_CMPEQSP(r, fr, C67_B2);
-
-	    C67_invert_test = false;
-	} else if (op == TOK_NE) {
-	    if ((ft & VT_BTYPE) == VT_DOUBLE)
-		C67_CMPEQDP(r, fr, C67_B2);
-	    else
-		C67_CMPEQSP(r, fr, C67_B2);
-
-	    C67_invert_test = true;
-	} else {
-	    ALWAYS_ASSERT(FALSE);
-	}
-	vtop->r = VT_CMP;	// tell TCC that result is in "flags" actually B2
-    } else {
-	if (op == '+') {
-	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
-		C67_ADDDP(r, fr);	// ADD  fr,r,fr
-		C67_NOP(6);
-	    } else {
-		C67_ADDSP(r, fr);	// ADD  fr,r,fr
-		C67_NOP(3);
-	    }
-	    vtop--;
-	} else if (op == '-') {
-	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
-		C67_SUBDP(r, fr);	// SUB  fr,r,fr
-		C67_NOP(6);
-	    } else {
-		C67_SUBSP(r, fr);	// SUB  fr,r,fr
-		C67_NOP(3);
-	    }
-	    vtop--;
-	} else if (op == '*') {
-	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
-		C67_MPYDP(r, fr);	// MPY  fr,r,fr
-		C67_NOP(9);
-	    } else {
-		C67_MPYSP(r, fr);	// MPY  fr,r,fr
-		C67_NOP(3);
-	    }
-	    vtop--;
-	} else if (op == '/') {
-	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
-		// must call intrinsic DP floating point divide
-		vswap();
-		/* call generic idiv function */
-		vpush_global_sym(&func_old_type, TOK__divd);
-		vrott(3);
-		gfunc_call(2);
-		vpushi(0);
-		vtop->r = REG_FRET;
-		vtop->r2 = REG_LRET;
-
-	    } else {
-		// must call intrinsic SP floating point divide
-		vswap();
-		/* call generic idiv function */
-		vpush_global_sym(&func_old_type, TOK__divf);
-		vrott(3);
-		gfunc_call(2);
-		vpushi(0);
-		vtop->r = REG_FRET;
-		vtop->r2 = VT_CONST;
-	    }
-	} else
-	    ALWAYS_ASSERT(FALSE);
-
-
-    }
-}
-
-
-/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
-   and 'long long' cases. */
-void gen_cvt_itof(int t)
-{
-    int r;
-
-    gv(RC_INT);
-    r = vtop->r;
-
-    if ((t & VT_BTYPE) == VT_DOUBLE) {
-	if (t & VT_UNSIGNED)
-	    C67_INTDPU(r, r);
-	else
-	    C67_INTDP(r, r);
-
-	C67_NOP(4);
-	vtop->type.t = VT_DOUBLE;
-    } else {
-	if (t & VT_UNSIGNED)
-	    C67_INTSPU(r, r);
-	else
-	    C67_INTSP(r, r);
-	C67_NOP(3);
-	vtop->type.t = VT_FLOAT;
-    }
-
-}
-
-/* convert fp to int 't' type */
-/* XXX: handle long long case */
-void gen_cvt_ftoi(int t)
-{
-    int r;
-
-    gv(RC_FLOAT);
-    r = vtop->r;
-
-    if (t != VT_INT)
-	error("long long not supported");
-    else {
-	if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
-	    C67_DPTRUNC(r, r);
-	    C67_NOP(3);
-	} else {
-	    C67_SPTRUNC(r, r);
-	    C67_NOP(3);
-	}
-
-	vtop->type.t = VT_INT;
-
-    }
-}
-
-/* convert from one floating point type to another */
-void gen_cvt_ftof(int t)
-{
-    int r, r2;
-
-    if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
-	(t & VT_BTYPE) == VT_FLOAT) {
-	// convert double to float
-
-	gv(RC_FLOAT);		// get it in a register pair
-
-	r = vtop->r;
-
-	C67_DPSP(r, r);		// convert it to SP same register
-	C67_NOP(3);
-
-	vtop->type.t = VT_FLOAT;
-	vtop->r2 = VT_CONST;	// set this as unused
-    } else if ((vtop->type.t & VT_BTYPE) == VT_FLOAT &&
-	       (t & VT_BTYPE) == VT_DOUBLE) {
-	// convert float to double
-
-	gv(RC_FLOAT);		// get it in a register
-
-	r = vtop->r;
-
-	if (r == TREG_EAX) {	// make sure the paired reg is avail
-	    r2 = get_reg(RC_ECX);
-	} else if (r == TREG_EDX) {
-	    r2 = get_reg(RC_ST0);
-	} else {
-	    ALWAYS_ASSERT(FALSE);
-            r2 = 0; /* avoid warning */
-        }
-
-	C67_SPDP(r, r);		// convert it to DP same register
-	C67_NOP(1);
-
-	vtop->type.t = VT_DOUBLE;
-	vtop->r2 = r2;		// set this as unused
-    } else {
-	ALWAYS_ASSERT(FALSE);
-    }
-}
-
-/* computed goto support */
-void ggoto(void)
-{
-    gcall_or_jmp(1);
-    vtop--;
-}
-
-/* end of X86 code generator */
-/*************************************************************/

+ 0 - 446
src/modules/native/tcc/libtcc/coff.h

@@ -1,446 +0,0 @@
-/**************************************************************************/
-/*  COFF.H                                                                */
-/*     COFF data structures and related definitions used by the linker    */
-/**************************************************************************/
-
-/*------------------------------------------------------------------------*/
-/*  COFF FILE HEADER                                                      */
-/*------------------------------------------------------------------------*/
-struct filehdr {
-        unsigned short  f_magic;        /* magic number */
-        unsigned short  f_nscns;        /* number of sections */
-        long            f_timdat;       /* time & date stamp */
-        long            f_symptr;       /* file pointer to symtab */
-        long            f_nsyms;        /* number of symtab entries */
-        unsigned short  f_opthdr;       /* sizeof(optional hdr) */
-        unsigned short  f_flags;        /* flags */
-        unsigned short  f_TargetID;     /* for C6x = 0x0099 */
-        };
-
-/*------------------------------------------------------------------------*/
-/*  File header flags                                                     */
-/*------------------------------------------------------------------------*/
-#define  F_RELFLG   0x01       /* relocation info stripped from file       */
-#define  F_EXEC     0x02       /* file is executable (no unresolved refs)  */
-#define  F_LNNO     0x04       /* line nunbers stripped from file          */
-#define  F_LSYMS    0x08       /* local symbols stripped from file         */
-#define  F_GSP10    0x10       /* 34010 version                            */
-#define  F_GSP20    0x20       /* 34020 version                            */
-#define  F_SWABD    0x40       /* bytes swabbed (in names)                 */
-#define  F_AR16WR   0x80       /* byte ordering of an AR16WR (PDP-11)      */
-#define  F_LITTLE   0x100      /* byte ordering of an AR32WR (vax)         */
-#define  F_BIG      0x200      /* byte ordering of an AR32W (3B, maxi)     */
-#define  F_PATCH    0x400      /* contains "patch" list in optional header */
-#define  F_NODF     0x400   
-
-#define F_VERSION    (F_GSP10  | F_GSP20)   
-#define F_BYTE_ORDER (F_LITTLE | F_BIG)
-#define FILHDR  struct filehdr
-
-//#define FILHSZ  sizeof(FILHDR) 
-#define FILHSZ  22                // above rounds to align on 4 bytes which causes problems 
-
-#define COFF_C67_MAGIC 0x00c2
-
-/*------------------------------------------------------------------------*/
-/*  Macros to recognize magic numbers                                     */
-/*------------------------------------------------------------------------*/
-#define ISMAGIC(x)      (((unsigned short)(x))==(unsigned short)magic)
-#define ISARCHIVE(x)    ((((unsigned short)(x))==(unsigned short)ARTYPE))
-#define BADMAGIC(x)     (((unsigned short)(x) & 0x8080) && !ISMAGIC(x))
-
-
-/*------------------------------------------------------------------------*/
-/*  OPTIONAL FILE HEADER                                                  */
-/*------------------------------------------------------------------------*/
-typedef struct aouthdr {
-        short   magic;          /* see magic.h                          */
-        short   vstamp;         /* version stamp                        */
-        long    tsize;          /* text size in bytes, padded to FW bdry*/
-        long    dsize;          /* initialized data "  "                */
-        long    bsize;          /* uninitialized data "   "             */
-        long    entrypt;        /* entry pt.                            */
-        long    text_start;     /* base of text used for this file      */
-        long    data_start;     /* base of data used for this file      */
-} AOUTHDR;
-
-#define AOUTSZ  sizeof(AOUTHDR)
-
-/*----------------------------------------------------------------------*/
-/*      When a UNIX aout header is to be built in the optional header,  */
-/*      the following magic numbers can appear in that header:          */ 
-/*                                                                      */
-/*              AOUT1MAGIC : default : readonly sharable text segment   */
-/*              AOUT2MAGIC:          : writable text segment            */
-/*              PAGEMAGIC  :         : configured for paging            */
-/*----------------------------------------------------------------------*/
-#define AOUT1MAGIC 0410
-#define AOUT2MAGIC 0407
-#define PAGEMAGIC  0413
-
-
-/*------------------------------------------------------------------------*/
-/*  COMMON ARCHIVE FILE STRUCTURES                                        */
-/*                                                                        */
-/*       ARCHIVE File Organization:                                       */
-/*       _______________________________________________                  */
-/*       |__________ARCHIVE_MAGIC_STRING_______________|                  */
-/*       |__________ARCHIVE_FILE_MEMBER_1______________|                  */
-/*       |                                             |                  */
-/*       |       Archive File Header "ar_hdr"          |                  */
-/*       |.............................................|                  */
-/*       |       Member Contents                       |                  */
-/*       |               1. External symbol directory  |                  */
-/*       |               2. Text file                  |                  */
-/*       |_____________________________________________|                  */
-/*       |________ARCHIVE_FILE_MEMBER_2________________|                  */
-/*       |               "ar_hdr"                      |                  */
-/*       |.............................................|                  */
-/*       |       Member Contents (.o or text file)     |                  */
-/*       |_____________________________________________|                  */
-/*       |       .               .               .     |                  */
-/*       |       .               .               .     |                  */
-/*       |       .               .               .     |                  */
-/*       |_____________________________________________|                  */
-/*       |________ARCHIVE_FILE_MEMBER_n________________|                  */
-/*       |               "ar_hdr"                      |                  */
-/*       |.............................................|                  */
-/*       |               Member Contents               |                  */
-/*       |_____________________________________________|                  */
-/*                                                                        */
-/*------------------------------------------------------------------------*/
-
-#define COFF_ARMAG   "!<arch>\n"
-#define SARMAG  8
-#define ARFMAG  "`\n"
-
-struct ar_hdr           /* archive file member header - printable ascii */
-{
-        char    ar_name[16];    /* file member name - `/' terminated */
-        char    ar_date[12];    /* file member date - decimal */
-        char    ar_uid[6];      /* file member user id - decimal */
-        char    ar_gid[6];      /* file member group id - decimal */
-        char    ar_mode[8];     /* file member mode - octal */
-        char    ar_size[10];    /* file member size - decimal */
-        char    ar_fmag[2];     /* ARFMAG - string to end header */
-};
-
-
-/*------------------------------------------------------------------------*/
-/*  SECTION HEADER                                                        */
-/*------------------------------------------------------------------------*/
-struct scnhdr {
-        char            s_name[8];      /* section name */
-        long            s_paddr;        /* physical address */
-        long            s_vaddr;        /* virtual address */
-        long            s_size;         /* section size */
-        long            s_scnptr;       /* file ptr to raw data for section */
-        long            s_relptr;       /* file ptr to relocation */
-        long            s_lnnoptr;      /* file ptr to line numbers */
-        unsigned int	s_nreloc;       /* number of relocation entries */
-        unsigned int	s_nlnno;        /* number of line number entries */
-        unsigned int	s_flags;        /* flags */
-		unsigned short	s_reserved;     /* reserved byte */
-		unsigned short  s_page;         /* memory page id */
-        };
-
-#define SCNHDR  struct scnhdr
-#define SCNHSZ  sizeof(SCNHDR)
-
-/*------------------------------------------------------------------------*/
-/* Define constants for names of "special" sections                       */
-/*------------------------------------------------------------------------*/
-//#define _TEXT    ".text"
-#define _DATA    ".data"
-#define _BSS     ".bss"
-#define _CINIT   ".cinit"
-#define _TV      ".tv"
-
-/*------------------------------------------------------------------------*/
-/* The low 4 bits of s_flags is used as a section "type"                  */
-/*------------------------------------------------------------------------*/
-#define STYP_REG    0x00  /* "regular" : allocated, relocated, loaded */
-#define STYP_DSECT  0x01  /* "dummy"   : not allocated, relocated, not loaded */
-#define STYP_NOLOAD 0x02  /* "noload"  : allocated, relocated, not loaded */
-#define STYP_GROUP  0x04  /* "grouped" : formed of input sections */
-#define STYP_PAD    0x08  /* "padding" : not allocated, not relocated, loaded */
-#define STYP_COPY   0x10  /* "copy"    : used for C init tables - 
-                                                not allocated, relocated,
-                                                loaded;  reloc & lineno
-                                                entries processed normally */
-#define STYP_TEXT   0x20   /* section contains text only */
-#define STYP_DATA   0x40   /* section contains data only */
-#define STYP_BSS    0x80   /* section contains bss only */
-
-#define STYP_ALIGN  0x100  /* align flag passed by old version assemblers */
-#define ALIGN_MASK  0x0F00 /* part of s_flags that is used for align vals */
-#define ALIGNSIZE(x) (1 << ((x & ALIGN_MASK) >> 8))
-
-
-/*------------------------------------------------------------------------*/
-/*  RELOCATION ENTRIES                                                    */
-/*------------------------------------------------------------------------*/
-struct reloc
-{
-   long            r_vaddr;        /* (virtual) address of reference */
-   short           r_symndx;       /* index into symbol table */
-   unsigned short  r_disp;         /* additional bits for address calculation */
-   unsigned short  r_type;         /* relocation type */
-};
-
-#define RELOC   struct reloc
-#define RELSZ   10                 /* sizeof(RELOC) */
-
-/*--------------------------------------------------------------------------*/
-/*   define all relocation types                                            */
-/*--------------------------------------------------------------------------*/
-
-#define R_ABS           0         /* absolute address - no relocation       */
-#define R_DIR16         01        /* UNUSED                                 */
-#define R_REL16         02        /* UNUSED                                 */
-#define R_DIR24         04        /* UNUSED                                 */
-#define R_REL24         05        /* 24 bits, direct                        */
-#define R_DIR32         06        /* UNUSED                                 */
-#define R_RELBYTE      017        /* 8 bits, direct                         */
-#define R_RELWORD      020        /* 16 bits, direct                        */
-#define R_RELLONG      021        /* 32 bits, direct                        */
-#define R_PCRBYTE      022        /* 8 bits, PC-relative                    */
-#define R_PCRWORD      023        /* 16 bits, PC-relative                   */
-#define R_PCRLONG      024        /* 32 bits, PC-relative                   */
-#define R_OCRLONG      030        /* GSP: 32 bits, one's complement direct  */
-#define R_GSPPCR16     031        /* GSP: 16 bits, PC relative (in words)   */
-#define R_GSPOPR32     032        /* GSP: 32 bits, direct big-endian        */
-#define R_PARTLS16     040        /* Brahma: 16 bit offset of 24 bit address*/
-#define R_PARTMS8      041        /* Brahma: 8 bit page of 24 bit address   */
-#define R_PARTLS7      050        /* DSP: 7 bit offset of 16 bit address    */
-#define R_PARTMS9      051        /* DSP: 9 bit page of 16 bit address      */
-#define R_REL13        052        /* DSP: 13 bits, direct                   */
-
-
-/*------------------------------------------------------------------------*/
-/*  LINE NUMBER ENTRIES                                                   */
-/*------------------------------------------------------------------------*/
-struct lineno
-{
-        union
-        {
-                long    l_symndx ;      /* sym. table index of function name
-                                                iff l_lnno == 0      */
-                long    l_paddr ;       /* (physical) address of line number */
-        }               l_addr ;
-        unsigned short  l_lnno ;        /* line number */
-};
-
-#define LINENO  struct lineno
-#define LINESZ  6       /* sizeof(LINENO) */
-
-
-/*------------------------------------------------------------------------*/
-/*   STORAGE CLASSES                                                      */
-/*------------------------------------------------------------------------*/
-#define  C_EFCN          -1    /* physical end of function */
-#define  C_NULL          0
-#define  C_AUTO          1     /* automatic variable */
-#define  C_EXT           2     /* external symbol */
-#define  C_STAT          3     /* static */
-#define  C_REG           4     /* register variable */
-#define  C_EXTDEF        5     /* external definition */
-#define  C_LABEL         6     /* label */
-#define  C_ULABEL        7     /* undefined label */
-#define  C_MOS           8     /* member of structure */
-#define  C_ARG           9     /* function argument */
-#define  C_STRTAG        10    /* structure tag */
-#define  C_MOU           11    /* member of union */
-#define  C_UNTAG         12    /* union tag */
-#define  C_TPDEF         13    /* type definition */
-#define C_USTATIC        14    /* undefined static */
-#define  C_ENTAG         15    /* enumeration tag */
-#define  C_MOE           16    /* member of enumeration */
-#define  C_REGPARM       17    /* register parameter */
-#define  C_FIELD         18    /* bit field */
-
-#define  C_BLOCK         100   /* ".bb" or ".eb" */
-#define  C_FCN           101   /* ".bf" or ".ef" */
-#define  C_EOS           102   /* end of structure */
-#define  C_FILE          103   /* file name */
-#define  C_LINE          104   /* dummy sclass for line number entry */
-#define  C_ALIAS         105   /* duplicate tag */
-#define  C_HIDDEN        106   /* special storage class for external */
-                               /* symbols in dmert public libraries  */
-
-/*------------------------------------------------------------------------*/
-/*  SYMBOL TABLE ENTRIES                                                  */
-/*------------------------------------------------------------------------*/
-
-#define  SYMNMLEN   8      /*  Number of characters in a symbol name */
-#define  FILNMLEN   14     /*  Number of characters in a file name */
-#define  DIMNUM     4      /*  Number of array dimensions in auxiliary entry */
-
-
-struct syment
-{
-        union
-        {
-                char            _n_name[SYMNMLEN];      /* old COFF version */
-                struct
-                {
-                        long    _n_zeroes;      /* new == 0 */
-                        long    _n_offset;      /* offset into string table */
-                } _n_n;
-                char            *_n_nptr[2];    /* allows for overlaying */
-        } _n;
-        long                    n_value;        /* value of symbol */
-        short                   n_scnum;        /* section number */
-        unsigned short          n_type;         /* type and derived type */
-        char                    n_sclass;       /* storage class */
-        char                    n_numaux;       /* number of aux. entries */
-};
-
-#define n_name          _n._n_name
-#define n_nptr          _n._n_nptr[1]
-#define n_zeroes        _n._n_n._n_zeroes
-#define n_offset        _n._n_n._n_offset
-
-/*------------------------------------------------------------------------*/
-/* Relocatable symbols have a section number of the                       */
-/* section in which they are defined.  Otherwise, section                 */
-/* numbers have the following meanings:                                   */
-/*------------------------------------------------------------------------*/
-#define  N_UNDEF  0                     /* undefined symbol */
-#define  N_ABS    -1                    /* value of symbol is absolute */
-#define  N_DEBUG  -2                    /* special debugging symbol  */
-#define  N_TV     (unsigned short)-3    /* needs transfer vector (preload) */
-#define  P_TV     (unsigned short)-4    /* needs transfer vector (postload) */
-
-
-/*------------------------------------------------------------------------*/
-/* The fundamental type of a symbol packed into the low                   */
-/* 4 bits of the word.                                                    */
-/*------------------------------------------------------------------------*/
-#define  _EF    ".ef"
-
-#define  T_NULL     0          /* no type info */
-#define  T_ARG      1          /* function argument (only used by compiler) */
-#define  T_CHAR     2          /* character */
-#define  T_SHORT    3          /* short integer */
-#define  T_INT      4          /* integer */
-#define  T_LONG     5          /* long integer */
-#define  T_FLOAT    6          /* floating point */
-#define  T_DOUBLE   7          /* double word */
-#define  T_STRUCT   8          /* structure  */
-#define  T_UNION    9          /* union  */
-#define  T_ENUM     10         /* enumeration  */
-#define  T_MOE      11         /* member of enumeration */
-#define  T_UCHAR    12         /* unsigned character */
-#define  T_USHORT   13         /* unsigned short */
-#define  T_UINT     14         /* unsigned integer */
-#define  T_ULONG    15         /* unsigned long */
-
-/*------------------------------------------------------------------------*/
-/* derived types are:                                                     */
-/*------------------------------------------------------------------------*/
-#define  DT_NON      0          /* no derived type */
-#define  DT_PTR      1          /* pointer */
-#define  DT_FCN      2          /* function */
-#define  DT_ARY      3          /* array */
-
-#define MKTYPE(basic, d1,d2,d3,d4,d5,d6) \
-       ((basic) | ((d1) <<  4) | ((d2) <<  6) | ((d3) <<  8) |\
-                  ((d4) << 10) | ((d5) << 12) | ((d6) << 14))
-
-/*------------------------------------------------------------------------*/
-/* type packing constants and macros                                      */
-/*------------------------------------------------------------------------*/
-#define  N_BTMASK_COFF     017
-#define  N_TMASK_COFF      060
-#define  N_TMASK1_COFF     0300
-#define  N_TMASK2_COFF     0360
-#define  N_BTSHFT_COFF     4
-#define  N_TSHIFT_COFF     2
-
-#define  BTYPE_COFF(x)  ((x) & N_BTMASK_COFF)  
-#define  ISINT(x)  (((x) >= T_CHAR && (x) <= T_LONG) ||   \
-		    ((x) >= T_UCHAR && (x) <= T_ULONG) || (x) == T_ENUM)
-#define  ISFLT_COFF(x)  ((x) == T_DOUBLE || (x) == T_FLOAT)
-#define  ISPTR_COFF(x)  (((x) & N_TMASK_COFF) == (DT_PTR << N_BTSHFT_COFF)) 
-#define  ISFCN_COFF(x)  (((x) & N_TMASK_COFF) == (DT_FCN << N_BTSHFT_COFF))
-#define  ISARY_COFF(x)  (((x) & N_TMASK_COFF) == (DT_ARY << N_BTSHFT_COFF))
-#define  ISTAG_COFF(x)  ((x)==C_STRTAG || (x)==C_UNTAG || (x)==C_ENTAG)
-
-#define  INCREF_COFF(x) ((((x)&~N_BTMASK_COFF)<<N_TSHIFT_COFF)|(DT_PTR<<N_BTSHFT_COFF)|(x&N_BTMASK_COFF))
-#define  DECREF_COFF(x) ((((x)>>N_TSHIFT_COFF)&~N_BTMASK_COFF)|((x)&N_BTMASK_COFF))
-
-
-/*------------------------------------------------------------------------*/
-/*  AUXILIARY SYMBOL ENTRY                                                */
-/*------------------------------------------------------------------------*/
-union auxent
-{
-	struct
-	{
-		long            x_tagndx;       /* str, un, or enum tag indx */
-		union
-		{
-			struct
-			{
-				unsigned short  x_lnno; /* declaration line number */
-				unsigned short  x_size; /* str, union, array size */
-			} x_lnsz;
-			long    x_fsize;        /* size of function */
-		} x_misc;
-		union
-		{
-			struct                  /* if ISFCN, tag, or .bb */
-			{
-				long    x_lnnoptr;      /* ptr to fcn line # */
-				long    x_endndx;       /* entry ndx past block end */
-			}       x_fcn;
-			struct                  /* if ISARY, up to 4 dimen. */
-			{
-				unsigned short  x_dimen[DIMNUM];
-			}       x_ary;
-		}               x_fcnary;
-		unsigned short  x_regcount;   /* number of registers used by func */
-	}       x_sym;
-	struct
-	{
-		char    x_fname[FILNMLEN];
-	}       x_file;
-	struct
-	{
-		long    x_scnlen;          /* section length */
-		unsigned short  x_nreloc;  /* number of relocation entries */
-		unsigned short  x_nlinno;  /* number of line numbers */
-	}       x_scn;
-};
-
-#define SYMENT  struct syment
-#define SYMESZ  18      /* sizeof(SYMENT) */
-
-#define AUXENT  union auxent
-#define AUXESZ  18      /* sizeof(AUXENT) */
-
-/*------------------------------------------------------------------------*/
-/*  NAMES OF "SPECIAL" SYMBOLS                                            */
-/*------------------------------------------------------------------------*/
-#define _STEXT          ".text"
-#define _ETEXT          "etext"
-#define _SDATA          ".data"
-#define _EDATA          "edata"
-#define _SBSS           ".bss"
-#define _END            "end"
-#define _CINITPTR       "cinit"
-
-/*--------------------------------------------------------------------------*/
-/*  ENTRY POINT SYMBOLS                                                     */
-/*--------------------------------------------------------------------------*/
-#define _START          "_start"
-#define _MAIN           "_main"
-    /*  _CSTART         "_c_int00"          (defined in params.h)  */
-
-
-#define _TVORIG         "_tvorig"
-#define _TORIGIN        "_torigin"
-#define _DORIGIN        "_dorigin"
-
-#define _SORIGIN        "_sorigin"

+ 0 - 4
src/modules/native/tcc/libtcc/config.h

@@ -1,4 +0,0 @@
-#define TCC_VERSION "0.9.25"
-#define TCC_TARGET_PE 1
-#define CONFIG_TCCDIR "."
-#define CONFIG_SYSROOT ""

+ 0 - 1714
src/modules/native/tcc/libtcc/elf.h

@@ -1,1714 +0,0 @@
-/* This file defines standard ELF types, structures, and macros.
-   Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ian Lance Taylor <[email protected]>.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-#ifndef _ELF_H
-#define _ELF_H 1
-
-#ifndef _WIN32
-#include <inttypes.h>
-#else
-#ifndef __int8_t_defined
-#define __int8_t_defined
-typedef signed char int8_t;
-typedef short int int16_t;
-typedef int int32_t;
-typedef long long int int64_t;
-#endif
-
-typedef unsigned char           uint8_t;
-typedef unsigned short int      uint16_t;
-typedef unsigned int            uint32_t;
-typedef unsigned long long int  uint64_t;
-#endif
-
-/* Standard ELF types.  */
-
-/* Type for a 16-bit quantity.  */
-typedef uint16_t Elf32_Half;
-typedef uint16_t Elf64_Half;
-
-/* Types for signed and unsigned 32-bit quantities.  */
-typedef uint32_t Elf32_Word;
-typedef int32_t  Elf32_Sword;
-typedef uint32_t Elf64_Word;
-typedef int32_t  Elf64_Sword;
-
-/* Types for signed and unsigned 64-bit quantities.  */
-typedef uint64_t Elf32_Xword;
-typedef int64_t  Elf32_Sxword;
-typedef uint64_t Elf64_Xword;
-typedef int64_t  Elf64_Sxword;
-
-/* Type of addresses.  */
-typedef uint32_t Elf32_Addr;
-typedef uint64_t Elf64_Addr;
-
-/* Type of file offsets.  */
-typedef uint32_t Elf32_Off;
-typedef uint64_t Elf64_Off;
-
-/* Type for section indices, which are 16-bit quantities.  */
-typedef uint16_t Elf32_Section;
-typedef uint16_t Elf64_Section;
-
-/* Type of symbol indices.  */
-typedef uint32_t Elf32_Symndx;
-typedef uint64_t Elf64_Symndx;
-
-
-/* The ELF file header.  This appears at the start of every ELF file.  */
-
-#define EI_NIDENT (16)
-
-typedef struct
-{
-  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
-  Elf32_Half    e_type;                 /* Object file type */
-  Elf32_Half    e_machine;              /* Architecture */
-  Elf32_Word    e_version;              /* Object file version */
-  Elf32_Addr    e_entry;                /* Entry point virtual address */
-  Elf32_Off     e_phoff;                /* Program header table file offset */
-  Elf32_Off     e_shoff;                /* Section header table file offset */
-  Elf32_Word    e_flags;                /* Processor-specific flags */
-  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
-  Elf32_Half    e_phentsize;            /* Program header table entry size */
-  Elf32_Half    e_phnum;                /* Program header table entry count */
-  Elf32_Half    e_shentsize;            /* Section header table entry size */
-  Elf32_Half    e_shnum;                /* Section header table entry count */
-  Elf32_Half    e_shstrndx;             /* Section header string table index */
-} Elf32_Ehdr;
-
-typedef struct
-{
-  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
-  Elf64_Half    e_type;                 /* Object file type */
-  Elf64_Half    e_machine;              /* Architecture */
-  Elf64_Word    e_version;              /* Object file version */
-  Elf64_Addr    e_entry;                /* Entry point virtual address */
-  Elf64_Off     e_phoff;                /* Program header table file offset */
-  Elf64_Off     e_shoff;                /* Section header table file offset */
-  Elf64_Word    e_flags;                /* Processor-specific flags */
-  Elf64_Half    e_ehsize;               /* ELF header size in bytes */
-  Elf64_Half    e_phentsize;            /* Program header table entry size */
-  Elf64_Half    e_phnum;                /* Program header table entry count */
-  Elf64_Half    e_shentsize;            /* Section header table entry size */
-  Elf64_Half    e_shnum;                /* Section header table entry count */
-  Elf64_Half    e_shstrndx;             /* Section header string table index */
-} Elf64_Ehdr;
-
-/* Fields in the e_ident array.  The EI_* macros are indices into the
-   array.  The macros under each EI_* macro are the values the byte
-   may have.  */
-
-#define EI_MAG0         0               /* File identification byte 0 index */
-#define ELFMAG0         0x7f            /* Magic number byte 0 */
-
-#define EI_MAG1         1               /* File identification byte 1 index */
-#define ELFMAG1         'E'             /* Magic number byte 1 */
-
-#define EI_MAG2         2               /* File identification byte 2 index */
-#define ELFMAG2         'L'             /* Magic number byte 2 */
-
-#define EI_MAG3         3               /* File identification byte 3 index */
-#define ELFMAG3         'F'             /* Magic number byte 3 */
-
-/* Conglomeration of the identification bytes, for easy testing as a word.  */
-#define ELFMAG          "\177ELF"
-#define SELFMAG         4
-
-#define EI_CLASS        4               /* File class byte index */
-#define ELFCLASSNONE    0               /* Invalid class */
-#define ELFCLASS32      1               /* 32-bit objects */
-#define ELFCLASS64      2               /* 64-bit objects */
-#define ELFCLASSNUM     3
-
-#define EI_DATA         5               /* Data encoding byte index */
-#define ELFDATANONE     0               /* Invalid data encoding */
-#define ELFDATA2LSB     1               /* 2's complement, little endian */
-#define ELFDATA2MSB     2               /* 2's complement, big endian */
-#define ELFDATANUM      3
-
-#define EI_VERSION      6               /* File version byte index */
-                                        /* Value must be EV_CURRENT */
-
-#define EI_OSABI        7               /* OS ABI identification */
-#define ELFOSABI_SYSV           0       /* UNIX System V ABI */
-#define ELFOSABI_HPUX           1       /* HP-UX */
-#define ELFOSABI_FREEBSD        9       /* Free BSD */
-#define ELFOSABI_ARM            97      /* ARM */
-#define ELFOSABI_STANDALONE     255     /* Standalone (embedded) application */
-
-#define EI_ABIVERSION   8               /* ABI version */
-
-#define EI_PAD          9               /* Byte index of padding bytes */
-
-/* Legal values for e_type (object file type).  */
-
-#define ET_NONE         0               /* No file type */
-#define ET_REL          1               /* Relocatable file */
-#define ET_EXEC         2               /* Executable file */
-#define ET_DYN          3               /* Shared object file */
-#define ET_CORE         4               /* Core file */
-#define ET_NUM          5               /* Number of defined types */
-#define ET_LOPROC       0xff00          /* Processor-specific */
-#define ET_HIPROC       0xffff          /* Processor-specific */
-
-/* Legal values for e_machine (architecture).  */
-
-#define EM_NONE          0              /* No machine */
-#define EM_M32           1              /* AT&T WE 32100 */
-#define EM_SPARC         2              /* SUN SPARC */
-#define EM_386           3              /* Intel 80386 */
-#define EM_68K           4              /* Motorola m68k family */
-#define EM_88K           5              /* Motorola m88k family */
-#define EM_486           6              /* Intel 80486 */
-#define EM_860           7              /* Intel 80860 */
-#define EM_MIPS          8              /* MIPS R3000 big-endian */
-#define EM_S370          9              /* Amdahl */
-#define EM_MIPS_RS4_BE  10              /* MIPS R4000 big-endian */
-#define EM_RS6000       11              /* RS6000 */
-
-#define EM_PARISC       15              /* HPPA */
-#define EM_nCUBE        16              /* nCUBE */
-#define EM_VPP500       17              /* Fujitsu VPP500 */
-#define EM_SPARC32PLUS  18              /* Sun's "v8plus" */
-#define EM_960          19              /* Intel 80960 */
-#define EM_PPC          20              /* PowerPC */
-
-#define EM_V800         36              /* NEC V800 series */
-#define EM_FR20         37              /* Fujitsu FR20 */
-#define EM_RH32         38              /* TRW RH32 */
-#define EM_RCE          39              /* Motorola RCE */
-#define EM_ARM          40              /* ARM */
-#define EM_FAKE_ALPHA   41              /* Digital Alpha */
-#define EM_SH           42              /* Hitachi SH */
-#define EM_SPARCV9      43              /* SPARC v9 64-bit */
-#define EM_TRICORE      44              /* Siemens Tricore */
-#define EM_ARC          45              /* Argonaut RISC Core */
-#define EM_H8_300       46              /* Hitachi H8/300 */
-#define EM_H8_300H      47              /* Hitachi H8/300H */
-#define EM_H8S          48              /* Hitachi H8S */
-#define EM_H8_500       49              /* Hitachi H8/500 */
-#define EM_IA_64        50              /* Intel Merced */
-#define EM_MIPS_X       51              /* Stanford MIPS-X */
-#define EM_COLDFIRE     52              /* Motorola Coldfire */
-#define EM_68HC12       53              /* Motorola M68HC12 */
-#define EM_MMA          54              /* Fujitsu MMA Multimedia Accelerator*/
-#define EM_PCP          55              /* Siemens PCP */
-#define EM_NCPU         56              /* Sony nCPU embeeded RISC */
-#define EM_NDR1         57              /* Denso NDR1 microprocessor */
-#define EM_STARCORE     58              /* Motorola Start*Core processor */
-#define EM_ME16         59              /* Toyota ME16 processor */
-#define EM_ST100        60              /* STMicroelectronic ST100 processor */
-#define EM_TINYJ        61              /* Advanced Logic Corp. Tinyj emb.fam*/
-#define EM_X86_64       62              /* AMD x86-64 architecture */
-#define EM_PDSP         63              /* Sony DSP Processor */
-#define EM_FX66         66              /* Siemens FX66 microcontroller */
-#define EM_ST9PLUS      67              /* STMicroelectronics ST9+ 8/16 mc */
-#define EM_ST7          68              /* STmicroelectronics ST7 8 bit mc */
-#define EM_68HC16       69              /* Motorola MC68HC16 microcontroller */
-#define EM_68HC11       70              /* Motorola MC68HC11 microcontroller */
-#define EM_68HC08       71              /* Motorola MC68HC08 microcontroller */
-#define EM_68HC05       72              /* Motorola MC68HC05 microcontroller */
-#define EM_SVX          73              /* Silicon Graphics SVx */
-#define EM_ST19         74              /* STMicroelectronics ST19 8 bit mc */
-#define EM_VAX          75              /* Digital VAX */
-#define EM_CRIS         76              /* Axis Communications 32-bit embedded processor */
-#define EM_JAVELIN      77              /* Infineon Technologies 32-bit embedded processor */
-#define EM_FIREPATH     78              /* Element 14 64-bit DSP Processor */
-#define EM_ZSP          79              /* LSI Logic 16-bit DSP Processor */
-#define EM_MMIX         80              /* Donald Knuth's educational 64-bit processor */
-#define EM_HUANY        81              /* Harvard University machine-independent object files */
-#define EM_PRISM        82              /* SiTera Prism */
-#define EM_AVR          83              /* Atmel AVR 8-bit microcontroller */
-#define EM_FR30         84              /* Fujitsu FR30 */
-#define EM_D10V         85              /* Mitsubishi D10V */
-#define EM_D30V         86              /* Mitsubishi D30V */
-#define EM_V850         87              /* NEC v850 */
-#define EM_M32R         88              /* Mitsubishi M32R */
-#define EM_MN10300      89              /* Matsushita MN10300 */
-#define EM_MN10200      90              /* Matsushita MN10200 */
-#define EM_PJ           91              /* picoJava */
-#define EM_OPENRISC     92              /* OpenRISC 32-bit embedded processor */
-#define EM_ARC_A5       93              /* ARC Cores Tangent-A5 */
-#define EM_XTENSA       94              /* Tensilica Xtensa Architecture */
-#define EM_NUM          95
-
-/* If it is necessary to assign new unofficial EM_* values, please
-   pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
-   chances of collision with official or non-GNU unofficial values.  */
-
-#define EM_ALPHA        0x9026
-#define EM_C60          0x9c60
-
-/* Legal values for e_version (version).  */
-
-#define EV_NONE         0               /* Invalid ELF version */
-#define EV_CURRENT      1               /* Current version */
-#define EV_NUM          2
-
-/* Section header.  */
-
-typedef struct
-{
-  Elf32_Word    sh_name;                /* Section name (string tbl index) */
-  Elf32_Word    sh_type;                /* Section type */
-  Elf32_Word    sh_flags;               /* Section flags */
-  Elf32_Addr    sh_addr;                /* Section virtual addr at execution */
-  Elf32_Off     sh_offset;              /* Section file offset */
-  Elf32_Word    sh_size;                /* Section size in bytes */
-  Elf32_Word    sh_link;                /* Link to another section */
-  Elf32_Word    sh_info;                /* Additional section information */
-  Elf32_Word    sh_addralign;           /* Section alignment */
-  Elf32_Word    sh_entsize;             /* Entry size if section holds table */
-} Elf32_Shdr;
-
-typedef struct
-{
-  Elf64_Word    sh_name;                /* Section name (string tbl index) */
-  Elf64_Word    sh_type;                /* Section type */
-  Elf64_Xword   sh_flags;               /* Section flags */
-  Elf64_Addr    sh_addr;                /* Section virtual addr at execution */
-  Elf64_Off     sh_offset;              /* Section file offset */
-  Elf64_Xword   sh_size;                /* Section size in bytes */
-  Elf64_Word    sh_link;                /* Link to another section */
-  Elf64_Word    sh_info;                /* Additional section information */
-  Elf64_Xword   sh_addralign;           /* Section alignment */
-  Elf64_Xword   sh_entsize;             /* Entry size if section holds table */
-} Elf64_Shdr;
-
-/* Special section indices.  */
-
-#define SHN_UNDEF       0               /* Undefined section */
-#define SHN_LORESERVE   0xff00          /* Start of reserved indices */
-#define SHN_LOPROC      0xff00          /* Start of processor-specific */
-#define SHN_HIPROC      0xff1f          /* End of processor-specific */
-#define SHN_ABS         0xfff1          /* Associated symbol is absolute */
-#define SHN_COMMON      0xfff2          /* Associated symbol is common */
-#define SHN_HIRESERVE   0xffff          /* End of reserved indices */
-
-/* Legal values for sh_type (section type).  */
-
-#define SHT_NULL         0              /* Section header table entry unused */
-#define SHT_PROGBITS     1              /* Program data */
-#define SHT_SYMTAB       2              /* Symbol table */
-#define SHT_STRTAB       3              /* String table */
-#define SHT_RELA         4              /* Relocation entries with addends */
-#define SHT_HASH         5              /* Symbol hash table */
-#define SHT_DYNAMIC      6              /* Dynamic linking information */
-#define SHT_NOTE         7              /* Notes */
-#define SHT_NOBITS       8              /* Program space with no data (bss) */
-#define SHT_REL          9              /* Relocation entries, no addends */
-#define SHT_SHLIB        10             /* Reserved */
-#define SHT_DYNSYM       11             /* Dynamic linker symbol table */
-#define SHT_NUM          12             /* Number of defined types.  */
-#define SHT_LOOS         0x60000000     /* Start OS-specific */
-#define SHT_LOSUNW       0x6ffffffb     /* Sun-specific low bound.  */
-#define SHT_SUNW_COMDAT  0x6ffffffb
-#define SHT_SUNW_syminfo 0x6ffffffc
-#define SHT_GNU_verdef   0x6ffffffd     /* Version definition section.  */
-#define SHT_GNU_verneed  0x6ffffffe     /* Version needs section.  */
-#define SHT_GNU_versym   0x6fffffff     /* Version symbol table.  */
-#define SHT_HISUNW       0x6fffffff     /* Sun-specific high bound.  */
-#define SHT_HIOS         0x6fffffff     /* End OS-specific type */
-#define SHT_LOPROC       0x70000000     /* Start of processor-specific */
-#define SHT_ARM_EXIDX    0x70000001     /* Exception Index table */
-#define SHT_ARM_PREEMPTMAP 0x70000002   /* dynamic linking pre-emption map */
-#define SHT_ARM_ATTRIBUTES 0x70000003   /* Object file compatibility attrs */
-#define SHT_HIPROC       0x7fffffff     /* End of processor-specific */
-#define SHT_LOUSER       0x80000000     /* Start of application-specific */
-#define SHT_HIUSER       0x8fffffff     /* End of application-specific */
-
-/* Legal values for sh_flags (section flags).  */
-
-#define SHF_WRITE       (1 << 0)        /* Writable */
-#define SHF_ALLOC       (1 << 1)        /* Occupies memory during execution */
-#define SHF_EXECINSTR   (1 << 2)        /* Executable */
-#define SHF_MASKPROC    0xf0000000      /* Processor-specific */
-
-/* Symbol table entry.  */
-
-typedef struct
-{
-  Elf32_Word    st_name;                /* Symbol name (string tbl index) */
-  Elf32_Addr    st_value;               /* Symbol value */
-  Elf32_Word    st_size;                /* Symbol size */
-  unsigned char st_info;                /* Symbol type and binding */
-  unsigned char st_other;               /* No defined meaning, 0 */
-  Elf32_Section st_shndx;               /* Section index */
-} Elf32_Sym;
-
-typedef struct
-{
-  Elf64_Word    st_name;                /* Symbol name (string tbl index) */
-  unsigned char st_info;                /* Symbol type and binding */
-  unsigned char st_other;               /* No defined meaning, 0 */
-  Elf64_Section st_shndx;               /* Section index */
-  Elf64_Addr    st_value;               /* Symbol value */
-  Elf64_Xword   st_size;                /* Symbol size */
-} Elf64_Sym;
-
-/* The syminfo section if available contains additional information about
-   every dynamic symbol.  */
-
-typedef struct
-{
-  Elf32_Half si_boundto;                /* Direct bindings, symbol bound to */
-  Elf32_Half si_flags;                  /* Per symbol flags */
-} Elf32_Syminfo;
-
-typedef struct
-{
-  Elf64_Half si_boundto;                /* Direct bindings, symbol bound to */
-  Elf64_Half si_flags;                  /* Per symbol flags */
-} Elf64_Syminfo;
-
-/* Possible values for si_boundto.  */
-#define SYMINFO_BT_SELF         0xffff  /* Symbol bound to self */
-#define SYMINFO_BT_PARENT       0xfffe  /* Symbol bound to parent */
-#define SYMINFO_BT_LOWRESERVE   0xff00  /* Beginning of reserved entries */
-
-/* Possible bitmasks for si_flags.  */
-#define SYMINFO_FLG_DIRECT      0x0001  /* Direct bound symbol */
-#define SYMINFO_FLG_PASSTHRU    0x0002  /* Pass-thru symbol for translator */
-#define SYMINFO_FLG_COPY        0x0004  /* Symbol is a copy-reloc */
-#define SYMINFO_FLG_LAZYLOAD    0x0008  /* Symbol bound to object to be lazy
-                                           loaded */
-/* Syminfo version values.  */
-#define SYMINFO_NONE            0
-#define SYMINFO_CURRENT         1
-#define SYMINFO_NUM             2
-
-
-/* Special section index.  */
-
-#define SHN_UNDEF       0               /* No section, undefined symbol.  */
-
-/* How to extract and insert information held in the st_info field.  */
-
-#define ELF32_ST_BIND(val)              (((unsigned char) (val)) >> 4)
-#define ELF32_ST_TYPE(val)              ((val) & 0xf)
-#define ELF32_ST_INFO(bind, type)       (((bind) << 4) + ((type) & 0xf))
-
-/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field.  */
-#define ELF64_ST_BIND(val)              ELF32_ST_BIND (val)
-#define ELF64_ST_TYPE(val)              ELF32_ST_TYPE (val)
-#define ELF64_ST_INFO(bind, type)       ELF32_ST_INFO ((bind), (type))
-
-/* Legal values for ST_BIND subfield of st_info (symbol binding).  */
-
-#define STB_LOCAL       0               /* Local symbol */
-#define STB_GLOBAL      1               /* Global symbol */
-#define STB_WEAK        2               /* Weak symbol */
-#define STB_NUM         3               /* Number of defined types.  */
-#define STB_LOOS        10              /* Start of OS-specific */
-#define STB_HIOS        12              /* End of OS-specific */
-#define STB_LOPROC      13              /* Start of processor-specific */
-#define STB_HIPROC      15              /* End of processor-specific */
-
-/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
-
-#define STT_NOTYPE      0               /* Symbol type is unspecified */
-#define STT_OBJECT      1               /* Symbol is a data object */
-#define STT_FUNC        2               /* Symbol is a code object */
-#define STT_SECTION     3               /* Symbol associated with a section */
-#define STT_FILE        4               /* Symbol's name is file name */
-#define STT_NUM         5               /* Number of defined types.  */
-#define STT_LOOS        11              /* Start of OS-specific */
-#define STT_HIOS        12              /* End of OS-specific */
-#define STT_LOPROC      13              /* Start of processor-specific */
-#define STT_HIPROC      15              /* End of processor-specific */
-
-
-/* Symbol table indices are found in the hash buckets and chain table
-   of a symbol hash table section.  This special index value indicates
-   the end of a chain, meaning no further symbols are found in that bucket.  */
-
-#define STN_UNDEF       0               /* End of a chain.  */
-
-
-/* How to extract and insert information held in the st_other field.  */
-
-#define ELF32_ST_VISIBILITY(o)  ((o) & 0x03)
-
-/* For ELF64 the definitions are the same.  */
-#define ELF64_ST_VISIBILITY(o)  ELF32_ST_VISIBILITY (o)
-
-/* Symbol visibility specification encoded in the st_other field.  */
-#define STV_DEFAULT     0               /* Default symbol visibility rules */
-#define STV_INTERNAL    1               /* Processor specific hidden class */
-#define STV_HIDDEN      2               /* Sym unavailable in other modules */
-#define STV_PROTECTED   3               /* Not preemptible, not exported */
-
-
-/* Relocation table entry without addend (in section of type SHT_REL).  */
-
-typedef struct
-{
-  Elf32_Addr    r_offset;               /* Address */
-  Elf32_Word    r_info;                 /* Relocation type and symbol index */
-} Elf32_Rel;
-
-/* I have seen two different definitions of the Elf64_Rel and
-   Elf64_Rela structures, so we'll leave them out until Novell (or
-   whoever) gets their act together.  */
-/* The following, at least, is used on Sparc v9, MIPS, and Alpha.  */
-
-typedef struct
-{
-  Elf64_Addr    r_offset;               /* Address */
-  Elf64_Xword   r_info;                 /* Relocation type and symbol index */
-} Elf64_Rel;
-
-/* Relocation table entry with addend (in section of type SHT_RELA).  */
-
-typedef struct
-{
-  Elf32_Addr    r_offset;               /* Address */
-  Elf32_Word    r_info;                 /* Relocation type and symbol index */
-  Elf32_Sword   r_addend;               /* Addend */
-} Elf32_Rela;
-
-typedef struct
-{
-  Elf64_Addr    r_offset;               /* Address */
-  Elf64_Xword   r_info;                 /* Relocation type and symbol index */
-  Elf64_Sxword  r_addend;               /* Addend */
-} Elf64_Rela;
-
-/* How to extract and insert information held in the r_info field.  */
-
-#define ELF32_R_SYM(val)                ((val) >> 8)
-#define ELF32_R_TYPE(val)               ((val) & 0xff)
-#define ELF32_R_INFO(sym, type)         (((sym) << 8) + ((type) & 0xff))
-
-#define ELF64_R_SYM(i)                  ((i) >> 32)
-#define ELF64_R_TYPE(i)                 ((i) & 0xffffffff)
-#define ELF64_R_INFO(sym,type)          ((((Elf64_Xword)(sym)) << 32) + (type))
-
-/* Program segment header.  */
-
-typedef struct
-{
-  Elf32_Word    p_type;                 /* Segment type */
-  Elf32_Off     p_offset;               /* Segment file offset */
-  Elf32_Addr    p_vaddr;                /* Segment virtual address */
-  Elf32_Addr    p_paddr;                /* Segment physical address */
-  Elf32_Word    p_filesz;               /* Segment size in file */
-  Elf32_Word    p_memsz;                /* Segment size in memory */
-  Elf32_Word    p_flags;                /* Segment flags */
-  Elf32_Word    p_align;                /* Segment alignment */
-} Elf32_Phdr;
-
-typedef struct
-{
-  Elf64_Word    p_type;                 /* Segment type */
-  Elf64_Word    p_flags;                /* Segment flags */
-  Elf64_Off     p_offset;               /* Segment file offset */
-  Elf64_Addr    p_vaddr;                /* Segment virtual address */
-  Elf64_Addr    p_paddr;                /* Segment physical address */
-  Elf64_Xword   p_filesz;               /* Segment size in file */
-  Elf64_Xword   p_memsz;                /* Segment size in memory */
-  Elf64_Xword   p_align;                /* Segment alignment */
-} Elf64_Phdr;
-
-/* Legal values for p_type (segment type).  */
-
-#define PT_NULL         0               /* Program header table entry unused */
-#define PT_LOAD         1               /* Loadable program segment */
-#define PT_DYNAMIC      2               /* Dynamic linking information */
-#define PT_INTERP       3               /* Program interpreter */
-#define PT_NOTE         4               /* Auxiliary information */
-#define PT_SHLIB        5               /* Reserved */
-#define PT_PHDR         6               /* Entry for header table itself */
-#define PT_NUM          7               /* Number of defined types.  */
-#define PT_LOOS         0x60000000      /* Start of OS-specific */
-#define PT_HIOS         0x6fffffff      /* End of OS-specific */
-#define PT_LOPROC       0x70000000      /* Start of processor-specific */
-#define PT_HIPROC       0x7fffffff      /* End of processor-specific */
-
-/* Legal values for p_flags (segment flags).  */
-
-#define PF_X            (1 << 0)        /* Segment is executable */
-#define PF_W            (1 << 1)        /* Segment is writable */
-#define PF_R            (1 << 2)        /* Segment is readable */
-#define PF_MASKPROC     0xf0000000      /* Processor-specific */
-
-/* Legal values for note segment descriptor types for core files. */
-
-#define NT_PRSTATUS     1               /* Contains copy of prstatus struct */
-#define NT_FPREGSET     2               /* Contains copy of fpregset struct */
-#define NT_PRPSINFO     3               /* Contains copy of prpsinfo struct */
-#define NT_PRXREG       4               /* Contains copy of prxregset struct */
-#define NT_PLATFORM     5               /* String from sysinfo(SI_PLATFORM) */
-#define NT_AUXV         6               /* Contains copy of auxv array */
-#define NT_GWINDOWS     7               /* Contains copy of gwindows struct */
-#define NT_PSTATUS      10              /* Contains copy of pstatus struct */
-#define NT_PSINFO       13              /* Contains copy of psinfo struct */
-#define NT_PRCRED       14              /* Contains copy of prcred struct */
-#define NT_UTSNAME      15              /* Contains copy of utsname struct */
-#define NT_LWPSTATUS    16              /* Contains copy of lwpstatus struct */
-#define NT_LWPSINFO     17              /* Contains copy of lwpinfo struct */
-
-/* Legal values for the  note segment descriptor types for object files.  */
-
-#define NT_VERSION      1               /* Contains a version string.  */
-
-
-/* Dynamic section entry.  */
-
-typedef struct
-{
-  Elf32_Sword   d_tag;                  /* Dynamic entry type */
-  union
-    {
-      Elf32_Word d_val;                 /* Integer value */
-      Elf32_Addr d_ptr;                 /* Address value */
-    } d_un;
-} Elf32_Dyn;
-
-typedef struct
-{
-  Elf64_Sxword  d_tag;                  /* Dynamic entry type */
-  union
-    {
-      Elf64_Xword d_val;                /* Integer value */
-      Elf64_Addr d_ptr;                 /* Address value */
-    } d_un;
-} Elf64_Dyn;
-
-/* Legal values for d_tag (dynamic entry type).  */
-
-#define DT_NULL         0               /* Marks end of dynamic section */
-#define DT_NEEDED       1               /* Name of needed library */
-#define DT_PLTRELSZ     2               /* Size in bytes of PLT relocs */
-#define DT_PLTGOT       3               /* Processor defined value */
-#define DT_HASH         4               /* Address of symbol hash table */
-#define DT_STRTAB       5               /* Address of string table */
-#define DT_SYMTAB       6               /* Address of symbol table */
-#define DT_RELA         7               /* Address of Rela relocs */
-#define DT_RELASZ       8               /* Total size of Rela relocs */
-#define DT_RELAENT      9               /* Size of one Rela reloc */
-#define DT_STRSZ        10              /* Size of string table */
-#define DT_SYMENT       11              /* Size of one symbol table entry */
-#define DT_INIT         12              /* Address of init function */
-#define DT_FINI         13              /* Address of termination function */
-#define DT_SONAME       14              /* Name of shared object */
-#define DT_RPATH        15              /* Library search path */
-#define DT_SYMBOLIC     16              /* Start symbol search here */
-#define DT_REL          17              /* Address of Rel relocs */
-#define DT_RELSZ        18              /* Total size of Rel relocs */
-#define DT_RELENT       19              /* Size of one Rel reloc */
-#define DT_PLTREL       20              /* Type of reloc in PLT */
-#define DT_DEBUG        21              /* For debugging; unspecified */
-#define DT_TEXTREL      22              /* Reloc might modify .text */
-#define DT_JMPREL       23              /* Address of PLT relocs */
-#define DT_BIND_NOW     24              /* Process relocations of object */
-#define DT_INIT_ARRAY   25              /* Array with addresses of init fct */
-#define DT_FINI_ARRAY   26              /* Array with addresses of fini fct */
-#define DT_INIT_ARRAYSZ 27              /* Size in bytes of DT_INIT_ARRAY */
-#define DT_FINI_ARRAYSZ 28              /* Size in bytes of DT_FINI_ARRAY */
-#define DT_NUM          29              /* Number used */
-#define DT_LOOS         0x60000000      /* Start of OS-specific */
-#define DT_HIOS         0x6fffffff      /* End of OS-specific */
-#define DT_LOPROC       0x70000000      /* Start of processor-specific */
-#define DT_HIPROC       0x7fffffff      /* End of processor-specific */
-#define DT_PROCNUM      DT_MIPS_NUM     /* Most used by any processor */
-
-/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
-   Dyn.d_un.d_val field of the Elf*_Dyn structure.  This follows Sun's
-   approach.  */
-#define DT_VALRNGLO     0x6ffffd00
-#define DT_POSFLAG_1    0x6ffffdfd      /* Flags for DT_* entries, effecting
-                                           the following DT_* entry.  */
-#define DT_SYMINSZ      0x6ffffdfe      /* Size of syminfo table (in bytes) */
-#define DT_SYMINENT     0x6ffffdff      /* Entry size of syminfo */
-#define DT_VALRNGHI     0x6ffffdff
-
-/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
-   Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
-
-   If any adjustment is made to the ELF object after it has been
-   built these entries will need to be adjusted.  */
-#define DT_ADDRRNGLO    0x6ffffe00
-#define DT_SYMINFO      0x6ffffeff      /* syminfo table */
-#define DT_ADDRRNGHI    0x6ffffeff
-
-/* The versioning entry types.  The next are defined as part of the
-   GNU extension.  */
-#define DT_VERSYM       0x6ffffff0
-
-/* These were chosen by Sun.  */
-#define DT_FLAGS_1      0x6ffffffb      /* State flags, see DF_1_* below.  */
-#define DT_VERDEF       0x6ffffffc      /* Address of version definition
-                                           table */
-#define DT_VERDEFNUM    0x6ffffffd      /* Number of version definitions */
-#define DT_VERNEED      0x6ffffffe      /* Address of table with needed
-                                           versions */
-#define DT_VERNEEDNUM   0x6fffffff      /* Number of needed versions */
-#define DT_VERSIONTAGIDX(tag)   (DT_VERNEEDNUM - (tag)) /* Reverse order! */
-#define DT_VERSIONTAGNUM 16
-
-/* Sun added these machine-independent extensions in the "processor-specific"
-   range.  Be compatible.  */
-#define DT_AUXILIARY    0x7ffffffd      /* Shared object to load before self */
-#define DT_FILTER       0x7fffffff      /* Shared object to get values from */
-#define DT_EXTRATAGIDX(tag)     ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
-#define DT_EXTRANUM     3
-
-/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
-   entry in the dynamic section.  */
-#define DF_1_NOW        0x00000001      /* Set RTLD_NOW for this object.  */
-#define DF_1_GLOBAL     0x00000002      /* Set RTLD_GLOBAL for this object.  */
-#define DF_1_GROUP      0x00000004      /* Set RTLD_GROUP for this object.  */
-#define DF_1_NODELETE   0x00000008      /* Set RTLD_NODELETE for this object.*/
-#define DF_1_LOADFLTR   0x00000010      /* Trigger filtee loading at runtime.*/
-#define DF_1_INITFIRST  0x00000020      /* Set RTLD_INITFIRST for this object*/
-#define DF_1_NOOPEN     0x00000040      /* Set RTLD_NOOPEN for this object.  */
-
-/* Version definition sections.  */
-
-typedef struct
-{
-  Elf32_Half    vd_version;             /* Version revision */
-  Elf32_Half    vd_flags;               /* Version information */
-  Elf32_Half    vd_ndx;                 /* Version Index */
-  Elf32_Half    vd_cnt;                 /* Number of associated aux entries */
-  Elf32_Word    vd_hash;                /* Version name hash value */
-  Elf32_Word    vd_aux;                 /* Offset in bytes to verdaux array */
-  Elf32_Word    vd_next;                /* Offset in bytes to next verdef
-                                           entry */
-} Elf32_Verdef;
-
-typedef struct
-{
-  Elf64_Half    vd_version;             /* Version revision */
-  Elf64_Half    vd_flags;               /* Version information */
-  Elf64_Half    vd_ndx;                 /* Version Index */
-  Elf64_Half    vd_cnt;                 /* Number of associated aux entries */
-  Elf64_Word    vd_hash;                /* Version name hash value */
-  Elf64_Word    vd_aux;                 /* Offset in bytes to verdaux array */
-  Elf64_Word    vd_next;                /* Offset in bytes to next verdef
-                                           entry */
-} Elf64_Verdef;
-
-
-/* Legal values for vd_version (version revision).  */
-#define VER_DEF_NONE    0               /* No version */
-#define VER_DEF_CURRENT 1               /* Current version */
-#define VER_DEF_NUM     2               /* Given version number */
-
-/* Legal values for vd_flags (version information flags).  */
-#define VER_FLG_BASE    0x1             /* Version definition of file itself */
-#define VER_FLG_WEAK    0x2             /* Weak version identifier */
-
-/* Auxialiary version information.  */
-
-typedef struct
-{
-  Elf32_Word    vda_name;               /* Version or dependency names */
-  Elf32_Word    vda_next;               /* Offset in bytes to next verdaux
-                                           entry */
-} Elf32_Verdaux;
-
-typedef struct
-{
-  Elf64_Word    vda_name;               /* Version or dependency names */
-  Elf64_Word    vda_next;               /* Offset in bytes to next verdaux
-                                           entry */
-} Elf64_Verdaux;
-
-
-/* Version dependency section.  */
-
-typedef struct
-{
-  Elf32_Half    vn_version;             /* Version of structure */
-  Elf32_Half    vn_cnt;                 /* Number of associated aux entries */
-  Elf32_Word    vn_file;                /* Offset of filename for this
-                                           dependency */
-  Elf32_Word    vn_aux;                 /* Offset in bytes to vernaux array */
-  Elf32_Word    vn_next;                /* Offset in bytes to next verneed
-                                           entry */
-} Elf32_Verneed;
-
-typedef struct
-{
-  Elf64_Half    vn_version;             /* Version of structure */
-  Elf64_Half    vn_cnt;                 /* Number of associated aux entries */
-  Elf64_Word    vn_file;                /* Offset of filename for this
-                                           dependency */
-  Elf64_Word    vn_aux;                 /* Offset in bytes to vernaux array */
-  Elf64_Word    vn_next;                /* Offset in bytes to next verneed
-                                           entry */
-} Elf64_Verneed;
-
-
-/* Legal values for vn_version (version revision).  */
-#define VER_NEED_NONE    0              /* No version */
-#define VER_NEED_CURRENT 1              /* Current version */
-#define VER_NEED_NUM     2              /* Given version number */
-
-/* Auxiliary needed version information.  */
-
-typedef struct
-{
-  Elf32_Word    vna_hash;               /* Hash value of dependency name */
-  Elf32_Half    vna_flags;              /* Dependency specific information */
-  Elf32_Half    vna_other;              /* Unused */
-  Elf32_Word    vna_name;               /* Dependency name string offset */
-  Elf32_Word    vna_next;               /* Offset in bytes to next vernaux
-                                           entry */
-} Elf32_Vernaux;
-
-typedef struct
-{
-  Elf64_Word    vna_hash;               /* Hash value of dependency name */
-  Elf64_Half    vna_flags;              /* Dependency specific information */
-  Elf64_Half    vna_other;              /* Unused */
-  Elf64_Word    vna_name;               /* Dependency name string offset */
-  Elf64_Word    vna_next;               /* Offset in bytes to next vernaux
-                                           entry */
-} Elf64_Vernaux;
-
-
-/* Legal values for vna_flags.  */
-#define VER_FLG_WEAK    0x2             /* Weak version identifier */
-
-
-/* Auxiliary vector.  */
-
-/* This vector is normally only used by the program interpreter.  The
-   usual definition in an ABI supplement uses the name auxv_t.  The
-   vector is not usually defined in a standard <elf.h> file, but it
-   can't hurt.  We rename it to avoid conflicts.  The sizes of these
-   types are an arrangement between the exec server and the program
-   interpreter, so we don't fully specify them here.  */
-
-typedef struct
-{
-  int a_type;                   /* Entry type */
-  union
-    {
-      long int a_val;           /* Integer value */
-      void *a_ptr;              /* Pointer value */
-      void (*a_fcn) (void);     /* Function pointer value */
-    } a_un;
-} Elf32_auxv_t;
-
-typedef struct
-{
-  long int a_type;              /* Entry type */
-  union
-    {
-      long int a_val;           /* Integer value */
-      void *a_ptr;              /* Pointer value */
-      void (*a_fcn) (void);     /* Function pointer value */
-    } a_un;
-} Elf64_auxv_t;
-
-/* Legal values for a_type (entry type).  */
-
-#define AT_NULL         0               /* End of vector */
-#define AT_IGNORE       1               /* Entry should be ignored */
-#define AT_EXECFD       2               /* File descriptor of program */
-#define AT_PHDR         3               /* Program headers for program */
-#define AT_PHENT        4               /* Size of program header entry */
-#define AT_PHNUM        5               /* Number of program headers */
-#define AT_PAGESZ       6               /* System page size */
-#define AT_BASE         7               /* Base address of interpreter */
-#define AT_FLAGS        8               /* Flags */
-#define AT_ENTRY        9               /* Entry point of program */
-#define AT_NOTELF       10              /* Program is not ELF */
-#define AT_UID          11              /* Real uid */
-#define AT_EUID         12              /* Effective uid */
-#define AT_GID          13              /* Real gid */
-#define AT_EGID         14              /* Effective gid */
-
-/* Some more special a_type values describing the hardware.  */
-#define AT_PLATFORM     15              /* String identifying platform.  */
-#define AT_HWCAP        16              /* Machine dependent hints about
-                                           processor capabilities.  */
-
-/* This entry gives some information about the FPU initialization
-   performed by the kernel.  */
-#define AT_FPUCW        17              /* Used FPU control word.  */
-
-
-/* Note section contents.  Each entry in the note section begins with
-   a header of a fixed form.  */
-
-typedef struct
-{
-  Elf32_Word n_namesz;                  /* Length of the note's name.  */
-  Elf32_Word n_descsz;                  /* Length of the note's descriptor.  */
-  Elf32_Word n_type;                    /* Type of the note.  */
-} Elf32_Nhdr;
-
-typedef struct
-{
-  Elf64_Word n_namesz;                  /* Length of the note's name.  */
-  Elf64_Word n_descsz;                  /* Length of the note's descriptor.  */
-  Elf64_Word n_type;                    /* Type of the note.  */
-} Elf64_Nhdr;
-
-/* Known names of notes.  */
-
-/* Solaris entries in the note section have this name.  */
-#define ELF_NOTE_SOLARIS        "SUNW Solaris"
-
-/* Note entries for GNU systems have this name.  */
-#define ELF_NOTE_GNU            "GNU"
-
-
-/* Defined types of notes for Solaris.  */
-
-/* Value of descriptor (one word) is desired pagesize for the binary.  */
-#define ELF_NOTE_PAGESIZE_HINT  1
-
-
-/* Defined note types for GNU systems.  */
-
-/* ABI information.  The descriptor consists of words:
-   word 0: OS descriptor
-   word 1: major version of the ABI
-   word 2: minor version of the ABI
-   word 3: subminor version of the ABI
-*/
-#define ELF_NOTE_ABI            1
-
-/* Known OSes.  These value can appear in word 0 of an ELF_NOTE_ABI
-   note section entry.  */
-#define ELF_NOTE_OS_LINUX       0
-#define ELF_NOTE_OS_GNU         1
-#define ELF_NOTE_OS_SOLARIS2    2
-
-
-/* Motorola 68k specific definitions.  */
-
-/* m68k relocs.  */
-
-#define R_68K_NONE      0               /* No reloc */
-#define R_68K_32        1               /* Direct 32 bit  */
-#define R_68K_16        2               /* Direct 16 bit  */
-#define R_68K_8         3               /* Direct 8 bit  */
-#define R_68K_PC32      4               /* PC relative 32 bit */
-#define R_68K_PC16      5               /* PC relative 16 bit */
-#define R_68K_PC8       6               /* PC relative 8 bit */
-#define R_68K_GOT32     7               /* 32 bit PC relative GOT entry */
-#define R_68K_GOT16     8               /* 16 bit PC relative GOT entry */
-#define R_68K_GOT8      9               /* 8 bit PC relative GOT entry */
-#define R_68K_GOT32O    10              /* 32 bit GOT offset */
-#define R_68K_GOT16O    11              /* 16 bit GOT offset */
-#define R_68K_GOT8O     12              /* 8 bit GOT offset */
-#define R_68K_PLT32     13              /* 32 bit PC relative PLT address */
-#define R_68K_PLT16     14              /* 16 bit PC relative PLT address */
-#define R_68K_PLT8      15              /* 8 bit PC relative PLT address */
-#define R_68K_PLT32O    16              /* 32 bit PLT offset */
-#define R_68K_PLT16O    17              /* 16 bit PLT offset */
-#define R_68K_PLT8O     18              /* 8 bit PLT offset */
-#define R_68K_COPY      19              /* Copy symbol at runtime */
-#define R_68K_GLOB_DAT  20              /* Create GOT entry */
-#define R_68K_JMP_SLOT  21              /* Create PLT entry */
-#define R_68K_RELATIVE  22              /* Adjust by program base */
-/* Keep this the last entry.  */
-#define R_68K_NUM       23
-
-/* Intel 80386 specific definitions.  */
-
-/* i386 relocs.  */
-
-#define R_386_NONE      0               /* No reloc */
-#define R_386_32        1               /* Direct 32 bit  */
-#define R_386_PC32      2               /* PC relative 32 bit */
-#define R_386_GOT32     3               /* 32 bit GOT entry */
-#define R_386_PLT32     4               /* 32 bit PLT address */
-#define R_386_COPY      5               /* Copy symbol at runtime */
-#define R_386_GLOB_DAT  6               /* Create GOT entry */
-#define R_386_JMP_SLOT  7               /* Create PLT entry */
-#define R_386_RELATIVE  8               /* Adjust by program base */
-#define R_386_GOTOFF    9               /* 32 bit offset to GOT */
-#define R_386_GOTPC     10              /* 32 bit PC relative offset to GOT */
-/* Keep this the last entry.  */
-#define R_386_NUM       11
-
-/* SUN SPARC specific definitions.  */
-
-/* Values for Elf64_Ehdr.e_flags.  */
-
-#define EF_SPARCV9_MM           3
-#define EF_SPARCV9_TSO          0
-#define EF_SPARCV9_PSO          1
-#define EF_SPARCV9_RMO          2
-#define EF_SPARC_EXT_MASK       0xFFFF00
-#define EF_SPARC_SUN_US1        0x000200
-#define EF_SPARC_HAL_R1         0x000400
-
-/* SPARC relocs.  */
-
-#define R_SPARC_NONE    0               /* No reloc */
-#define R_SPARC_8       1               /* Direct 8 bit */
-#define R_SPARC_16      2               /* Direct 16 bit */
-#define R_SPARC_32      3               /* Direct 32 bit */
-#define R_SPARC_DISP8   4               /* PC relative 8 bit */
-#define R_SPARC_DISP16  5               /* PC relative 16 bit */
-#define R_SPARC_DISP32  6               /* PC relative 32 bit */
-#define R_SPARC_WDISP30 7               /* PC relative 30 bit shifted */
-#define R_SPARC_WDISP22 8               /* PC relative 22 bit shifted */
-#define R_SPARC_HI22    9               /* High 22 bit */
-#define R_SPARC_22      10              /* Direct 22 bit */
-#define R_SPARC_13      11              /* Direct 13 bit */
-#define R_SPARC_LO10    12              /* Truncated 10 bit */
-#define R_SPARC_GOT10   13              /* Truncated 10 bit GOT entry */
-#define R_SPARC_GOT13   14              /* 13 bit GOT entry */
-#define R_SPARC_GOT22   15              /* 22 bit GOT entry shifted */
-#define R_SPARC_PC10    16              /* PC relative 10 bit truncated */
-#define R_SPARC_PC22    17              /* PC relative 22 bit shifted */
-#define R_SPARC_WPLT30  18              /* 30 bit PC relative PLT address */
-#define R_SPARC_COPY    19              /* Copy symbol at runtime */
-#define R_SPARC_GLOB_DAT 20             /* Create GOT entry */
-#define R_SPARC_JMP_SLOT 21             /* Create PLT entry */
-#define R_SPARC_RELATIVE 22             /* Adjust by program base */
-#define R_SPARC_UA32    23              /* Direct 32 bit unaligned */
-
-/* Additional Sparc64 relocs.  */
-
-#define R_SPARC_PLT32   24              /* Direct 32 bit ref to PLT entry */
-#define R_SPARC_HIPLT22 25              /* High 22 bit PLT entry */
-#define R_SPARC_LOPLT10 26              /* Truncated 10 bit PLT entry */
-#define R_SPARC_PCPLT32 27              /* PC rel 32 bit ref to PLT entry */
-#define R_SPARC_PCPLT22 28              /* PC rel high 22 bit PLT entry */
-#define R_SPARC_PCPLT10 29              /* PC rel trunc 10 bit PLT entry */
-#define R_SPARC_10      30              /* Direct 10 bit */
-#define R_SPARC_11      31              /* Direct 11 bit */
-#define R_SPARC_64      32              /* Direct 64 bit */
-#define R_SPARC_OLO10   33              /* ?? */
-#define R_SPARC_HH22    34              /* Top 22 bits of direct 64 bit */
-#define R_SPARC_HM10    35              /* High middle 10 bits of ... */
-#define R_SPARC_LM22    36              /* Low middle 22 bits of ... */
-#define R_SPARC_PC_HH22 37              /* Top 22 bits of pc rel 64 bit */
-#define R_SPARC_PC_HM10 38              /* High middle 10 bit of ... */
-#define R_SPARC_PC_LM22 39              /* Low miggle 22 bits of ... */
-#define R_SPARC_WDISP16 40              /* PC relative 16 bit shifted */
-#define R_SPARC_WDISP19 41              /* PC relative 19 bit shifted */
-#define R_SPARC_7       43              /* Direct 7 bit */
-#define R_SPARC_5       44              /* Direct 5 bit */
-#define R_SPARC_6       45              /* Direct 6 bit */
-#define R_SPARC_DISP64  46              /* PC relative 64 bit */
-#define R_SPARC_PLT64   47              /* Direct 64 bit ref to PLT entry */
-#define R_SPARC_HIX22   48              /* High 22 bit complemented */
-#define R_SPARC_LOX10   49              /* Truncated 11 bit complemented */
-#define R_SPARC_H44     50              /* Direct high 12 of 44 bit */
-#define R_SPARC_M44     51              /* Direct mid 22 of 44 bit */
-#define R_SPARC_L44     52              /* Direct low 10 of 44 bit */
-#define R_SPARC_REGISTER 53             /* Global register usage */
-#define R_SPARC_UA64    54              /* Direct 64 bit unaligned */
-#define R_SPARC_UA16    55              /* Direct 16 bit unaligned */
-/* Keep this the last entry.  */
-#define R_SPARC_NUM     56
-
-/* AMD x86-64 relocations.  */
-#define R_X86_64_NONE		0	/* No reloc */
-#define R_X86_64_64		1	/* Direct 64 bit  */
-#define R_X86_64_PC32		2	/* PC relative 32 bit signed */
-#define R_X86_64_GOT32		3	/* 32 bit GOT entry */
-#define R_X86_64_PLT32		4	/* 32 bit PLT address */
-#define R_X86_64_COPY		5	/* Copy symbol at runtime */
-#define R_X86_64_GLOB_DAT	6	/* Create GOT entry */
-#define R_X86_64_JUMP_SLOT	7	/* Create PLT entry */
-#define R_X86_64_RELATIVE	8	/* Adjust by program base */
-#define R_X86_64_GOTPCREL	9	/* 32 bit signed PC relative
-					   offset to GOT */
-#define R_X86_64_32		10	/* Direct 32 bit zero extended */
-#define R_X86_64_32S		11	/* Direct 32 bit sign extended */
-#define R_X86_64_16		12	/* Direct 16 bit zero extended */
-#define R_X86_64_PC16		13	/* 16 bit sign extended pc relative */
-#define R_X86_64_8		14	/* Direct 8 bit sign extended  */
-#define R_X86_64_PC8		15	/* 8 bit sign extended pc relative */
-#define R_X86_64_DTPMOD64	16	/* ID of module containing symbol */
-#define R_X86_64_DTPOFF64	17	/* Offset in module's TLS block */
-#define R_X86_64_TPOFF64	18	/* Offset in initial TLS block */
-#define R_X86_64_TLSGD		19	/* 32 bit signed PC relative offset
-					   to two GOT entries for GD symbol */
-#define R_X86_64_TLSLD		20	/* 32 bit signed PC relative offset
-					   to two GOT entries for LD symbol */
-#define R_X86_64_DTPOFF32	21	/* Offset in TLS block */
-#define R_X86_64_GOTTPOFF	22	/* 32 bit signed PC relative offset
-					   to GOT entry for IE symbol */
-#define R_X86_64_TPOFF32	23	/* Offset in initial TLS block */
-
-#define R_X86_64_NUM		24
-
-/* For Sparc64, legal values for d_tag of Elf64_Dyn.  */
-
-#define DT_SPARC_REGISTER 0x70000001
-#define DT_SPARC_NUM    2
-
-/* Bits present in AT_HWCAP, primarily for Sparc32.  */
-
-#define HWCAP_SPARC_FLUSH       1       /* The cpu supports flush insn.  */
-#define HWCAP_SPARC_STBAR       2
-#define HWCAP_SPARC_SWAP        4
-#define HWCAP_SPARC_MULDIV      8
-#define HWCAP_SPARC_V9          16      /* The cpu is v9, so v8plus is ok.  */
-
-/* MIPS R3000 specific definitions.  */
-
-/* Legal values for e_flags field of Elf32_Ehdr.  */
-
-#define EF_MIPS_NOREORDER   1           /* A .noreorder directive was used */
-#define EF_MIPS_PIC         2           /* Contains PIC code */
-#define EF_MIPS_CPIC        4           /* Uses PIC calling sequence */
-#define EF_MIPS_XGOT        8
-#define EF_MIPS_64BIT_WHIRL 16
-#define EF_MIPS_ABI2        32
-#define EF_MIPS_ABI_ON32    64
-#define EF_MIPS_ARCH        0xf0000000  /* MIPS architecture level */
-
-/* Legal values for MIPS architecture level.  */
-
-#define EF_MIPS_ARCH_1      0x00000000  /* -mips1 code.  */
-#define EF_MIPS_ARCH_2      0x10000000  /* -mips2 code.  */
-#define EF_MIPS_ARCH_3      0x20000000  /* -mips3 code.  */
-#define EF_MIPS_ARCH_4      0x30000000  /* -mips4 code.  */
-#define EF_MIPS_ARCH_5      0x40000000  /* -mips5 code.  */
-
-/* The following are non-official names and should not be used.  */
-
-#define E_MIPS_ARCH_1     0x00000000    /* -mips1 code.  */
-#define E_MIPS_ARCH_2     0x10000000    /* -mips2 code.  */
-#define E_MIPS_ARCH_3     0x20000000    /* -mips3 code.  */
-#define E_MIPS_ARCH_4     0x30000000    /* -mips4 code.  */
-#define E_MIPS_ARCH_5     0x40000000    /* -mips5 code.  */
-
-/* Special section indices.  */
-
-#define SHN_MIPS_ACOMMON 0xff00         /* Allocated common symbols */
-#define SHN_MIPS_TEXT    0xff01         /* Allocated test symbols.  */
-#define SHN_MIPS_DATA    0xff02         /* Allocated data symbols.  */
-#define SHN_MIPS_SCOMMON 0xff03         /* Small common symbols */
-#define SHN_MIPS_SUNDEFINED 0xff04      /* Small undefined symbols */
-
-/* Legal values for sh_type field of Elf32_Shdr.  */
-
-#define SHT_MIPS_LIBLIST       0x70000000 /* Shared objects used in link */
-#define SHT_MIPS_MSYM          0x70000001
-#define SHT_MIPS_CONFLICT      0x70000002 /* Conflicting symbols */
-#define SHT_MIPS_GPTAB         0x70000003 /* Global data area sizes */
-#define SHT_MIPS_UCODE         0x70000004 /* Reserved for SGI/MIPS compilers */
-#define SHT_MIPS_DEBUG         0x70000005 /* MIPS ECOFF debugging information*/
-#define SHT_MIPS_REGINFO       0x70000006 /* Register usage information */
-#define SHT_MIPS_PACKAGE       0x70000007
-#define SHT_MIPS_PACKSYM       0x70000008
-#define SHT_MIPS_RELD          0x70000009
-#define SHT_MIPS_IFACE         0x7000000b
-#define SHT_MIPS_CONTENT       0x7000000c
-#define SHT_MIPS_OPTIONS       0x7000000d /* Miscellaneous options.  */
-#define SHT_MIPS_SHDR          0x70000010
-#define SHT_MIPS_FDESC         0x70000011
-#define SHT_MIPS_EXTSYM        0x70000012
-#define SHT_MIPS_DENSE         0x70000013
-#define SHT_MIPS_PDESC         0x70000014
-#define SHT_MIPS_LOCSYM        0x70000015
-#define SHT_MIPS_AUXSYM        0x70000016
-#define SHT_MIPS_OPTSYM        0x70000017
-#define SHT_MIPS_LOCSTR        0x70000018
-#define SHT_MIPS_LINE          0x70000019
-#define SHT_MIPS_RFDESC        0x7000001a
-#define SHT_MIPS_DELTASYM      0x7000001b
-#define SHT_MIPS_DELTAINST     0x7000001c
-#define SHT_MIPS_DELTACLASS    0x7000001d
-#define SHT_MIPS_DWARF         0x7000001e /* DWARF debugging information.  */
-#define SHT_MIPS_DELTADECL     0x7000001f
-#define SHT_MIPS_SYMBOL_LIB    0x70000020
-#define SHT_MIPS_EVENTS        0x70000021 /* Event section.  */
-#define SHT_MIPS_TRANSLATE     0x70000022
-#define SHT_MIPS_PIXIE         0x70000023
-#define SHT_MIPS_XLATE         0x70000024
-#define SHT_MIPS_XLATE_DEBUG   0x70000025
-#define SHT_MIPS_WHIRL         0x70000026
-#define SHT_MIPS_EH_REGION     0x70000027
-#define SHT_MIPS_XLATE_OLD     0x70000028
-#define SHT_MIPS_PDR_EXCEPTION 0x70000029
-
-/* Legal values for sh_flags field of Elf32_Shdr.  */
-
-#define SHF_MIPS_GPREL   0x10000000     /* Must be part of global data area */
-#define SHF_MIPS_MERGE   0x20000000
-#define SHF_MIPS_ADDR    0x40000000
-#define SHF_MIPS_STRINGS 0x80000000
-#define SHF_MIPS_NOSTRIP 0x08000000
-#define SHF_MIPS_LOCAL   0x04000000
-#define SHF_MIPS_NAMES   0x02000000
-#define SHF_MIPS_NODUPE  0x01000000
-
-
-/* Symbol tables.  */
-
-/* MIPS specific values for `st_other'.  */
-#define STO_MIPS_DEFAULT                0x0
-#define STO_MIPS_INTERNAL               0x1
-#define STO_MIPS_HIDDEN                 0x2
-#define STO_MIPS_PROTECTED              0x3
-#define STO_MIPS_SC_ALIGN_UNUSED        0xff
-
-/* MIPS specific values for `st_info'.  */
-#define STB_MIPS_SPLIT_COMMON           13
-
-/* Entries found in sections of type SHT_MIPS_GPTAB.  */
-
-typedef union
-{
-  struct
-    {
-      Elf32_Word gt_current_g_value;    /* -G value used for compilation */
-      Elf32_Word gt_unused;             /* Not used */
-    } gt_header;                        /* First entry in section */
-  struct
-    {
-      Elf32_Word gt_g_value;            /* If this value were used for -G */
-      Elf32_Word gt_bytes;              /* This many bytes would be used */
-    } gt_entry;                         /* Subsequent entries in section */
-} Elf32_gptab;
-
-/* Entry found in sections of type SHT_MIPS_REGINFO.  */
-
-typedef struct
-{
-  Elf32_Word    ri_gprmask;             /* General registers used */
-  Elf32_Word    ri_cprmask[4];          /* Coprocessor registers used */
-  Elf32_Sword   ri_gp_value;            /* $gp register value */
-} Elf32_RegInfo;
-
-/* Entries found in sections of type SHT_MIPS_OPTIONS.  */
-
-typedef struct
-{
-  unsigned char kind;           /* Determines interpretation of the
-                                   variable part of descriptor.  */
-  unsigned char size;           /* Size of descriptor, including header.  */
-  Elf32_Section section;        /* Section header index of section affected,
-                                   0 for global options.  */
-  Elf32_Word info;              /* Kind-specific information.  */
-} Elf_Options;
-
-/* Values for `kind' field in Elf_Options.  */
-
-#define ODK_NULL        0       /* Undefined.  */
-#define ODK_REGINFO     1       /* Register usage information.  */
-#define ODK_EXCEPTIONS  2       /* Exception processing options.  */
-#define ODK_PAD         3       /* Section padding options.  */
-#define ODK_HWPATCH     4       /* Hardware workarounds performed */
-#define ODK_FILL        5       /* record the fill value used by the linker. */
-#define ODK_TAGS        6       /* reserve space for desktop tools to write. */
-#define ODK_HWAND       7       /* HW workarounds.  'AND' bits when merging. */
-#define ODK_HWOR        8       /* HW workarounds.  'OR' bits when merging.  */
-
-/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries.  */
-
-#define OEX_FPU_MIN     0x1f    /* FPE's which MUST be enabled.  */
-#define OEX_FPU_MAX     0x1f00  /* FPE's which MAY be enabled.  */
-#define OEX_PAGE0       0x10000 /* page zero must be mapped.  */
-#define OEX_SMM         0x20000 /* Force sequential memory mode?  */
-#define OEX_FPDBUG      0x40000 /* Force floating point debug mode?  */
-#define OEX_PRECISEFP   OEX_FPDBUG
-#define OEX_DISMISS     0x80000 /* Dismiss invalid address faults?  */
-
-#define OEX_FPU_INVAL   0x10
-#define OEX_FPU_DIV0    0x08
-#define OEX_FPU_OFLO    0x04
-#define OEX_FPU_UFLO    0x02
-#define OEX_FPU_INEX    0x01
-
-/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry.  */
-
-#define OHW_R4KEOP      0x1     /* R4000 end-of-page patch.  */
-#define OHW_R8KPFETCH   0x2     /* may need R8000 prefetch patch.  */
-#define OHW_R5KEOP      0x4     /* R5000 end-of-page patch.  */
-#define OHW_R5KCVTL     0x8     /* R5000 cvt.[ds].l bug.  clean=1.  */
-
-#define OPAD_PREFIX     0x1
-#define OPAD_POSTFIX    0x2
-#define OPAD_SYMBOL     0x4
-
-/* Entry found in `.options' section.  */
-
-typedef struct
-{
-  Elf32_Word hwp_flags1;        /* Extra flags.  */
-  Elf32_Word hwp_flags2;        /* Extra flags.  */
-} Elf_Options_Hw;
-
-/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries.  */
-
-#define OHWA0_R4KEOP_CHECKED    0x00000001
-#define OHWA1_R4KEOP_CLEAN      0x00000002
-
-/* MIPS relocs.  */
-
-#define R_MIPS_NONE             0       /* No reloc */
-#define R_MIPS_16               1       /* Direct 16 bit */
-#define R_MIPS_32               2       /* Direct 32 bit */
-#define R_MIPS_REL32            3       /* PC relative 32 bit */
-#define R_MIPS_26               4       /* Direct 26 bit shifted */
-#define R_MIPS_HI16             5       /* High 16 bit */
-#define R_MIPS_LO16             6       /* Low 16 bit */
-#define R_MIPS_GPREL16          7       /* GP relative 16 bit */
-#define R_MIPS_LITERAL          8       /* 16 bit literal entry */
-#define R_MIPS_GOT16            9       /* 16 bit GOT entry */
-#define R_MIPS_PC16             10      /* PC relative 16 bit */
-#define R_MIPS_CALL16           11      /* 16 bit GOT entry for function */
-#define R_MIPS_GPREL32          12      /* GP relative 32 bit */
-
-#define R_MIPS_SHIFT5           16
-#define R_MIPS_SHIFT6           17
-#define R_MIPS_64               18
-#define R_MIPS_GOT_DISP         19
-#define R_MIPS_GOT_PAGE         20
-#define R_MIPS_GOT_OFST         21
-#define R_MIPS_GOT_HI16         22
-#define R_MIPS_GOT_LO16         23
-#define R_MIPS_SUB              24
-#define R_MIPS_INSERT_A         25
-#define R_MIPS_INSERT_B         26
-#define R_MIPS_DELETE           27
-#define R_MIPS_HIGHER           28
-#define R_MIPS_HIGHEST          29
-#define R_MIPS_CALL_HI16        30
-#define R_MIPS_CALL_LO16        31
-#define R_MIPS_SCN_DISP         32
-#define R_MIPS_REL16            33
-#define R_MIPS_ADD_IMMEDIATE    34
-#define R_MIPS_PJUMP            35
-#define R_MIPS_RELGOT           36
-#define R_MIPS_JALR             37
-/* Keep this the last entry.  */
-#define R_MIPS_NUM              38
-
-/* Legal values for p_type field of Elf32_Phdr.  */
-
-#define PT_MIPS_REGINFO 0x70000000      /* Register usage information */
-#define PT_MIPS_RTPROC  0x70000001      /* Runtime procedure table. */
-#define PT_MIPS_OPTIONS 0x70000002
-
-/* Special program header types.  */
-
-#define PF_MIPS_LOCAL   0x10000000
-
-/* Legal values for d_tag field of Elf32_Dyn.  */
-
-#define DT_MIPS_RLD_VERSION  0x70000001 /* Runtime linker interface version */
-#define DT_MIPS_TIME_STAMP   0x70000002 /* Timestamp */
-#define DT_MIPS_ICHECKSUM    0x70000003 /* Checksum */
-#define DT_MIPS_IVERSION     0x70000004 /* Version string (string tbl index) */
-#define DT_MIPS_FLAGS        0x70000005 /* Flags */
-#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */
-#define DT_MIPS_MSYM         0x70000007
-#define DT_MIPS_CONFLICT     0x70000008 /* Address of CONFLICT section */
-#define DT_MIPS_LIBLIST      0x70000009 /* Address of LIBLIST section */
-#define DT_MIPS_LOCAL_GOTNO  0x7000000a /* Number of local GOT entries */
-#define DT_MIPS_CONFLICTNO   0x7000000b /* Number of CONFLICT entries */
-#define DT_MIPS_LIBLISTNO    0x70000010 /* Number of LIBLIST entries */
-#define DT_MIPS_SYMTABNO     0x70000011 /* Number of DYNSYM entries */
-#define DT_MIPS_UNREFEXTNO   0x70000012 /* First external DYNSYM */
-#define DT_MIPS_GOTSYM       0x70000013 /* First GOT entry in DYNSYM */
-#define DT_MIPS_HIPAGENO     0x70000014 /* Number of GOT page table entries */
-#define DT_MIPS_RLD_MAP      0x70000016 /* Address of run time loader map.  */
-#define DT_MIPS_DELTA_CLASS  0x70000017 /* Delta C++ class definition.  */
-#define DT_MIPS_DELTA_CLASS_NO    0x70000018 /* Number of entries in
-                                                DT_MIPS_DELTA_CLASS.  */
-#define DT_MIPS_DELTA_INSTANCE    0x70000019 /* Delta C++ class instances.  */
-#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
-                                                DT_MIPS_DELTA_INSTANCE.  */
-#define DT_MIPS_DELTA_RELOC  0x7000001b /* Delta relocations.  */
-#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
-                                             DT_MIPS_DELTA_RELOC.  */
-#define DT_MIPS_DELTA_SYM    0x7000001d /* Delta symbols that Delta
-                                           relocations refer to.  */
-#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
-                                           DT_MIPS_DELTA_SYM.  */
-#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
-                                             class declaration.  */
-#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
-                                                DT_MIPS_DELTA_CLASSSYM.  */
-#define DT_MIPS_CXX_FLAGS    0x70000022 /* Flags indicating for C++ flavor.  */
-#define DT_MIPS_PIXIE_INIT   0x70000023
-#define DT_MIPS_SYMBOL_LIB   0x70000024
-#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
-#define DT_MIPS_LOCAL_GOTIDX 0x70000026
-#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
-#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
-#define DT_MIPS_OPTIONS      0x70000029 /* Address of .options.  */
-#define DT_MIPS_INTERFACE    0x7000002a /* Address of .interface.  */
-#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
-#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
-#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
-                                                    function stored in GOT.  */
-#define DT_MIPS_PERF_SUFFIX  0x7000002e /* Default suffix of dso to be added
-                                           by rld on dlopen() calls.  */
-#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
-#define DT_MIPS_GP_VALUE     0x70000030 /* GP value for aux GOTs.  */
-#define DT_MIPS_AUX_DYNAMIC  0x70000031 /* Address of aux .dynamic.  */
-#define DT_MIPS_NUM          0x32
-
-/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry.  */
-
-#define RHF_NONE                   0            /* No flags */
-#define RHF_QUICKSTART             (1 << 0)     /* Use quickstart */
-#define RHF_NOTPOT                 (1 << 1)     /* Hash size not power of 2 */
-#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)     /* Ignore LD_LIBRARY_PATH */
-#define RHF_NO_MOVE                (1 << 3)
-#define RHF_SGI_ONLY               (1 << 4)
-#define RHF_GUARANTEE_INIT         (1 << 5)
-#define RHF_DELTA_C_PLUS_PLUS      (1 << 6)
-#define RHF_GUARANTEE_START_INIT   (1 << 7)
-#define RHF_PIXIE                  (1 << 8)
-#define RHF_DEFAULT_DELAY_LOAD     (1 << 9)
-#define RHF_REQUICKSTART           (1 << 10)
-#define RHF_REQUICKSTARTED         (1 << 11)
-#define RHF_CORD                   (1 << 12)
-#define RHF_NO_UNRES_UNDEF         (1 << 13)
-#define RHF_RLD_ORDER_SAFE         (1 << 14)
-
-/* Entries found in sections of type SHT_MIPS_LIBLIST.  */
-
-typedef struct
-{
-  Elf32_Word l_name;            /* Name (string table index) */
-  Elf32_Word l_time_stamp;      /* Timestamp */
-  Elf32_Word l_checksum;        /* Checksum */
-  Elf32_Word l_version;         /* Interface version */
-  Elf32_Word l_flags;           /* Flags */
-} Elf32_Lib;
-
-typedef struct
-{
-  Elf64_Word l_name;            /* Name (string table index) */
-  Elf64_Word l_time_stamp;      /* Timestamp */
-  Elf64_Word l_checksum;        /* Checksum */
-  Elf64_Word l_version;         /* Interface version */
-  Elf64_Word l_flags;           /* Flags */
-} Elf64_Lib;
-
-
-/* Legal values for l_flags.  */
-
-#define LL_NONE           0
-#define LL_EXACT_MATCH    (1 << 0)      /* Require exact match */
-#define LL_IGNORE_INT_VER (1 << 1)      /* Ignore interface version */
-#define LL_REQUIRE_MINOR  (1 << 2)
-#define LL_EXPORTS        (1 << 3)
-#define LL_DELAY_LOAD     (1 << 4)
-#define LL_DELTA          (1 << 5)
-
-/* Entries found in sections of type SHT_MIPS_CONFLICT.  */
-
-typedef Elf32_Addr Elf32_Conflict;
-
-
-/* HPPA specific definitions.  */
-
-/* Legal values for e_flags field of Elf32_Ehdr.  */
-
-#define EF_PARISC_TRAPNL        1       /* Trap nil pointer dereference.  */
-#define EF_PARISC_EXT           2       /* Program uses arch. extensions.  */
-#define EF_PARISC_ARCH          0xffff0000 /* Architecture version.  */
-/* Defined values are:
-                                0x020b  PA-RISC 1.0 big-endian
-                                0x0210  PA-RISC 1.1 big-endian
-                                0x028b  PA-RISC 1.0 little-endian
-                                0x0290  PA-RISC 1.1 little-endian
-*/
-
-/* Legal values for sh_type field of Elf32_Shdr.  */
-
-#define SHT_PARISC_GOT          0x70000000 /* GOT for external data.  */
-#define SHT_PARISC_ARCH         0x70000001 /* Architecture extensions.  */
-#define SHT_PARISC_GLOBAL       0x70000002 /* Definition of $global$.  */
-#define SHT_PARISC_MILLI        0x70000003 /* Millicode routines.  */
-#define SHT_PARISC_UNWIND       0x70000004 /* Unwind information.  */
-#define SHT_PARISC_PLT          0x70000005 /* Procedure linkage table.  */
-#define SHT_PARISC_SDATA        0x70000006 /* Short initialized data.  */
-#define SHT_PARISC_SBSS         0x70000007 /* Short uninitialized data.  */
-#define SHT_PARISC_SYMEXTN      0x70000008 /* Argument/relocation info.  */
-#define SHT_PARISC_STUBS        0x70000009 /* Linker stubs.  */
-
-/* Legal values for sh_flags field of Elf32_Shdr.  */
-
-#define SHF_PARISC_GLOBAL       0x10000000 /* Section defines dp.  */
-#define SHF_PARISC_SHORT        0x20000000 /* Section with short addressing. */
-
-/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
-
-#define STT_PARISC_MILLICODE    13      /* Millicode function entry point.  */
-
-/* HPPA relocs.  */
-
-#define R_PARISC_NONE           0       /* No reloc.  */
-#define R_PARISC_DIR32          1       /* Direct 32-bit reference.  */
-#define R_PARISC_DIR21L         2       /* Left 21 bits of eff. address.  */
-#define R_PARISC_DIR17R         3       /* Right 17 bits of eff. address.  */
-#define R_PARISC_DIR14R         4       /* Right 14 bits of eff. address.  */
-#define R_PARISC_PCREL21L       5       /* PC-relative, left 21 bits.  */
-#define R_PARISC_PCREL14R       6       /* PC-relative, right 14 bits.  */
-#define R_PARISC_PCREL17C       7       /* Conditional PC-relative, ignore
-                                           if displacement > 17bits.  */
-#define R_PARISC_PCREL17F       8       /* Conditional PC-relative, must
-                                           fit in 17bits.  */
-#define R_PARISC_DPREL21L       9       /* DP-relative, left 21 bits.  */
-#define R_PARISC_DPREL14R       10      /* DP-relative, right 14 bits.  */
-#define R_PARISC_DPREL14F       11      /* DP-relative, must bit in 14 bits. */
-#define R_PARISC_DLTREL21L      12      /* DLT-relative, left 21 bits.  */
-#define R_PARISC_DLTREL14R      13      /* DLT-relative, right 14 bits.  */
-#define R_PARISC_DLTREL14F      14      /* DLT-relative, must fit in 14 bits.*/
-#define R_PARISC_DLTIND21L      15      /* DLT-relative indirect, left
-                                           21 bits.  */
-#define R_PARISC_DLTIND14R      16      /* DLT-relative indirect, right
-                                           14 bits.  */
-#define R_PARISC_DLTIND14F      17      /* DLT-relative indirect, must fit
-                                           int 14 bits.  */
-#define R_PARISC_PLABEL32       18      /* Direct 32-bit reference to proc.  */
-
-/* Alpha specific definitions.  */
-
-/* Legal values for e_flags field of Elf64_Ehdr.  */
-
-#define EF_ALPHA_32BIT          1       /* All addresses must be < 2GB.  */
-#define EF_ALPHA_CANRELAX       2       /* Relocations for relaxing exist.  */
-
-/* Legal values for sh_type field of Elf64_Shdr.  */
-
-/* These two are primerily concerned with ECOFF debugging info.  */
-#define SHT_ALPHA_DEBUG         0x70000001
-#define SHT_ALPHA_REGINFO       0x70000002
-
-/* Legal values for sh_flags field of Elf64_Shdr.  */
-
-#define SHF_ALPHA_GPREL         0x10000000
-
-/* Legal values for st_other field of Elf64_Sym.  */
-#define STO_ALPHA_NOPV          0x80    /* No PV required.  */
-#define STO_ALPHA_STD_GPLOAD    0x88    /* PV only used for initial ldgp.  */
-
-/* Alpha relocs.  */
-
-#define R_ALPHA_NONE            0       /* No reloc */
-#define R_ALPHA_REFLONG         1       /* Direct 32 bit */
-#define R_ALPHA_REFQUAD         2       /* Direct 64 bit */
-#define R_ALPHA_GPREL32         3       /* GP relative 32 bit */
-#define R_ALPHA_LITERAL         4       /* GP relative 16 bit w/optimization */
-#define R_ALPHA_LITUSE          5       /* Optimization hint for LITERAL */
-#define R_ALPHA_GPDISP          6       /* Add displacement to GP */
-#define R_ALPHA_BRADDR          7       /* PC+4 relative 23 bit shifted */
-#define R_ALPHA_HINT            8       /* PC+4 relative 16 bit shifted */
-#define R_ALPHA_SREL16          9       /* PC relative 16 bit */
-#define R_ALPHA_SREL32          10      /* PC relative 32 bit */
-#define R_ALPHA_SREL64          11      /* PC relative 64 bit */
-#define R_ALPHA_OP_PUSH         12      /* OP stack push */
-#define R_ALPHA_OP_STORE        13      /* OP stack pop and store */
-#define R_ALPHA_OP_PSUB         14      /* OP stack subtract */
-#define R_ALPHA_OP_PRSHIFT      15      /* OP stack right shift */
-#define R_ALPHA_GPVALUE         16
-#define R_ALPHA_GPRELHIGH       17
-#define R_ALPHA_GPRELLOW        18
-#define R_ALPHA_IMMED_GP_16     19
-#define R_ALPHA_IMMED_GP_HI32   20
-#define R_ALPHA_IMMED_SCN_HI32  21
-#define R_ALPHA_IMMED_BR_HI32   22
-#define R_ALPHA_IMMED_LO32      23
-#define R_ALPHA_COPY            24      /* Copy symbol at runtime */
-#define R_ALPHA_GLOB_DAT        25      /* Create GOT entry */
-#define R_ALPHA_JMP_SLOT        26      /* Create PLT entry */
-#define R_ALPHA_RELATIVE        27      /* Adjust by program base */
-/* Keep this the last entry.  */
-#define R_ALPHA_NUM             28
-
-
-/* PowerPC specific declarations */
-
-/* PowerPC relocations defined by the ABIs */
-#define R_PPC_NONE              0
-#define R_PPC_ADDR32            1       /* 32bit absolute address */
-#define R_PPC_ADDR24            2       /* 26bit address, 2 bits ignored.  */
-#define R_PPC_ADDR16            3       /* 16bit absolute address */
-#define R_PPC_ADDR16_LO         4       /* lower 16bit of absolute address */
-#define R_PPC_ADDR16_HI         5       /* high 16bit of absolute address */
-#define R_PPC_ADDR16_HA         6       /* adjusted high 16bit */
-#define R_PPC_ADDR14            7       /* 16bit address, 2 bits ignored */
-#define R_PPC_ADDR14_BRTAKEN    8
-#define R_PPC_ADDR14_BRNTAKEN   9
-#define R_PPC_REL24             10      /* PC relative 26 bit */
-#define R_PPC_REL14             11      /* PC relative 16 bit */
-#define R_PPC_REL14_BRTAKEN     12
-#define R_PPC_REL14_BRNTAKEN    13
-#define R_PPC_GOT16             14
-#define R_PPC_GOT16_LO          15
-#define R_PPC_GOT16_HI          16
-#define R_PPC_GOT16_HA          17
-#define R_PPC_PLTREL24          18
-#define R_PPC_COPY              19
-#define R_PPC_GLOB_DAT          20
-#define R_PPC_JMP_SLOT          21
-#define R_PPC_RELATIVE          22
-#define R_PPC_LOCAL24PC         23
-#define R_PPC_UADDR32           24
-#define R_PPC_UADDR16           25
-#define R_PPC_REL32             26
-#define R_PPC_PLT32             27
-#define R_PPC_PLTREL32          28
-#define R_PPC_PLT16_LO          29
-#define R_PPC_PLT16_HI          30
-#define R_PPC_PLT16_HA          31
-#define R_PPC_SDAREL16          32
-#define R_PPC_SECTOFF           33
-#define R_PPC_SECTOFF_LO        34
-#define R_PPC_SECTOFF_HI        35
-#define R_PPC_SECTOFF_HA        36
-/* Keep this the last entry.  */
-#define R_PPC_NUM               37
-
-/* The remaining relocs are from the Embedded ELF ABI, and are not
-   in the SVR4 ELF ABI.  */
-#define R_PPC_EMB_NADDR32       101
-#define R_PPC_EMB_NADDR16       102
-#define R_PPC_EMB_NADDR16_LO    103
-#define R_PPC_EMB_NADDR16_HI    104
-#define R_PPC_EMB_NADDR16_HA    105
-#define R_PPC_EMB_SDAI16        106
-#define R_PPC_EMB_SDA2I16       107
-#define R_PPC_EMB_SDA2REL       108
-#define R_PPC_EMB_SDA21         109     /* 16 bit offset in SDA */
-#define R_PPC_EMB_MRKREF        110
-#define R_PPC_EMB_RELSEC16      111
-#define R_PPC_EMB_RELST_LO      112
-#define R_PPC_EMB_RELST_HI      113
-#define R_PPC_EMB_RELST_HA      114
-#define R_PPC_EMB_BIT_FLD       115
-#define R_PPC_EMB_RELSDA        116     /* 16 bit relative offset in SDA */
-
-/* Diab tool relocations.  */
-#define R_PPC_DIAB_SDA21_LO     180     /* like EMB_SDA21, but lower 16 bit */
-#define R_PPC_DIAB_SDA21_HI     181     /* like EMB_SDA21, but high 16 bit */
-#define R_PPC_DIAB_SDA21_HA     182     /* like EMB_SDA21, adjusted high 16 */
-#define R_PPC_DIAB_RELSDA_LO    183     /* like EMB_RELSDA, but lower 16 bit */
-#define R_PPC_DIAB_RELSDA_HI    184     /* like EMB_RELSDA, but high 16 bit */
-#define R_PPC_DIAB_RELSDA_HA    185     /* like EMB_RELSDA, adjusted high 16 */
-
-/* This is a phony reloc to handle any old fashioned TOC16 references
-   that may still be in object files.  */
-#define R_PPC_TOC16             255
-
-
-/* ARM specific declarations */
-
-/* Processor specific flags for the ELF header e_flags field.  */
-#define EF_ARM_RELEXEC     0x01
-#define EF_ARM_HASENTRY    0x02
-#define EF_ARM_INTERWORK   0x04
-#define EF_ARM_APCS_26     0x08
-#define EF_ARM_APCS_FLOAT  0x10
-#define EF_ARM_PIC         0x20
-#define EF_ALIGN8          0x40         /* 8-bit structure alignment is in use */
-#define EF_NEW_ABI         0x80
-#define EF_OLD_ABI         0x100
-
-/* Additional symbol types for Thumb */
-#define STT_ARM_TFUNC      0xd
-
-/* ARM-specific values for sh_flags */
-#define SHF_ARM_ENTRYSECT  0x10000000   /* Section contains an entry point */
-#define SHF_ARM_COMDEF     0x80000000   /* Section may be multiply defined
-                                           in the input to a link step */
-
-/* ARM-specific program header flags */
-#define PF_ARM_SB          0x10000000   /* Segment contains the location
-                                           addressed by the static base */
-
-/* ARM relocs.  */
-#define R_ARM_NONE              0       /* No reloc */
-#define R_ARM_PC24              1       /* PC relative 26 bit branch */
-#define R_ARM_ABS32             2       /* Direct 32 bit  */
-#define R_ARM_REL32             3       /* PC relative 32 bit */
-#define R_ARM_PC13              4
-#define R_ARM_ABS16             5       /* Direct 16 bit */
-#define R_ARM_ABS12             6       /* Direct 12 bit */
-#define R_ARM_THM_ABS5          7
-#define R_ARM_ABS8              8       /* Direct 8 bit */
-#define R_ARM_SBREL32           9
-#define R_ARM_THM_PC22          10
-#define R_ARM_THM_PC8           11
-#define R_ARM_AMP_VCALL9        12
-#define R_ARM_SWI24             13
-#define R_ARM_THM_SWI8          14
-#define R_ARM_XPC25             15
-#define R_ARM_THM_XPC22         16
-#define R_ARM_COPY              20      /* Copy symbol at runtime */
-#define R_ARM_GLOB_DAT          21      /* Create GOT entry */
-#define R_ARM_JUMP_SLOT         22      /* Create PLT entry */
-#define R_ARM_RELATIVE          23      /* Adjust by program base */
-#define R_ARM_GOTOFF32          24      /* 32 bit offset to GOT */
-#define R_ARM_BASE_PREL         25      /* 32 bit PC relative offset to GOT */
-#define R_ARM_GOT_BREL          26      /* 32 bit GOT entry */
-#define R_ARM_PLT32             27      /* 32 bit PLT address */
-#define R_ARM_CALL              28
-#define R_ARM_JUMP24            29
-#define R_ARM_PREL31            42
-#define R_ARM_GNU_VTENTRY       100
-#define R_ARM_GNU_VTINHERIT     101
-#define R_ARM_THM_PC11          102     /* thumb unconditional branch */
-#define R_ARM_THM_PC9           103     /* thumb conditional branch */
-#define R_ARM_RXPC25            249
-#define R_ARM_RSBREL32          250
-#define R_ARM_THM_RPC22         251
-#define R_ARM_RREL32            252
-#define R_ARM_RABS22            253
-#define R_ARM_RPC24             254
-#define R_ARM_RBASE             255
-/* Keep this the last entry.  */
-#define R_ARM_NUM               256
-
-/* TMS320C67xx specific declarations */
-/* XXX: no ELF standard yet */
-
-/* TMS320C67xx relocs. */
-#define R_C60_32       1
-#define R_C60_GOT32     3               /* 32 bit GOT entry */
-#define R_C60_PLT32     4               /* 32 bit PLT address */
-#define R_C60_COPY      5               /* Copy symbol at runtime */
-#define R_C60_GLOB_DAT  6               /* Create GOT entry */
-#define R_C60_JMP_SLOT  7               /* Create PLT entry */
-#define R_C60_RELATIVE  8               /* Adjust by program base */
-#define R_C60_GOTOFF    9               /* 32 bit offset to GOT */
-#define R_C60_GOTPC     10              /* 32 bit PC relative offset to GOT */
-
-#define R_C60HI16      0x55       // high 16 bit MVKH embedded
-#define R_C60LO16      0x54       // low 16 bit MVKL embedded
-
-#ifdef TCC_TARGET_X86_64
-#define TCC_ELFCLASS ELFCLASS64
-#define ElfW(type) Elf##64##_##type
-#define ELFW(type) ELF##64##_##type
-#else
-#define TCC_ELFCLASS ELFCLASS32
-#define ElfW(type) Elf##32##_##type
-#define ELFW(type) ELF##32##_##type
-#endif
-
-#endif  /* elf.h */

+ 0 - 1211
src/modules/native/tcc/libtcc/i386-asm.c

@@ -1,1211 +0,0 @@
-/*
- *  i386 specific functions for TCC assembler
- * 
- *  Copyright (c) 2001, 2002 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#define MAX_OPERANDS 3
-
-typedef struct ASMInstr {
-    uint16_t sym;
-    uint16_t opcode;
-    uint16_t instr_type;
-#define OPC_JMP       0x01  /* jmp operand */
-#define OPC_B         0x02  /* only used zith OPC_WL */
-#define OPC_WL        0x04  /* accepts w, l or no suffix */
-#define OPC_BWL       (OPC_B | OPC_WL) /* accepts b, w, l or no suffix */
-#define OPC_REG       0x08 /* register is added to opcode */
-#define OPC_MODRM     0x10 /* modrm encoding */
-#define OPC_FWAIT     0x20 /* add fwait opcode */
-#define OPC_TEST      0x40 /* test opcodes */
-#define OPC_SHIFT     0x80 /* shift opcodes */
-#define OPC_D16      0x0100 /* generate data16 prefix */
-#define OPC_ARITH    0x0200 /* arithmetic opcodes */
-#define OPC_SHORTJMP 0x0400 /* short jmp operand */
-#define OPC_FARITH   0x0800 /* FPU arithmetic opcodes */
-#define OPC_GROUP_SHIFT 13
-
-/* in order to compress the operand type, we use specific operands and
-   we or only with EA  */ 
-#define OPT_REG8  0 /* warning: value is hardcoded from TOK_ASM_xxx */
-#define OPT_REG16 1 /* warning: value is hardcoded from TOK_ASM_xxx */
-#define OPT_REG32 2 /* warning: value is hardcoded from TOK_ASM_xxx */
-#define OPT_MMX   3 /* warning: value is hardcoded from TOK_ASM_xxx */
-#define OPT_SSE   4 /* warning: value is hardcoded from TOK_ASM_xxx */
-#define OPT_CR    5 /* warning: value is hardcoded from TOK_ASM_xxx */
-#define OPT_TR    6 /* warning: value is hardcoded from TOK_ASM_xxx */
-#define OPT_DB    7 /* warning: value is hardcoded from TOK_ASM_xxx */
-#define OPT_SEG   8
-#define OPT_ST    9
-#define OPT_IM8   10
-#define OPT_IM8S  11
-#define OPT_IM16  12
-#define OPT_IM32  13
-#define OPT_EAX   14 /* %al, %ax or %eax register */
-#define OPT_ST0   15 /* %st(0) register */
-#define OPT_CL    16 /* %cl register */
-#define OPT_DX    17 /* %dx register */
-#define OPT_ADDR  18 /* OP_EA with only offset */
-#define OPT_INDIR 19 /* *(expr) */
-
-/* composite types */ 
-#define OPT_COMPOSITE_FIRST   20
-#define OPT_IM       20 /* IM8 | IM16 | IM32 */
-#define OPT_REG      21 /* REG8 | REG16 | REG32 */ 
-#define OPT_REGW     22 /* REG16 | REG32 */
-#define OPT_IMW      23 /* IM16 | IM32 */ 
-
-/* can be ored with any OPT_xxx */
-#define OPT_EA    0x80
-
-    uint8_t nb_ops;
-    uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */
-} ASMInstr;
-
-typedef struct Operand {
-    uint32_t type;
-#define OP_REG8   (1 << OPT_REG8)
-#define OP_REG16  (1 << OPT_REG16)
-#define OP_REG32  (1 << OPT_REG32)
-#define OP_MMX    (1 << OPT_MMX)
-#define OP_SSE    (1 << OPT_SSE)
-#define OP_CR     (1 << OPT_CR)
-#define OP_TR     (1 << OPT_TR)
-#define OP_DB     (1 << OPT_DB)
-#define OP_SEG    (1 << OPT_SEG)
-#define OP_ST     (1 << OPT_ST)
-#define OP_IM8    (1 << OPT_IM8)
-#define OP_IM8S   (1 << OPT_IM8S)
-#define OP_IM16   (1 << OPT_IM16)
-#define OP_IM32   (1 << OPT_IM32)
-#define OP_EAX    (1 << OPT_EAX)
-#define OP_ST0    (1 << OPT_ST0)
-#define OP_CL     (1 << OPT_CL)
-#define OP_DX     (1 << OPT_DX)
-#define OP_ADDR   (1 << OPT_ADDR)
-#define OP_INDIR  (1 << OPT_INDIR)
-
-#define OP_EA     0x40000000
-#define OP_REG    (OP_REG8 | OP_REG16 | OP_REG32)
-#define OP_IM     OP_IM32
-    int8_t  reg; /* register, -1 if none */
-    int8_t  reg2; /* second register, -1 if none */
-    uint8_t shift;
-    ExprValue e;
-} Operand;
-
-static const uint8_t reg_to_size[5] = {
-/*
-    [OP_REG8] = 0,
-    [OP_REG16] = 1,
-    [OP_REG32] = 2,
-*/
-    0, 0, 1, 0, 2
-};
-    
-#define WORD_PREFIX_OPCODE 0x66
-
-#define NB_TEST_OPCODES 30
-
-static const uint8_t test_bits[NB_TEST_OPCODES] = {
- 0x00, /* o */
- 0x01, /* no */
- 0x02, /* b */
- 0x02, /* c */
- 0x02, /* nae */
- 0x03, /* nb */
- 0x03, /* nc */
- 0x03, /* ae */
- 0x04, /* e */
- 0x04, /* z */
- 0x05, /* ne */
- 0x05, /* nz */
- 0x06, /* be */
- 0x06, /* na */
- 0x07, /* nbe */
- 0x07, /* a */
- 0x08, /* s */
- 0x09, /* ns */
- 0x0a, /* p */
- 0x0a, /* pe */
- 0x0b, /* np */
- 0x0b, /* po */
- 0x0c, /* l */
- 0x0c, /* nge */
- 0x0d, /* nl */
- 0x0d, /* ge */
- 0x0e, /* le */
- 0x0e, /* ng */
- 0x0f, /* nle */
- 0x0f, /* g */
-};
-
-static const uint8_t segment_prefixes[] = {
- 0x26, /* es */
- 0x2e, /* cs */
- 0x36, /* ss */
- 0x3e, /* ds */
- 0x64, /* fs */
- 0x65  /* gs */
-};
-
-static const ASMInstr asm_instrs[] = {
-#define ALT(x) x
-#define DEF_ASM_OP0(name, opcode)
-#define DEF_ASM_OP0L(name, opcode, group, instr_type) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 0 },
-#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 1, { op0 }},
-#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 2, { op0, op1 }},
-#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 3, { op0, op1, op2 }},
-#include "i386-asm.h"
-
-    /* last operation */
-    { 0, },
-};
-
-static const uint16_t op0_codes[] = {
-#define ALT(x)
-#define DEF_ASM_OP0(x, opcode) opcode,
-#define DEF_ASM_OP0L(name, opcode, group, instr_type)
-#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
-#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
-#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
-#include "i386-asm.h"
-};
-
-static inline int get_reg_shift(TCCState *s1)
-{
-    int shift, v;
-
-    v = asm_int_expr(s1);
-    switch(v) {
-    case 1:
-        shift = 0;
-        break;
-    case 2:
-        shift = 1;
-        break;
-    case 4:
-        shift = 2;
-        break;
-    case 8:
-        shift = 3;
-        break;
-    default:
-        expect("1, 2, 4 or 8 constant");
-        shift = 0;
-        break;
-    }
-    return shift;
-}
-
-static int asm_parse_reg(void)
-{
-    int reg;
-    if (tok != '%')
-        goto error_32;
-    next();
-    if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
-        reg = tok - TOK_ASM_eax;
-        next();
-        return reg;
-    } else {
-    error_32:
-        expect("32 bit register");
-        return 0;
-    }
-}
-
-static void parse_operand(TCCState *s1, Operand *op)
-{
-    ExprValue e;
-    int reg, indir;
-    const char *p;
-
-    indir = 0;
-    if (tok == '*') {
-        next();
-        indir = OP_INDIR;
-    }
-
-    if (tok == '%') {
-        next();
-        if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
-            reg = tok - TOK_ASM_al;
-            op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
-            op->reg = reg & 7;
-            if ((op->type & OP_REG) && op->reg == TREG_EAX)
-                op->type |= OP_EAX;
-            else if (op->type == OP_REG8 && op->reg == TREG_ECX)
-                op->type |= OP_CL;
-            else if (op->type == OP_REG16 && op->reg == TREG_EDX)
-                op->type |= OP_DX;
-        } else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
-            op->type = OP_DB;
-            op->reg = tok - TOK_ASM_dr0;
-        } else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
-            op->type = OP_SEG;
-            op->reg = tok - TOK_ASM_es;
-        } else if (tok == TOK_ASM_st) {
-            op->type = OP_ST;
-            op->reg = 0;
-            next();
-            if (tok == '(') {
-                next();
-                if (tok != TOK_PPNUM)
-                    goto reg_error;
-                p = tokc.cstr->data;
-                reg = p[0] - '0';
-                if ((unsigned)reg >= 8 || p[1] != '\0')
-                    goto reg_error;
-                op->reg = reg;
-                next();
-                skip(')');
-            }
-            if (op->reg == 0)
-                op->type |= OP_ST0;
-            goto no_skip;
-        } else {
-        reg_error:
-            error("unknown register");
-        }
-        next();
-    no_skip: ;
-    } else if (tok == '$') {
-        /* constant value */
-        next();
-        asm_expr(s1, &e);
-        op->type = OP_IM32;
-        op->e.v = e.v;
-        op->e.sym = e.sym;
-        if (!op->e.sym) {
-            if (op->e.v == (uint8_t)op->e.v)
-                op->type |= OP_IM8;
-            if (op->e.v == (int8_t)op->e.v)
-                op->type |= OP_IM8S;
-            if (op->e.v == (uint16_t)op->e.v)
-                op->type |= OP_IM16;
-        }
-    } else {
-        /* address(reg,reg2,shift) with all variants */
-        op->type = OP_EA;
-        op->reg = -1;
-        op->reg2 = -1;
-        op->shift = 0;
-        if (tok != '(') {
-            asm_expr(s1, &e);
-            op->e.v = e.v;
-            op->e.sym = e.sym;
-        } else {
-            op->e.v = 0;
-            op->e.sym = NULL;
-        }
-        if (tok == '(') {
-            next();
-            if (tok != ',') {
-                op->reg = asm_parse_reg();
-            }
-            if (tok == ',') {
-                next();
-                if (tok != ',') {
-                    op->reg2 = asm_parse_reg();
-                } 
-                if (tok == ',') {
-                    next();
-                    op->shift = get_reg_shift(s1);
-                }
-            }
-            skip(')');
-        }
-        if (op->reg == -1 && op->reg2 == -1)
-            op->type |= OP_ADDR;
-    }
-    op->type |= indir;
-}
-
-/* XXX: unify with C code output ? */
-static void gen_expr32(ExprValue *pe)
-{
-    if (pe->sym)
-        greloc(cur_text_section, pe->sym, ind, R_386_32);
-    gen_le32(pe->v);
-}
-
-/* XXX: unify with C code output ? */
-static void gen_disp32(ExprValue *pe)
-{
-    Sym *sym;
-    sym = pe->sym;
-    if (sym) {
-        if (sym->r == cur_text_section->sh_num) {
-            /* same section: we can output an absolute value. Note
-               that the TCC compiler behaves differently here because
-               it always outputs a relocation to ease (future) code
-               elimination in the linker */
-            gen_le32(pe->v + (long)sym->next - ind - 4);
-        } else {
-            greloc(cur_text_section, sym, ind, R_386_PC32);
-            gen_le32(pe->v - 4);
-        }
-    } else {
-        /* put an empty PC32 relocation */
-        put_elf_reloc(symtab_section, cur_text_section, 
-                      ind, R_386_PC32, 0);
-        gen_le32(pe->v - 4);
-    }
-}
-
-
-static void gen_le16(int v)
-{
-    g(v);
-    g(v >> 8);
-}
-
-/* generate the modrm operand */
-static inline void asm_modrm(int reg, Operand *op)
-{
-    int mod, reg1, reg2, sib_reg1;
-
-    if (op->type & (OP_REG | OP_MMX | OP_SSE)) {
-        g(0xc0 + (reg << 3) + op->reg);
-    } else if (op->reg == -1 && op->reg2 == -1) {
-        /* displacement only */
-        g(0x05 + (reg << 3));
-        gen_expr32(&op->e);
-    } else {
-        sib_reg1 = op->reg;
-        /* fist compute displacement encoding */
-        if (sib_reg1 == -1) {
-            sib_reg1 = 5;
-            mod = 0x00;
-        } else if (op->e.v == 0 && !op->e.sym && op->reg != 5) {
-            mod = 0x00;
-        } else if (op->e.v == (int8_t)op->e.v && !op->e.sym) {
-            mod = 0x40;
-        } else {
-            mod = 0x80;
-        }
-        /* compute if sib byte needed */
-        reg1 = op->reg;
-        if (op->reg2 != -1)
-            reg1 = 4;
-        g(mod + (reg << 3) + reg1);
-        if (reg1 == 4) {
-            /* add sib byte */
-            reg2 = op->reg2;
-            if (reg2 == -1)
-                reg2 = 4; /* indicate no index */
-            g((op->shift << 6) + (reg2 << 3) + sib_reg1);
-        }
-
-        /* add offset */
-        if (mod == 0x40) {
-            g(op->e.v);
-        } else if (mod == 0x80 || op->reg == -1) {
-            gen_expr32(&op->e);
-        }
-    }
-}
-
-static void asm_opcode(TCCState *s1, int opcode)
-{
-    const ASMInstr *pa;
-    int i, modrm_index, reg, v, op1, is_short_jmp, seg_prefix;
-    int nb_ops, s, ss;
-    Operand ops[MAX_OPERANDS], *pop;
-    int op_type[3]; /* decoded op type */
-
-    /* get operands */
-    pop = ops;
-    nb_ops = 0;
-    seg_prefix = 0;
-    for(;;) {
-        if (tok == ';' || tok == TOK_LINEFEED)
-            break;
-        if (nb_ops >= MAX_OPERANDS) {
-            error("incorrect number of operands");
-        }
-        parse_operand(s1, pop);
-        if (tok == ':') {
-           if (pop->type != OP_SEG || seg_prefix) {
-               error("incorrect prefix");
-           }
-           seg_prefix = segment_prefixes[pop->reg];
-           next();
-           parse_operand(s1, pop);
-           if (!(pop->type & OP_EA)) {
-               error("segment prefix must be followed by memory reference");
-           }
-        }
-        pop++;
-        nb_ops++;
-        if (tok != ',')
-            break;
-        next();
-    }
-
-    is_short_jmp = 0;
-    s = 0; /* avoid warning */
-    
-    /* optimize matching by using a lookup table (no hashing is needed
-       !) */
-    for(pa = asm_instrs; pa->sym != 0; pa++) {
-        s = 0;
-        if (pa->instr_type & OPC_FARITH) {
-            v = opcode - pa->sym;
-            if (!((unsigned)v < 8 * 6 && (v % 6) == 0))
-                continue;
-        } else if (pa->instr_type & OPC_ARITH) {
-            if (!(opcode >= pa->sym && opcode < pa->sym + 8 * 4))
-                continue;
-            goto compute_size;
-        } else if (pa->instr_type & OPC_SHIFT) {
-            if (!(opcode >= pa->sym && opcode < pa->sym + 7 * 4))
-                continue;
-            goto compute_size;
-        } else if (pa->instr_type & OPC_TEST) {
-            if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
-                continue;
-        } else if (pa->instr_type & OPC_B) {
-            if (!(opcode >= pa->sym && opcode <= pa->sym + 3))
-                continue;
-        compute_size:
-            s = (opcode - pa->sym) & 3;
-        } else if (pa->instr_type & OPC_WL) {
-            if (!(opcode >= pa->sym && opcode <= pa->sym + 2))
-                continue;
-            s = opcode - pa->sym + 1;
-        } else {
-            if (pa->sym != opcode)
-                continue;
-        }
-        if (pa->nb_ops != nb_ops)
-            continue;
-        /* now decode and check each operand */
-        for(i = 0; i < nb_ops; i++) {
-            int op1, op2;
-            op1 = pa->op_type[i];
-            op2 = op1 & 0x1f;
-            switch(op2) {
-            case OPT_IM:
-                v = OP_IM8 | OP_IM16 | OP_IM32;
-                break;
-            case OPT_REG:
-                v = OP_REG8 | OP_REG16 | OP_REG32;
-                break;
-            case OPT_REGW:
-                v = OP_REG16 | OP_REG32;
-                break;
-            case OPT_IMW:
-                v = OP_IM16 | OP_IM32;
-                break;
-            default:
-                v = 1 << op2;
-                break;
-            }
-            if (op1 & OPT_EA)
-                v |= OP_EA;
-            op_type[i] = v;
-            if ((ops[i].type & v) == 0)
-                goto next;
-        }
-        /* all is matching ! */
-        break;
-    next: ;
-    }
-    if (pa->sym == 0) {
-        if (opcode >= TOK_ASM_pusha && opcode <= TOK_ASM_emms) {
-            int b;
-            b = op0_codes[opcode - TOK_ASM_pusha];
-            if (b & 0xff00) 
-                g(b >> 8);
-            g(b);
-            return;
-        } else {
-            error("unknown opcode '%s'", 
-                  get_tok_str(opcode, NULL));
-        }
-    }
-    /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
-    if (s == 3) {
-        for(i = 0; s == 3 && i < nb_ops; i++) {
-            if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
-                s = reg_to_size[ops[i].type & OP_REG];
-        }
-        if (s == 3) {
-            if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) && 
-                (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32)))
-                s = 2;
-            else
-                error("cannot infer opcode suffix");
-        }
-    }
-
-    /* generate data16 prefix if needed */
-    ss = s;
-    if (s == 1 || (pa->instr_type & OPC_D16))
-        g(WORD_PREFIX_OPCODE);
-    else if (s == 2)
-        s = 1;
-    /* now generates the operation */
-    if (pa->instr_type & OPC_FWAIT)
-        g(0x9b);
-    if (seg_prefix)
-        g(seg_prefix);
-
-    v = pa->opcode;
-    if (v == 0x69 || v == 0x69) {
-        /* kludge for imul $im, %reg */
-        nb_ops = 3;
-        ops[2] = ops[1];
-    } else if (v == 0xcd && ops[0].e.v == 3 && !ops[0].e.sym) {
-        v--; /* int $3 case */
-        nb_ops = 0;
-    } else if ((v == 0x06 || v == 0x07)) {
-        if (ops[0].reg >= 4) {
-            /* push/pop %fs or %gs */
-            v = 0x0fa0 + (v - 0x06) + ((ops[0].reg - 4) << 3);
-        } else {
-            v += ops[0].reg << 3;
-        }
-        nb_ops = 0;
-    } else if (v <= 0x05) {
-        /* arith case */
-        v += ((opcode - TOK_ASM_addb) >> 2) << 3;
-    } else if ((pa->instr_type & (OPC_FARITH | OPC_MODRM)) == OPC_FARITH) {
-        /* fpu arith case */
-        v += ((opcode - pa->sym) / 6) << 3;
-    }
-    if (pa->instr_type & OPC_REG) {
-        for(i = 0; i < nb_ops; i++) {
-            if (op_type[i] & (OP_REG | OP_ST)) {
-                v += ops[i].reg;
-                break;
-            }
-        }
-        /* mov $im, %reg case */
-        if (pa->opcode == 0xb0 && s >= 1)
-            v += 7;
-    }
-    if (pa->instr_type & OPC_B)
-        v += s;
-    if (pa->instr_type & OPC_TEST)
-        v += test_bits[opcode - pa->sym]; 
-    if (pa->instr_type & OPC_SHORTJMP) {
-        Sym *sym;
-        int jmp_disp;
-
-        /* see if we can really generate the jump with a byte offset */
-        sym = ops[0].e.sym;
-        if (!sym)
-            goto no_short_jump;
-        if (sym->r != cur_text_section->sh_num)
-            goto no_short_jump;
-        jmp_disp = ops[0].e.v + (long)sym->next - ind - 2;
-        if (jmp_disp == (int8_t)jmp_disp) {
-            /* OK to generate jump */
-            is_short_jmp = 1;
-            ops[0].e.v = jmp_disp;
-        } else {
-        no_short_jump:
-            if (pa->instr_type & OPC_JMP) {
-                /* long jump will be allowed. need to modify the
-                   opcode slightly */
-                if (v == 0xeb)
-                    v = 0xe9;
-                else 
-                    v += 0x0f10;
-            } else {
-                error("invalid displacement");
-            }
-        }
-    }
-    op1 = v >> 8;
-    if (op1)
-        g(op1);
-    g(v);
-        
-    /* search which operand will used for modrm */
-    modrm_index = 0;
-    if (pa->instr_type & OPC_SHIFT) {
-        reg = (opcode - pa->sym) >> 2; 
-        if (reg == 6)
-            reg = 7;
-    } else if (pa->instr_type & OPC_ARITH) {
-        reg = (opcode - pa->sym) >> 2;
-    } else if (pa->instr_type & OPC_FARITH) {
-        reg = (opcode - pa->sym) / 6;
-    } else {
-        reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;
-    }
-    if (pa->instr_type & OPC_MODRM) {
-        /* first look for an ea operand */
-        for(i = 0;i < nb_ops; i++) {
-            if (op_type[i] & OP_EA)
-                goto modrm_found;
-        }
-        /* then if not found, a register or indirection (shift instructions) */
-        for(i = 0;i < nb_ops; i++) {
-            if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR))
-                goto modrm_found;
-        }
-#ifdef ASM_DEBUG
-        error("bad op table");
-#endif      
-    modrm_found:
-        modrm_index = i;
-        /* if a register is used in another operand then it is
-           used instead of group */
-        for(i = 0;i < nb_ops; i++) {
-            v = op_type[i];
-            if (i != modrm_index && 
-                (v & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_TR | OP_DB | OP_SEG))) {
-                reg = ops[i].reg;
-                break;
-            }
-        }
-
-        asm_modrm(reg, &ops[modrm_index]);
-    }
-
-    /* emit constants */
-    if (pa->opcode == 0x9a || pa->opcode == 0xea) {
-        /* ljmp or lcall kludge */
-        gen_expr32(&ops[1].e);
-        if (ops[0].e.sym)
-            error("cannot relocate");
-        gen_le16(ops[0].e.v);
-    } else {
-        for(i = 0;i < nb_ops; i++) {
-            v = op_type[i];
-            if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM8S | OP_ADDR)) {
-                /* if multiple sizes are given it means we must look
-                   at the op size */
-                if (v == (OP_IM8 | OP_IM16 | OP_IM32) ||
-                    v == (OP_IM16 | OP_IM32)) {
-                    if (ss == 0)
-                        v = OP_IM8;
-                    else if (ss == 1)
-                        v = OP_IM16;
-                    else
-                        v = OP_IM32;
-                }
-                if (v & (OP_IM8 | OP_IM8S)) {
-                    if (ops[i].e.sym)
-                        goto error_relocate;
-                    g(ops[i].e.v);
-                } else if (v & OP_IM16) {
-                    if (ops[i].e.sym) {
-                    error_relocate:
-                        error("cannot relocate");
-                    }
-                    gen_le16(ops[i].e.v);
-                } else {
-                    if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
-                        if (is_short_jmp)
-                            g(ops[i].e.v);
-                        else
-                            gen_disp32(&ops[i].e);
-                    } else {
-                        gen_expr32(&ops[i].e);
-                    }
-                }
-            }
-        }
-    }
-}
-
-#define NB_SAVED_REGS 3
-#define NB_ASM_REGS 8
-
-/* return the constraint priority (we allocate first the lowest
-   numbered constraints) */
-static inline int constraint_priority(const char *str)
-{
-    int priority, c, pr;
-
-    /* we take the lowest priority */
-    priority = 0;
-    for(;;) {
-        c = *str;
-        if (c == '\0')
-            break;
-        str++;
-        switch(c) {
-        case 'A':
-            pr = 0;
-            break;
-        case 'a':
-        case 'b':
-        case 'c':
-        case 'd':
-        case 'S':
-        case 'D':
-            pr = 1;
-            break;
-        case 'q':
-            pr = 2;
-            break;
-        case 'r':
-            pr = 3;
-            break;
-        case 'N':
-        case 'M':
-        case 'I':
-        case 'i':
-        case 'm':
-        case 'g':
-            pr = 4;
-            break;
-        default:
-            error("unknown constraint '%c'", c);
-            pr = 0;
-        }
-        if (pr > priority)
-            priority = pr;
-    }
-    return priority;
-}
-
-static const char *skip_constraint_modifiers(const char *p)
-{
-    while (*p == '=' || *p == '&' || *p == '+' || *p == '%')
-        p++;
-    return p;
-}
-
-#define REG_OUT_MASK 0x01
-#define REG_IN_MASK  0x02
-
-#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
-
-static void asm_compute_constraints(ASMOperand *operands, 
-                                    int nb_operands, int nb_outputs, 
-                                    const uint8_t *clobber_regs,
-                                    int *pout_reg)
-{
-    ASMOperand *op;
-    int sorted_op[MAX_ASM_OPERANDS];
-    int i, j, k, p1, p2, tmp, reg, c, reg_mask;
-    const char *str;
-    uint8_t regs_allocated[NB_ASM_REGS];
-    
-    /* init fields */
-    for(i=0;i<nb_operands;i++) {
-        op = &operands[i];
-        op->input_index = -1;
-        op->ref_index = -1;
-        op->reg = -1;
-        op->is_memory = 0;
-        op->is_rw = 0;
-    }
-    /* compute constraint priority and evaluate references to output
-       constraints if input constraints */
-    for(i=0;i<nb_operands;i++) {
-        op = &operands[i];
-        str = op->constraint;
-        str = skip_constraint_modifiers(str);
-        if (isnum(*str) || *str == '[') {
-            /* this is a reference to another constraint */
-            k = find_constraint(operands, nb_operands, str, NULL);
-            if ((unsigned)k >= i || i < nb_outputs)
-                error("invalid reference in constraint %d ('%s')",
-                      i, str);
-            op->ref_index = k;
-            if (operands[k].input_index >= 0)
-                error("cannot reference twice the same operand");
-            operands[k].input_index = i;
-            op->priority = 5;
-        } else {
-            op->priority = constraint_priority(str);
-        }
-    }
-    
-    /* sort operands according to their priority */
-    for(i=0;i<nb_operands;i++)
-        sorted_op[i] = i;
-    for(i=0;i<nb_operands - 1;i++) {
-        for(j=i+1;j<nb_operands;j++) {
-            p1 = operands[sorted_op[i]].priority; 
-            p2 = operands[sorted_op[j]].priority;
-            if (p2 < p1) {
-                tmp = sorted_op[i];
-                sorted_op[i] = sorted_op[j];
-                sorted_op[j] = tmp;
-            }
-        }
-    }
-
-    for(i = 0;i < NB_ASM_REGS; i++) {
-        if (clobber_regs[i])
-            regs_allocated[i] = REG_IN_MASK | REG_OUT_MASK;
-        else
-            regs_allocated[i] = 0;
-    }
-    /* esp cannot be used */
-    regs_allocated[4] = REG_IN_MASK | REG_OUT_MASK; 
-    /* ebp cannot be used yet */
-    regs_allocated[5] = REG_IN_MASK | REG_OUT_MASK; 
-
-    /* allocate registers and generate corresponding asm moves */
-    for(i=0;i<nb_operands;i++) {
-        j = sorted_op[i];
-        op = &operands[j];
-        str = op->constraint;
-        /* no need to allocate references */
-        if (op->ref_index >= 0)
-            continue;
-        /* select if register is used for output, input or both */
-        if (op->input_index >= 0) {
-            reg_mask = REG_IN_MASK | REG_OUT_MASK;
-        } else if (j < nb_outputs) {
-            reg_mask = REG_OUT_MASK;
-        } else {
-            reg_mask = REG_IN_MASK;
-        }
-    try_next:
-        c = *str++;
-        switch(c) {
-        case '=':
-            goto try_next;
-        case '+':
-            op->is_rw = 1;
-            /* FALL THRU */
-        case '&':
-            if (j >= nb_outputs)
-                error("'%c' modifier can only be applied to outputs", c);
-            reg_mask = REG_IN_MASK | REG_OUT_MASK;
-            goto try_next;
-        case 'A':
-            /* allocate both eax and edx */
-            if (is_reg_allocated(TREG_EAX) || 
-                is_reg_allocated(TREG_EDX))
-                goto try_next;
-            op->is_llong = 1;
-            op->reg = TREG_EAX;
-            regs_allocated[TREG_EAX] |= reg_mask;
-            regs_allocated[TREG_EDX] |= reg_mask;
-            break;
-        case 'a':
-            reg = TREG_EAX;
-            goto alloc_reg;
-        case 'b':
-            reg = 3;
-            goto alloc_reg;
-        case 'c':
-            reg = TREG_ECX;
-            goto alloc_reg;
-        case 'd':
-            reg = TREG_EDX;
-            goto alloc_reg;
-        case 'S':
-            reg = 6;
-            goto alloc_reg;
-        case 'D':
-            reg = 7;
-        alloc_reg:
-            if (is_reg_allocated(reg))
-                goto try_next;
-            goto reg_found;
-        case 'q':
-            /* eax, ebx, ecx or edx */
-            for(reg = 0; reg < 4; reg++) {
-                if (!is_reg_allocated(reg))
-                    goto reg_found;
-            }
-            goto try_next;
-        case 'r':
-            /* any general register */
-            for(reg = 0; reg < 8; reg++) {
-                if (!is_reg_allocated(reg))
-                    goto reg_found;
-            }
-            goto try_next;
-        reg_found:
-            /* now we can reload in the register */
-            op->is_llong = 0;
-            op->reg = reg;
-            regs_allocated[reg] |= reg_mask;
-            break;
-        case 'i':
-            if (!((op->vt->r & (VT_VALMASK | VT_LVAL)) == VT_CONST))
-                goto try_next;
-            break;
-        case 'I':
-        case 'N':
-        case 'M':
-            if (!((op->vt->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST))
-                goto try_next;
-            break;
-        case 'm':
-        case 'g':
-            /* nothing special to do because the operand is already in
-               memory, except if the pointer itself is stored in a
-               memory variable (VT_LLOCAL case) */
-            /* XXX: fix constant case */
-            /* if it is a reference to a memory zone, it must lie
-               in a register, so we reserve the register in the
-               input registers and a load will be generated
-               later */
-            if (j < nb_outputs || c == 'm') {
-                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
-                    /* any general register */
-                    for(reg = 0; reg < 8; reg++) {
-                        if (!(regs_allocated[reg] & REG_IN_MASK))
-                            goto reg_found1;
-                    }
-                    goto try_next;
-                reg_found1:
-                    /* now we can reload in the register */
-                    regs_allocated[reg] |= REG_IN_MASK;
-                    op->reg = reg;
-                    op->is_memory = 1;
-                }
-            }
-            break;
-        default:
-            error("asm constraint %d ('%s') could not be satisfied", 
-                  j, op->constraint);
-            break;
-        }
-        /* if a reference is present for that operand, we assign it too */
-        if (op->input_index >= 0) {
-            operands[op->input_index].reg = op->reg;
-            operands[op->input_index].is_llong = op->is_llong;
-        }
-    }
-    
-    /* compute out_reg. It is used to store outputs registers to memory
-       locations references by pointers (VT_LLOCAL case) */
-    *pout_reg = -1;
-    for(i=0;i<nb_operands;i++) {
-        op = &operands[i];
-        if (op->reg >= 0 && 
-            (op->vt->r & VT_VALMASK) == VT_LLOCAL  &&
-            !op->is_memory) {
-            for(reg = 0; reg < 8; reg++) {
-                if (!(regs_allocated[reg] & REG_OUT_MASK))
-                    goto reg_found2;
-            }
-            error("could not find free output register for reloading");
-        reg_found2:
-            *pout_reg = reg;
-            break;
-        }
-    }
-    
-    /* print sorted constraints */
-#ifdef ASM_DEBUG
-    for(i=0;i<nb_operands;i++) {
-        j = sorted_op[i];
-        op = &operands[j];
-        printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n", 
-               j,                
-               op->id ? get_tok_str(op->id, NULL) : "", 
-               op->constraint,
-               op->vt->r,
-               op->reg);
-    }
-    if (*pout_reg >= 0)
-        printf("out_reg=%d\n", *pout_reg);
-#endif
-}
-
-static void subst_asm_operand(CString *add_str, 
-                              SValue *sv, int modifier)
-{
-    int r, reg, size, val;
-    char buf[64];
-
-    r = sv->r;
-    if ((r & VT_VALMASK) == VT_CONST) {
-        if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n')
-            cstr_ccat(add_str, '$');
-        if (r & VT_SYM) {
-            cstr_cat(add_str, get_tok_str(sv->sym->v, NULL));
-            if (sv->c.i != 0) {
-                cstr_ccat(add_str, '+');
-            } else {
-                return;
-            }
-        }
-        val = sv->c.i;
-        if (modifier == 'n')
-            val = -val;
-        snprintf(buf, sizeof(buf), "%d", sv->c.i);
-        cstr_cat(add_str, buf);
-    } else if ((r & VT_VALMASK) == VT_LOCAL) {
-        snprintf(buf, sizeof(buf), "%d(%%ebp)", sv->c.i);
-        cstr_cat(add_str, buf);
-    } else if (r & VT_LVAL) {
-        reg = r & VT_VALMASK;
-        if (reg >= VT_CONST)
-            error("internal compiler error");
-        snprintf(buf, sizeof(buf), "(%%%s)", 
-                 get_tok_str(TOK_ASM_eax + reg, NULL));
-        cstr_cat(add_str, buf);
-    } else {
-        /* register case */
-        reg = r & VT_VALMASK;
-        if (reg >= VT_CONST)
-            error("internal compiler error");
-
-        /* choose register operand size */
-        if ((sv->type.t & VT_BTYPE) == VT_BYTE)
-            size = 1;
-        else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
-            size = 2;
-        else
-            size = 4;
-        if (size == 1 && reg >= 4)
-            size = 4;
-
-        if (modifier == 'b') {
-            if (reg >= 4)
-                error("cannot use byte register");
-            size = 1;
-        } else if (modifier == 'h') {
-            if (reg >= 4)
-                error("cannot use byte register");
-            size = -1;
-        } else if (modifier == 'w') {
-            size = 2;
-        }
-
-        switch(size) {
-        case -1:
-            reg = TOK_ASM_ah + reg;
-            break;
-        case 1:
-            reg = TOK_ASM_al + reg;
-            break;
-        case 2:
-            reg = TOK_ASM_ax + reg;
-            break;
-        default:
-            reg = TOK_ASM_eax + reg;
-            break;
-        }
-        snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
-        cstr_cat(add_str, buf);
-    }
-}
-
-/* generate prolog and epilog code for asm statment */
-static void asm_gen_code(ASMOperand *operands, int nb_operands, 
-                         int nb_outputs, int is_output,
-                         uint8_t *clobber_regs,
-                         int out_reg)
-{
-    uint8_t regs_allocated[NB_ASM_REGS];
-    ASMOperand *op;
-    int i, reg;
-    static uint8_t reg_saved[NB_SAVED_REGS] = { 3, 6, 7 };
-
-    /* mark all used registers */
-    memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));
-    for(i = 0; i < nb_operands;i++) {
-        op = &operands[i];
-        if (op->reg >= 0)
-            regs_allocated[op->reg] = 1;
-    }
-    if (!is_output) {
-        /* generate reg save code */
-        for(i = 0; i < NB_SAVED_REGS; i++) {
-            reg = reg_saved[i];
-            if (regs_allocated[reg]) 
-                g(0x50 + reg);
-        }
-
-        /* generate load code */
-        for(i = 0; i < nb_operands; i++) {
-            op = &operands[i];
-            if (op->reg >= 0) {
-                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL &&
-                    op->is_memory) {
-                    /* memory reference case (for both input and
-                       output cases) */
-                    SValue sv;
-                    sv = *op->vt;
-                    sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
-                    load(op->reg, &sv);
-                } else if (i >= nb_outputs || op->is_rw) {
-                    /* load value in register */
-                    load(op->reg, op->vt);
-                    if (op->is_llong) {
-                        SValue sv;
-                        sv = *op->vt;
-                        sv.c.ul += 4;
-                        load(TREG_EDX, &sv);
-                    }
-                }
-            }
-        }
-    } else {
-        /* generate save code */
-        for(i = 0 ; i < nb_outputs; i++) {
-            op = &operands[i];
-            if (op->reg >= 0) {
-                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
-                    if (!op->is_memory) {
-                        SValue sv;
-                        sv = *op->vt;
-                        sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
-                        load(out_reg, &sv);
-
-                        sv.r = (sv.r & ~VT_VALMASK) | out_reg;
-                        store(op->reg, &sv);
-                    }
-                } else {
-                    store(op->reg, op->vt);
-                    if (op->is_llong) {
-                        SValue sv;
-                        sv = *op->vt;
-                        sv.c.ul += 4;
-                        store(TREG_EDX, &sv);
-                    }
-                }
-            }
-        }
-        /* generate reg restore code */
-        for(i = NB_SAVED_REGS - 1; i >= 0; i--) {
-            reg = reg_saved[i];
-            if (regs_allocated[reg]) 
-                g(0x58 + reg);
-        }
-    }
-}
-
-static void asm_clobber(uint8_t *clobber_regs, const char *str)
-{
-    int reg;
-    TokenSym *ts;
-
-    if (!strcmp(str, "memory") || 
-        !strcmp(str, "cc"))
-        return;
-    ts = tok_alloc(str, strlen(str));
-    reg = ts->tok;
-    if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
-        reg -= TOK_ASM_eax;
-    } else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
-        reg -= TOK_ASM_ax;
-    } else {
-        error("invalid clobber register '%s'", str);
-    }
-    clobber_regs[reg] = 1;
-}

+ 0 - 446
src/modules/native/tcc/libtcc/i386-asm.h

@@ -1,446 +0,0 @@
-     DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
-     DEF_ASM_OP0(popa, 0x61)
-     DEF_ASM_OP0(clc, 0xf8)
-     DEF_ASM_OP0(cld, 0xfc)
-     DEF_ASM_OP0(cli, 0xfa)
-     DEF_ASM_OP0(clts, 0x0f06)
-     DEF_ASM_OP0(cmc, 0xf5)
-     DEF_ASM_OP0(lahf, 0x9f)
-     DEF_ASM_OP0(sahf, 0x9e)
-     DEF_ASM_OP0(pushfl, 0x9c)
-     DEF_ASM_OP0(popfl, 0x9d)
-     DEF_ASM_OP0(pushf, 0x9c)
-     DEF_ASM_OP0(popf, 0x9d)
-     DEF_ASM_OP0(stc, 0xf9)
-     DEF_ASM_OP0(std, 0xfd)
-     DEF_ASM_OP0(sti, 0xfb)
-     DEF_ASM_OP0(aaa, 0x37)
-     DEF_ASM_OP0(aas, 0x3f)
-     DEF_ASM_OP0(daa, 0x27)
-     DEF_ASM_OP0(das, 0x2f)
-     DEF_ASM_OP0(aad, 0xd50a)
-     DEF_ASM_OP0(aam, 0xd40a)
-     DEF_ASM_OP0(cbw, 0x6698)
-     DEF_ASM_OP0(cwd, 0x6699)
-     DEF_ASM_OP0(cwde, 0x98)
-     DEF_ASM_OP0(cdq, 0x99)
-     DEF_ASM_OP0(cbtw, 0x6698)
-     DEF_ASM_OP0(cwtl, 0x98)
-     DEF_ASM_OP0(cwtd, 0x6699)
-     DEF_ASM_OP0(cltd, 0x99)
-     DEF_ASM_OP0(int3, 0xcc)
-     DEF_ASM_OP0(into, 0xce)
-     DEF_ASM_OP0(iret, 0xcf)
-     DEF_ASM_OP0(rsm, 0x0faa)
-     DEF_ASM_OP0(hlt, 0xf4)
-     DEF_ASM_OP0(wait, 0x9b)
-     DEF_ASM_OP0(nop, 0x90)
-     DEF_ASM_OP0(xlat, 0xd7)
-
-     /* strings */
-ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
-ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
-
-ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
-ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
-
-ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
-ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
-
-ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
-ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
-
-ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
-ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
-
-ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
-ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
-
-     /* bits */
-     
-ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
-
-ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
-
-ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
-
-ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
-
-ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
-
-     /* prefixes */
-     DEF_ASM_OP0(aword, 0x67)
-     DEF_ASM_OP0(addr16, 0x67)
-     DEF_ASM_OP0(word, 0x66)
-     DEF_ASM_OP0(data16, 0x66)
-     DEF_ASM_OP0(lock, 0xf0)
-     DEF_ASM_OP0(rep, 0xf3)
-     DEF_ASM_OP0(repe, 0xf3)
-     DEF_ASM_OP0(repz, 0xf3)
-     DEF_ASM_OP0(repne, 0xf2)
-     DEF_ASM_OP0(repnz, 0xf2)
-             
-     DEF_ASM_OP0(invd, 0x0f08)
-     DEF_ASM_OP0(wbinvd, 0x0f09)
-     DEF_ASM_OP0(cpuid, 0x0fa2)
-     DEF_ASM_OP0(wrmsr, 0x0f30)
-     DEF_ASM_OP0(rdtsc, 0x0f31)
-     DEF_ASM_OP0(rdmsr, 0x0f32)
-     DEF_ASM_OP0(rdpmc, 0x0f33)
-     DEF_ASM_OP0(ud2, 0x0f0b)
-
-     /* NOTE: we took the same order as gas opcode definition order */
-ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
-ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
-ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
-ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
-ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
-
-ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
-ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
-ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
-ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
-ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
-ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
-
-ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
-ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
-
-ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
-ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
-ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
-ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
-
-ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
-ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
-
-ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
-ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
-ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
-
-ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
-ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
-ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
-ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
-
-ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
-ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
-ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
-ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
-
-ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
-
-ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-
-     /* arith */
-ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
-ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
-ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
-ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
-
-ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
-ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
-ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
-
-ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
-ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
-ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
-ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
-ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
-
-ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
-ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
-
-     /* shifts */
-ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
-
-ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
-
-ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
-ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
-ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
-ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
-
-ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
-ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
-ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
-ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
-
-ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
-ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
-    DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
-    DEF_ASM_OP0(leave, 0xc9)
-    DEF_ASM_OP0(ret, 0xc3)
-ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
-    DEF_ASM_OP0(lret, 0xcb)
-ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
-
-ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
-    DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
-    DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
-    DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
-    DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
-    DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
-    DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
-     
-     /* float */
-     /* specific fcomp handling */
-ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
-
-ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
-ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
-ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
-ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
-ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
-ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
-ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
-ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-
-     DEF_ASM_OP0(fucompp, 0xdae9)
-     DEF_ASM_OP0(ftst, 0xd9e4)
-     DEF_ASM_OP0(fxam, 0xd9e5)
-     DEF_ASM_OP0(fld1, 0xd9e8)
-     DEF_ASM_OP0(fldl2t, 0xd9e9)
-     DEF_ASM_OP0(fldl2e, 0xd9ea)
-     DEF_ASM_OP0(fldpi, 0xd9eb)
-     DEF_ASM_OP0(fldlg2, 0xd9ec)
-     DEF_ASM_OP0(fldln2, 0xd9ed)
-     DEF_ASM_OP0(fldz, 0xd9ee)
-
-     DEF_ASM_OP0(f2xm1, 0xd9f0)
-     DEF_ASM_OP0(fyl2x, 0xd9f1)
-     DEF_ASM_OP0(fptan, 0xd9f2)
-     DEF_ASM_OP0(fpatan, 0xd9f3)
-     DEF_ASM_OP0(fxtract, 0xd9f4)
-     DEF_ASM_OP0(fprem1, 0xd9f5)
-     DEF_ASM_OP0(fdecstp, 0xd9f6)
-     DEF_ASM_OP0(fincstp, 0xd9f7)
-     DEF_ASM_OP0(fprem, 0xd9f8)
-     DEF_ASM_OP0(fyl2xp1, 0xd9f9)
-     DEF_ASM_OP0(fsqrt, 0xd9fa)
-     DEF_ASM_OP0(fsincos, 0xd9fb)
-     DEF_ASM_OP0(frndint, 0xd9fc)
-     DEF_ASM_OP0(fscale, 0xd9fd)
-     DEF_ASM_OP0(fsin, 0xd9fe)
-     DEF_ASM_OP0(fcos, 0xd9ff)
-     DEF_ASM_OP0(fchs, 0xd9e0)
-     DEF_ASM_OP0(fabs, 0xd9e1)
-     DEF_ASM_OP0(fninit, 0xdbe3)
-     DEF_ASM_OP0(fnclex, 0xdbe2)
-     DEF_ASM_OP0(fnop, 0xd9d0)
-     DEF_ASM_OP0(fwait, 0x9b)
-
-    /* fp load */
-    DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
-    DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
-    DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
-ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
-    DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
-    DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
-    
-    /* fp store */
-    DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
-    DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
-    DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
-ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
-    DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
-
-    DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
-    DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
-
-    /* exchange */
-    DEF_ASM_OP0(fxch, 0xd9c9)
-ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
-
-    /* misc FPU */
-    DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
-    DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
-
-    DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
-    DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
-    DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
-    DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
-    DEF_ASM_OP0(fnstsw, 0xdfe0)
-ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
-ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
-    DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
-ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
-ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
-    DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
-    DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
-    DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
-    DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
-    DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
-    DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
-    DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
-    DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
-    DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
-    DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
-    DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
-
-    /* segments */
-    DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
-    DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
-    DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
-    DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
-ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
-    DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
-    DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
-    DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
-    DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
-    DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
-    DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
-    DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
-
-    /* 486 */
-    DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
-ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
-ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
-    DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
-
-    DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
-    DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
-
-    /* pentium */
-    DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
-    
-    /* pentium pro */
-    ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
-
-    DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
-    DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
-    DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
-    DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
-    DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
-    DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
-    DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
-    DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
-
-    DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
-    DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
-    DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
-    DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
-
-    /* mmx */
-    DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
-    DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
-ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
-    DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
-    DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
-    DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
-    DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
-    DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
-    DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
-    DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
-    DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
-    DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
-    DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-    DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-
-#undef ALT
-#undef DEF_ASM_OP0
-#undef DEF_ASM_OP0L
-#undef DEF_ASM_OP1
-#undef DEF_ASM_OP2
-#undef DEF_ASM_OP3

+ 0 - 1034
src/modules/native/tcc/libtcc/i386-gen.c

@@ -1,1034 +0,0 @@
-/*
- *  X86 code generator for TCC
- * 
- *  Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* number of available registers */
-#define NB_REGS             4
-
-/* a register can belong to several classes. The classes must be
-   sorted from more general to more precise (see gv2() code which does
-   assumptions on it). */
-#define RC_INT     0x0001 /* generic integer register */
-#define RC_FLOAT   0x0002 /* generic float register */
-#define RC_EAX     0x0004
-#define RC_ST0     0x0008 
-#define RC_ECX     0x0010
-#define RC_EDX     0x0020
-#define RC_IRET    RC_EAX /* function return: integer register */
-#define RC_LRET    RC_EDX /* function return: second integer register */
-#define RC_FRET    RC_ST0 /* function return: float register */
-
-/* pretty names for the registers */
-enum {
-    TREG_EAX = 0,
-    TREG_ECX,
-    TREG_EDX,
-    TREG_ST0,
-};
-
-int reg_classes[NB_REGS] = {
-    /* eax */ RC_INT | RC_EAX,
-    /* ecx */ RC_INT | RC_ECX,
-    /* edx */ RC_INT | RC_EDX,
-    /* st0 */ RC_FLOAT | RC_ST0,
-};
-
-/* return registers for function */
-#define REG_IRET TREG_EAX /* single word int return register */
-#define REG_LRET TREG_EDX /* second word return register (for long long) */
-#define REG_FRET TREG_ST0 /* float return register */
-
-/* defined if function parameters must be evaluated in reverse order */
-#define INVERT_FUNC_PARAMS
-
-/* defined if structures are passed as pointers. Otherwise structures
-   are directly pushed on stack. */
-//#define FUNC_STRUCT_PARAM_AS_PTR
-
-/* pointer size, in bytes */
-#define PTR_SIZE 4
-
-/* long double size and alignment, in bytes */
-#define LDOUBLE_SIZE  12
-#define LDOUBLE_ALIGN 4
-/* maximum alignment (for aligned attribute support) */
-#define MAX_ALIGN     8
-
-/******************************************************/
-/* ELF defines */
-
-#define EM_TCC_TARGET EM_386
-
-/* relocation type for 32 bit data relocation */
-#define R_DATA_32   R_386_32
-#define R_JMP_SLOT  R_386_JMP_SLOT
-#define R_COPY      R_386_COPY
-
-#define ELF_START_ADDR 0x08048000
-#define ELF_PAGE_SIZE  0x1000
-
-/******************************************************/
-
-static unsigned long func_sub_sp_offset;
-static unsigned long func_bound_offset;
-static int func_ret_sub;
-
-/* XXX: make it faster ? */
-void g(int c)
-{
-    int ind1;
-    ind1 = ind + 1;
-    if (ind1 > cur_text_section->data_allocated)
-        section_realloc(cur_text_section, ind1);
-    cur_text_section->data[ind] = c;
-    ind = ind1;
-}
-
-void o(unsigned int c)
-{
-    while (c) {
-        g(c);
-        c = c >> 8;
-    }
-}
-
-void gen_le32(int c)
-{
-    g(c);
-    g(c >> 8);
-    g(c >> 16);
-    g(c >> 24);
-}
-
-/* output a symbol and patch all calls to it */
-void gsym_addr(int t, int a)
-{
-    int n, *ptr;
-    while (t) {
-        ptr = (int *)(cur_text_section->data + t);
-        n = *ptr; /* next value */
-        *ptr = a - t - 4;
-        t = n;
-    }
-}
-
-void gsym(int t)
-{
-    gsym_addr(t, ind);
-}
-
-/* psym is used to put an instruction with a data field which is a
-   reference to a symbol. It is in fact the same as oad ! */
-#define psym oad
-
-/* instruction + 4 bytes data. Return the address of the data */
-static int oad(int c, int s)
-{
-    int ind1;
-
-    o(c);
-    ind1 = ind + 4;
-    if (ind1 > cur_text_section->data_allocated)
-        section_realloc(cur_text_section, ind1);
-    *(int *)(cur_text_section->data + ind) = s;
-    s = ind;
-    ind = ind1;
-    return s;
-}
-
-/* output constant with relocation if 'r & VT_SYM' is true */
-static void gen_addr32(int r, Sym *sym, int c)
-{
-    if (r & VT_SYM)
-        greloc(cur_text_section, sym, ind, R_386_32);
-    gen_le32(c);
-}
-
-/* generate a modrm reference. 'op_reg' contains the addtionnal 3
-   opcode bits */
-static void gen_modrm(int op_reg, int r, Sym *sym, int c)
-{
-    op_reg = op_reg << 3;
-    if ((r & VT_VALMASK) == VT_CONST) {
-        /* constant memory reference */
-        o(0x05 | op_reg);
-        gen_addr32(r, sym, c);
-    } else if ((r & VT_VALMASK) == VT_LOCAL) {
-        /* currently, we use only ebp as base */
-        if (c == (char)c) {
-            /* short reference */
-            o(0x45 | op_reg);
-            g(c);
-        } else {
-            oad(0x85 | op_reg, c);
-        }
-    } else {
-        g(0x00 | op_reg | (r & VT_VALMASK));
-    }
-}
-
-
-/* load 'r' from value 'sv' */
-void load(int r, SValue *sv)
-{
-    int v, t, ft, fc, fr;
-    SValue v1;
-
-    fr = sv->r;
-    ft = sv->type.t;
-    fc = sv->c.ul;
-
-    v = fr & VT_VALMASK;
-    if (fr & VT_LVAL) {
-        if (v == VT_LLOCAL) {
-            v1.type.t = VT_INT;
-            v1.r = VT_LOCAL | VT_LVAL;
-            v1.c.ul = fc;
-            load(r, &v1);
-            fr = r;
-        }
-        if ((ft & VT_BTYPE) == VT_FLOAT) {
-            o(0xd9); /* flds */
-            r = 0;
-        } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
-            o(0xdd); /* fldl */
-            r = 0;
-        } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
-            o(0xdb); /* fldt */
-            r = 5;
-        } else if ((ft & VT_TYPE) == VT_BYTE) {
-            o(0xbe0f);   /* movsbl */
-        } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
-            o(0xb60f);   /* movzbl */
-        } else if ((ft & VT_TYPE) == VT_SHORT) {
-            o(0xbf0f);   /* movswl */
-        } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
-            o(0xb70f);   /* movzwl */
-        } else {
-            o(0x8b);     /* movl */
-        }
-        gen_modrm(r, fr, sv->sym, fc);
-    } else {
-        if (v == VT_CONST) {
-            o(0xb8 + r); /* mov $xx, r */
-            gen_addr32(fr, sv->sym, fc);
-        } else if (v == VT_LOCAL) {
-            o(0x8d); /* lea xxx(%ebp), r */
-            gen_modrm(r, VT_LOCAL, sv->sym, fc);
-        } else if (v == VT_CMP) {
-            oad(0xb8 + r, 0); /* mov $0, r */
-            o(0x0f); /* setxx %br */
-            o(fc);
-            o(0xc0 + r);
-        } else if (v == VT_JMP || v == VT_JMPI) {
-            t = v & 1;
-            oad(0xb8 + r, t); /* mov $1, r */
-            o(0x05eb); /* jmp after */
-            gsym(fc);
-            oad(0xb8 + r, t ^ 1); /* mov $0, r */
-        } else if (v != r) {
-            o(0x89);
-            o(0xc0 + r + v * 8); /* mov v, r */
-        }
-    }
-}
-
-/* store register 'r' in lvalue 'v' */
-void store(int r, SValue *v)
-{
-    int fr, bt, ft, fc;
-
-    ft = v->type.t;
-    fc = v->c.ul;
-    fr = v->r & VT_VALMASK;
-    bt = ft & VT_BTYPE;
-    /* XXX: incorrect if float reg to reg */
-    if (bt == VT_FLOAT) {
-        o(0xd9); /* fsts */
-        r = 2;
-    } else if (bt == VT_DOUBLE) {
-        o(0xdd); /* fstpl */
-        r = 2;
-    } else if (bt == VT_LDOUBLE) {
-        o(0xc0d9); /* fld %st(0) */
-        o(0xdb); /* fstpt */
-        r = 7;
-    } else {
-        if (bt == VT_SHORT)
-            o(0x66);
-        if (bt == VT_BYTE || bt == VT_BOOL)
-            o(0x88);
-        else
-            o(0x89);
-    }
-    if (fr == VT_CONST ||
-        fr == VT_LOCAL ||
-        (v->r & VT_LVAL)) {
-        gen_modrm(r, v->r, v->sym, fc);
-    } else if (fr != r) {
-        o(0xc0 + fr + r * 8); /* mov r, fr */
-    }
-}
-
-static void gadd_sp(int val)
-{
-    if (val == (char)val) {
-        o(0xc483);
-        g(val);
-    } else {
-        oad(0xc481, val); /* add $xxx, %esp */
-    }
-}
-
-/* 'is_jmp' is '1' if it is a jump */
-static void gcall_or_jmp(int is_jmp)
-{
-    int r;
-    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
-        /* constant case */
-        if (vtop->r & VT_SYM) {
-            /* relocation case */
-            greloc(cur_text_section, vtop->sym, 
-                   ind + 1, R_386_PC32);
-        } else {
-            /* put an empty PC32 relocation */
-            put_elf_reloc(symtab_section, cur_text_section, 
-                          ind + 1, R_386_PC32, 0);
-        }
-        oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */
-    } else {
-        /* otherwise, indirect call */
-        r = gv(RC_INT);
-        o(0xff); /* call/jmp *r */
-        o(0xd0 + r + (is_jmp << 4));
-    }
-}
-
-static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX };
-static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX };
-
-/* Generate function call. The function address is pushed first, then
-   all the parameters in call order. This functions pops all the
-   parameters and the function address. */
-void gfunc_call(int nb_args)
-{
-    int size, align, r, args_size, i, func_call;
-    Sym *func_sym;
-    
-    args_size = 0;
-    for(i = 0;i < nb_args; i++) {
-        if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
-            size = type_size(&vtop->type, &align);
-            /* align to stack align size */
-            size = (size + 3) & ~3;
-            /* allocate the necessary size on stack */
-            oad(0xec81, size); /* sub $xxx, %esp */
-            /* generate structure store */
-            r = get_reg(RC_INT);
-            o(0x89); /* mov %esp, r */
-            o(0xe0 + r);
-            vset(&vtop->type, r | VT_LVAL, 0);
-            vswap();
-            vstore();
-            args_size += size;
-        } else if (is_float(vtop->type.t)) {
-            gv(RC_FLOAT); /* only one float register */
-            if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
-                size = 4;
-            else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
-                size = 8;
-            else
-                size = 12;
-            oad(0xec81, size); /* sub $xxx, %esp */
-            if (size == 12)
-                o(0x7cdb);
-            else
-                o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */
-            g(0x24);
-            g(0x00);
-            args_size += size;
-        } else {
-            /* simple type (currently always same size) */
-            /* XXX: implicit cast ? */
-            r = gv(RC_INT);
-            if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
-                size = 8;
-                o(0x50 + vtop->r2); /* push r */
-            } else {
-                size = 4;
-            }
-            o(0x50 + r); /* push r */
-            args_size += size;
-        }
-        vtop--;
-    }
-    save_regs(0); /* save used temporary registers */
-    func_sym = vtop->type.ref;
-    func_call = FUNC_CALL(func_sym->r);
-    /* fast call case */
-    if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) ||
-        func_call == FUNC_FASTCALLW) {
-        int fastcall_nb_regs;
-        uint8_t *fastcall_regs_ptr;
-        if (func_call == FUNC_FASTCALLW) {
-            fastcall_regs_ptr = fastcallw_regs;
-            fastcall_nb_regs = 2;
-        } else {
-            fastcall_regs_ptr = fastcall_regs;
-            fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
-        }
-        for(i = 0;i < fastcall_nb_regs; i++) {
-            if (args_size <= 0)
-                break;
-            o(0x58 + fastcall_regs_ptr[i]); /* pop r */
-            /* XXX: incorrect for struct/floats */
-            args_size -= 4;
-        }
-    }
-    gcall_or_jmp(0);
-    if (args_size && func_call != FUNC_STDCALL)
-        gadd_sp(args_size);
-    vtop--;
-}
-
-#ifdef TCC_TARGET_PE
-#define FUNC_PROLOG_SIZE 10
-#else
-#define FUNC_PROLOG_SIZE 9
-#endif
-
-/* generate function prolog of type 't' */
-void gfunc_prolog(CType *func_type)
-{
-    int addr, align, size, func_call, fastcall_nb_regs;
-    int param_index, param_addr;
-    uint8_t *fastcall_regs_ptr;
-    Sym *sym;
-    CType *type;
-
-    sym = func_type->ref;
-    func_call = FUNC_CALL(sym->r);
-    addr = 8;
-    loc = 0;
-    if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
-        fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
-        fastcall_regs_ptr = fastcall_regs;
-    } else if (func_call == FUNC_FASTCALLW) {
-        fastcall_nb_regs = 2;
-        fastcall_regs_ptr = fastcallw_regs;
-    } else {
-        fastcall_nb_regs = 0;
-        fastcall_regs_ptr = NULL;
-    }
-    param_index = 0;
-
-    ind += FUNC_PROLOG_SIZE;
-    func_sub_sp_offset = ind;
-    /* if the function returns a structure, then add an
-       implicit pointer parameter */
-    func_vt = sym->type;
-    if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
-        /* XXX: fastcall case ? */
-        func_vc = addr;
-        addr += 4;
-        param_index++;
-    }
-    /* define parameters */
-    while ((sym = sym->next) != NULL) {
-        type = &sym->type;
-        size = type_size(type, &align);
-        size = (size + 3) & ~3;
-#ifdef FUNC_STRUCT_PARAM_AS_PTR
-        /* structs are passed as pointer */
-        if ((type->t & VT_BTYPE) == VT_STRUCT) {
-            size = 4;
-        }
-#endif
-        if (param_index < fastcall_nb_regs) {
-            /* save FASTCALL register */
-            loc -= 4;
-            o(0x89);     /* movl */
-            gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc);
-            param_addr = loc;
-        } else {
-            param_addr = addr;
-            addr += size;
-        }
-        sym_push(sym->v & ~SYM_FIELD, type,
-                 VT_LOCAL | lvalue_type(type->t), param_addr);
-        param_index++;
-    }
-    func_ret_sub = 0;
-    /* pascal type call ? */
-    if (func_call == FUNC_STDCALL)
-        func_ret_sub = addr - 8;
-
-    /* leave some room for bound checking code */
-    if (tcc_state->do_bounds_check) {
-        oad(0xb8, 0); /* lbound section pointer */
-        oad(0xb8, 0); /* call to function */
-        func_bound_offset = lbounds_section->data_offset;
-    }
-}
-
-/* generate function epilog */
-void gfunc_epilog(void)
-{
-    int v, saved_ind;
-
-#ifdef CONFIG_TCC_BCHECK
-    if (tcc_state->do_bounds_check
-     && func_bound_offset != lbounds_section->data_offset) {
-        int saved_ind;
-        int *bounds_ptr;
-        Sym *sym, *sym_data;
-        /* add end of table info */
-        bounds_ptr = section_ptr_add(lbounds_section, sizeof(int));
-        *bounds_ptr = 0;
-        /* generate bound local allocation */
-        saved_ind = ind;
-        ind = func_sub_sp_offset;
-        sym_data = get_sym_ref(&char_pointer_type, lbounds_section, 
-                               func_bound_offset, lbounds_section->data_offset);
-        greloc(cur_text_section, sym_data,
-               ind + 1, R_386_32);
-        oad(0xb8, 0); /* mov %eax, xxx */
-        sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0);
-        greloc(cur_text_section, sym, 
-               ind + 1, R_386_PC32);
-        oad(0xe8, -4);
-        ind = saved_ind;
-        /* generate bound check local freeing */
-        o(0x5250); /* save returned value, if any */
-        greloc(cur_text_section, sym_data,
-               ind + 1, R_386_32);
-        oad(0xb8, 0); /* mov %eax, xxx */
-        sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0);
-        greloc(cur_text_section, sym, 
-               ind + 1, R_386_PC32);
-        oad(0xe8, -4);
-        o(0x585a); /* restore returned value, if any */
-    }
-#endif
-    o(0xc9); /* leave */
-    if (func_ret_sub == 0) {
-        o(0xc3); /* ret */
-    } else {
-        o(0xc2); /* ret n */
-        g(func_ret_sub);
-        g(func_ret_sub >> 8);
-    }
-    /* align local size to word & save local variables */
-    
-    v = (-loc + 3) & -4; 
-    saved_ind = ind;
-    ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
-#ifdef TCC_TARGET_PE
-    if (v >= 4096) {
-        Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
-        oad(0xb8, v); /* mov stacksize, %eax */
-        oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
-        greloc(cur_text_section, sym, ind-4, R_386_PC32);
-    } else
-#endif
-    {
-        o(0xe58955);  /* push %ebp, mov %esp, %ebp */
-        o(0xec81);  /* sub esp, stacksize */
-        gen_le32(v);
-#if FUNC_PROLOG_SIZE == 10
-        o(0x90);  /* adjust to FUNC_PROLOG_SIZE */
-#endif
-    }
-    ind = saved_ind;
-}
-
-/* generate a jump to a label */
-int gjmp(int t)
-{
-    return psym(0xe9, t);
-}
-
-/* generate a jump to a fixed address */
-void gjmp_addr(int a)
-{
-    int r;
-    r = a - ind - 2;
-    if (r == (char)r) {
-        g(0xeb);
-        g(r);
-    } else {
-        oad(0xe9, a - ind - 5);
-    }
-}
-
-/* generate a test. set 'inv' to invert test. Stack entry is popped */
-int gtst(int inv, int t)
-{
-    int v, *p;
-
-    v = vtop->r & VT_VALMASK;
-    if (v == VT_CMP) {
-        /* fast case : can jump directly since flags are set */
-        g(0x0f);
-        t = psym((vtop->c.i - 16) ^ inv, t);
-    } else if (v == VT_JMP || v == VT_JMPI) {
-        /* && or || optimization */
-        if ((v & 1) == inv) {
-            /* insert vtop->c jump list in t */
-            p = &vtop->c.i;
-            while (*p != 0)
-                p = (int *)(cur_text_section->data + *p);
-            *p = t;
-            t = vtop->c.i;
-        } else {
-            t = gjmp(t);
-            gsym(vtop->c.i);
-        }
-    } else {
-        if (is_float(vtop->type.t) || 
-            (vtop->type.t & VT_BTYPE) == VT_LLONG) {
-            vpushi(0);
-            gen_op(TOK_NE);
-        }
-        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-            /* constant jmp optimization */
-            if ((vtop->c.i != 0) != inv) 
-                t = gjmp(t);
-        } else {
-            v = gv(RC_INT);
-            o(0x85);
-            o(0xc0 + v * 9);
-            g(0x0f);
-            t = psym(0x85 ^ inv, t);
-        }
-    }
-    vtop--;
-    return t;
-}
-
-/* generate an integer binary operation */
-void gen_opi(int op)
-{
-    int r, fr, opc, c;
-
-    switch(op) {
-    case '+':
-    case TOK_ADDC1: /* add with carry generation */
-        opc = 0;
-    gen_op8:
-        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-            /* constant case */
-            vswap();
-            r = gv(RC_INT);
-            vswap();
-            c = vtop->c.i;
-            if (c == (char)c) {
-                /* XXX: generate inc and dec for smaller code ? */
-                o(0x83);
-                o(0xc0 | (opc << 3) | r);
-                g(c);
-            } else {
-                o(0x81);
-                oad(0xc0 | (opc << 3) | r, c);
-            }
-        } else {
-            gv2(RC_INT, RC_INT);
-            r = vtop[-1].r;
-            fr = vtop[0].r;
-            o((opc << 3) | 0x01);
-            o(0xc0 + r + fr * 8); 
-        }
-        vtop--;
-        if (op >= TOK_ULT && op <= TOK_GT) {
-            vtop->r = VT_CMP;
-            vtop->c.i = op;
-        }
-        break;
-    case '-':
-    case TOK_SUBC1: /* sub with carry generation */
-        opc = 5;
-        goto gen_op8;
-    case TOK_ADDC2: /* add with carry use */
-        opc = 2;
-        goto gen_op8;
-    case TOK_SUBC2: /* sub with carry use */
-        opc = 3;
-        goto gen_op8;
-    case '&':
-        opc = 4;
-        goto gen_op8;
-    case '^':
-        opc = 6;
-        goto gen_op8;
-    case '|':
-        opc = 1;
-        goto gen_op8;
-    case '*':
-        gv2(RC_INT, RC_INT);
-        r = vtop[-1].r;
-        fr = vtop[0].r;
-        vtop--;
-        o(0xaf0f); /* imul fr, r */
-        o(0xc0 + fr + r * 8);
-        break;
-    case TOK_SHL:
-        opc = 4;
-        goto gen_shift;
-    case TOK_SHR:
-        opc = 5;
-        goto gen_shift;
-    case TOK_SAR:
-        opc = 7;
-    gen_shift:
-        opc = 0xc0 | (opc << 3);
-        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-            /* constant case */
-            vswap();
-            r = gv(RC_INT);
-            vswap();
-            c = vtop->c.i & 0x1f;
-            o(0xc1); /* shl/shr/sar $xxx, r */
-            o(opc | r);
-            g(c);
-        } else {
-            /* we generate the shift in ecx */
-            gv2(RC_INT, RC_ECX);
-            r = vtop[-1].r;
-            o(0xd3); /* shl/shr/sar %cl, r */
-            o(opc | r);
-        }
-        vtop--;
-        break;
-    case '/':
-    case TOK_UDIV:
-    case TOK_PDIV:
-    case '%':
-    case TOK_UMOD:
-    case TOK_UMULL:
-        /* first operand must be in eax */
-        /* XXX: need better constraint for second operand */
-        gv2(RC_EAX, RC_ECX);
-        r = vtop[-1].r;
-        fr = vtop[0].r;
-        vtop--;
-        save_reg(TREG_EDX);
-        if (op == TOK_UMULL) {
-            o(0xf7); /* mul fr */
-            o(0xe0 + fr);
-            vtop->r2 = TREG_EDX;
-            r = TREG_EAX;
-        } else {
-            if (op == TOK_UDIV || op == TOK_UMOD) {
-                o(0xf7d231); /* xor %edx, %edx, div fr, %eax */
-                o(0xf0 + fr);
-            } else {
-                o(0xf799); /* cltd, idiv fr, %eax */
-                o(0xf8 + fr);
-            }
-            if (op == '%' || op == TOK_UMOD)
-                r = TREG_EDX;
-            else
-                r = TREG_EAX;
-        }
-        vtop->r = r;
-        break;
-    default:
-        opc = 7;
-        goto gen_op8;
-    }
-}
-
-/* generate a floating point operation 'v = t1 op t2' instruction. The
-   two operands are guaranted to have the same floating point type */
-/* XXX: need to use ST1 too */
-void gen_opf(int op)
-{
-    int a, ft, fc, swapped, r;
-
-    /* convert constants to memory references */
-    if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
-        vswap();
-        gv(RC_FLOAT);
-        vswap();
-    }
-    if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
-        gv(RC_FLOAT);
-
-    /* must put at least one value in the floating point register */
-    if ((vtop[-1].r & VT_LVAL) &&
-        (vtop[0].r & VT_LVAL)) {
-        vswap();
-        gv(RC_FLOAT);
-        vswap();
-    }
-    swapped = 0;
-    /* swap the stack if needed so that t1 is the register and t2 is
-       the memory reference */
-    if (vtop[-1].r & VT_LVAL) {
-        vswap();
-        swapped = 1;
-    }
-    if (op >= TOK_ULT && op <= TOK_GT) {
-        /* load on stack second operand */
-        load(TREG_ST0, vtop);
-        save_reg(TREG_EAX); /* eax is used by FP comparison code */
-        if (op == TOK_GE || op == TOK_GT)
-            swapped = !swapped;
-        else if (op == TOK_EQ || op == TOK_NE)
-            swapped = 0;
-        if (swapped)
-            o(0xc9d9); /* fxch %st(1) */
-        o(0xe9da); /* fucompp */
-        o(0xe0df); /* fnstsw %ax */
-        if (op == TOK_EQ) {
-            o(0x45e480); /* and $0x45, %ah */
-            o(0x40fC80); /* cmp $0x40, %ah */
-        } else if (op == TOK_NE) {
-            o(0x45e480); /* and $0x45, %ah */
-            o(0x40f480); /* xor $0x40, %ah */
-            op = TOK_NE;
-        } else if (op == TOK_GE || op == TOK_LE) {
-            o(0x05c4f6); /* test $0x05, %ah */
-            op = TOK_EQ;
-        } else {
-            o(0x45c4f6); /* test $0x45, %ah */
-            op = TOK_EQ;
-        }
-        vtop--;
-        vtop->r = VT_CMP;
-        vtop->c.i = op;
-    } else {
-        /* no memory reference possible for long double operations */
-        if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
-            load(TREG_ST0, vtop);
-            swapped = !swapped;
-        }
-        
-        switch(op) {
-        default:
-        case '+':
-            a = 0;
-            break;
-        case '-':
-            a = 4;
-            if (swapped)
-                a++;
-            break;
-        case '*':
-            a = 1;
-            break;
-        case '/':
-            a = 6;
-            if (swapped)
-                a++;
-            break;
-        }
-        ft = vtop->type.t;
-        fc = vtop->c.ul;
-        if ((ft & VT_BTYPE) == VT_LDOUBLE) {
-            o(0xde); /* fxxxp %st, %st(1) */
-            o(0xc1 + (a << 3));
-        } else {
-            /* if saved lvalue, then we must reload it */
-            r = vtop->r;
-            if ((r & VT_VALMASK) == VT_LLOCAL) {
-                SValue v1;
-                r = get_reg(RC_INT);
-                v1.type.t = VT_INT;
-                v1.r = VT_LOCAL | VT_LVAL;
-                v1.c.ul = fc;
-                load(r, &v1);
-                fc = 0;
-            }
-
-            if ((ft & VT_BTYPE) == VT_DOUBLE)
-                o(0xdc);
-            else
-                o(0xd8);
-            gen_modrm(a, r, vtop->sym, fc);
-        }
-        vtop--;
-    }
-}
-
-/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
-   and 'long long' cases. */
-void gen_cvt_itof(int t)
-{
-    save_reg(TREG_ST0);
-    gv(RC_INT);
-    if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
-        /* signed long long to float/double/long double (unsigned case
-           is handled generically) */
-        o(0x50 + vtop->r2); /* push r2 */
-        o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
-        o(0x242cdf); /* fildll (%esp) */
-        o(0x08c483); /* add $8, %esp */
-    } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == 
-               (VT_INT | VT_UNSIGNED)) {
-        /* unsigned int to float/double/long double */
-        o(0x6a); /* push $0 */
-        g(0x00);
-        o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
-        o(0x242cdf); /* fildll (%esp) */
-        o(0x08c483); /* add $8, %esp */
-    } else {
-        /* int to float/double/long double */
-        o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
-        o(0x2404db); /* fildl (%esp) */
-        o(0x04c483); /* add $4, %esp */
-    }
-    vtop->r = TREG_ST0;
-}
-
-/* convert fp to int 't' type */
-/* XXX: handle long long case */
-void gen_cvt_ftoi(int t)
-{
-    int r, r2, size;
-    Sym *sym;
-    CType ushort_type;
-
-    ushort_type.t = VT_SHORT | VT_UNSIGNED;
-
-    gv(RC_FLOAT);
-    if (t != VT_INT)
-        size = 8;
-    else 
-        size = 4;
-    
-    o(0x2dd9); /* ldcw xxx */
-    sym = external_global_sym(TOK___tcc_int_fpu_control, 
-                              &ushort_type, VT_LVAL);
-    greloc(cur_text_section, sym, 
-           ind, R_386_32);
-    gen_le32(0);
-    
-    oad(0xec81, size); /* sub $xxx, %esp */
-    if (size == 4)
-        o(0x1cdb); /* fistpl */
-    else
-        o(0x3cdf); /* fistpll */
-    o(0x24);
-    o(0x2dd9); /* ldcw xxx */
-    sym = external_global_sym(TOK___tcc_fpu_control, 
-                              &ushort_type, VT_LVAL);
-    greloc(cur_text_section, sym, 
-           ind, R_386_32);
-    gen_le32(0);
-
-    r = get_reg(RC_INT);
-    o(0x58 + r); /* pop r */
-    if (size == 8) {
-        if (t == VT_LLONG) {
-            vtop->r = r; /* mark reg as used */
-            r2 = get_reg(RC_INT);
-            o(0x58 + r2); /* pop r2 */
-            vtop->r2 = r2;
-        } else {
-            o(0x04c483); /* add $4, %esp */
-        }
-    }
-    vtop->r = r;
-}
-
-/* convert from one floating point type to another */
-void gen_cvt_ftof(int t)
-{
-    /* all we have to do on i386 is to put the float in a register */
-    gv(RC_FLOAT);
-}
-
-/* computed goto support */
-void ggoto(void)
-{
-    gcall_or_jmp(1);
-    vtop--;
-}
-
-/* bound check support functions */
-#ifdef CONFIG_TCC_BCHECK
-
-/* generate a bounded pointer addition */
-void gen_bounded_ptr_add(void)
-{
-    Sym *sym;
-
-    /* prepare fast i386 function call (args in eax and edx) */
-    gv2(RC_EAX, RC_EDX);
-    /* save all temporary registers */
-    vtop -= 2;
-    save_regs(0);
-    /* do a fast function call */
-    sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0);
-    greloc(cur_text_section, sym, 
-           ind + 1, R_386_PC32);
-    oad(0xe8, -4);
-    /* returned pointer is in eax */
-    vtop++;
-    vtop->r = TREG_EAX | VT_BOUNDED;
-    /* address of bounding function call point */
-    vtop->c.ul = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel)); 
-}
-
-/* patch pointer addition in vtop so that pointer dereferencing is
-   also tested */
-void gen_bounded_ptr_deref(void)
-{
-    int func;
-    int size, align;
-    Elf32_Rel *rel;
-    Sym *sym;
-
-    size = 0;
-    /* XXX: put that code in generic part of tcc */
-    if (!is_float(vtop->type.t)) {
-        if (vtop->r & VT_LVAL_BYTE)
-            size = 1;
-        else if (vtop->r & VT_LVAL_SHORT)
-            size = 2;
-    }
-    if (!size)
-        size = type_size(&vtop->type, &align);
-    switch(size) {
-    case  1: func = TOK___bound_ptr_indir1; break;
-    case  2: func = TOK___bound_ptr_indir2; break;
-    case  4: func = TOK___bound_ptr_indir4; break;
-    case  8: func = TOK___bound_ptr_indir8; break;
-    case 12: func = TOK___bound_ptr_indir12; break;
-    case 16: func = TOK___bound_ptr_indir16; break;
-    default:
-        error("unhandled size when derefencing bounded pointer");
-        func = 0;
-        break;
-    }
-
-    /* patch relocation */
-    /* XXX: find a better solution ? */
-    rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul);
-    sym = external_global_sym(func, &func_old_type, 0);
-    if (!sym->c)
-        put_extern_sym(sym, NULL, 0, 0);
-    rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
-}
-#endif
-
-/* end of X86 code generator */
-/*************************************************************/
-

+ 0 - 667
src/modules/native/tcc/libtcc/il-gen.c

@@ -1,667 +0,0 @@
-/*
- *  CIL code generator for TCC
- * 
- *  Copyright (c) 2002 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* number of available registers */
-#define NB_REGS             3
-
-/* a register can belong to several classes. The classes must be
-   sorted from more general to more precise (see gv2() code which does
-   assumptions on it). */
-#define RC_ST      0x0001  /* any stack entry */
-#define RC_ST0     0x0002  /* top of stack */
-#define RC_ST1     0x0004  /* top - 1 */
-
-#define RC_INT     RC_ST
-#define RC_FLOAT   RC_ST
-#define RC_IRET    RC_ST0 /* function return: integer register */
-#define RC_LRET    RC_ST0 /* function return: second integer register */
-#define RC_FRET    RC_ST0 /* function return: float register */
-
-/* pretty names for the registers */
-enum {
-    REG_ST0 = 0,
-    REG_ST1,
-    REG_ST2,
-};
-
-int reg_classes[NB_REGS] = {
-    /* ST0 */ RC_ST | RC_ST0,
-    /* ST1 */ RC_ST | RC_ST1,
-    /* ST2 */ RC_ST,
-};
-
-/* return registers for function */
-#define REG_IRET REG_ST0 /* single word int return register */
-#define REG_LRET REG_ST0 /* second word return register (for long long) */
-#define REG_FRET REG_ST0 /* float return register */
-
-/* defined if function parameters must be evaluated in reverse order */
-//#define INVERT_FUNC_PARAMS
-
-/* defined if structures are passed as pointers. Otherwise structures
-   are directly pushed on stack. */
-//#define FUNC_STRUCT_PARAM_AS_PTR
-
-/* pointer size, in bytes */
-#define PTR_SIZE 4
-
-/* long double size and alignment, in bytes */
-#define LDOUBLE_SIZE  8
-#define LDOUBLE_ALIGN 8
-
-/* function call context */
-typedef struct GFuncContext {
-    int func_call; /* func call type (FUNC_STDCALL or FUNC_CDECL) */
-} GFuncContext;
-
-/******************************************************/
-/* opcode definitions */
-
-#define IL_OP_PREFIX 0xFE
-
-enum ILOPCodes {
-#define OP(name, str, n) IL_OP_ ## name = n,
-#include "il-opcodes.h"
-#undef OP
-};
-
-char *il_opcodes_str[] = {
-#define OP(name, str, n) [n] = str,
-#include "il-opcodes.h"
-#undef OP
-};
-
-/******************************************************/
-
-/* arguments variable numbers start from there */
-#define ARG_BASE 0x70000000
-
-static FILE *il_outfile;
-
-static void out_byte(int c)
-{
-    *(char *)ind++ = c;
-}
-
-static void out_le32(int c)
-{
-    out_byte(c);
-    out_byte(c >> 8);
-    out_byte(c >> 16);
-    out_byte(c >> 24);
-}
-
-static void init_outfile(void)
-{
-    if (!il_outfile) {
-        il_outfile = stdout;
-        fprintf(il_outfile, 
-                ".assembly extern mscorlib\n"
-                "{\n"
-                ".ver 1:0:2411:0\n"
-                "}\n\n");
-    }
-}
-
-static void out_op1(int op)
-{
-    if (op & 0x100)
-        out_byte(IL_OP_PREFIX);
-    out_byte(op & 0xff);
-}
-
-/* output an opcode with prefix */
-static void out_op(int op)
-{
-    out_op1(op);
-    fprintf(il_outfile, " %s\n", il_opcodes_str[op]);
-}
-
-static void out_opb(int op, int c)
-{
-    out_op1(op);
-    out_byte(c);
-    fprintf(il_outfile, " %s %d\n", il_opcodes_str[op], c);
-}
-
-static void out_opi(int op, int c)
-{
-    out_op1(op);
-    out_le32(c);
-    fprintf(il_outfile, " %s 0x%x\n", il_opcodes_str[op], c);
-}
-
-/* XXX: not complete */
-static void il_type_to_str(char *buf, int buf_size, 
-                           int t, const char *varstr)
-{
-    int bt;
-    Sym *s, *sa;
-    char buf1[256];
-    const char *tstr;
-
-    t = t & VT_TYPE;
-    bt = t & VT_BTYPE;
-    buf[0] = '\0';
-    if (t & VT_UNSIGNED)
-        pstrcat(buf, buf_size, "unsigned ");
-    switch(bt) {
-    case VT_VOID:
-        tstr = "void";
-        goto add_tstr;
-    case VT_BOOL:
-        tstr = "bool";
-        goto add_tstr;
-    case VT_BYTE:
-        tstr = "int8";
-        goto add_tstr;
-    case VT_SHORT:
-        tstr = "int16";
-        goto add_tstr;
-    case VT_ENUM:
-    case VT_INT:
-    case VT_LONG:
-        tstr = "int32";
-        goto add_tstr;
-    case VT_LLONG:
-        tstr = "int64";
-        goto add_tstr;
-    case VT_FLOAT:
-        tstr = "float32";
-        goto add_tstr;
-    case VT_DOUBLE:
-    case VT_LDOUBLE:
-        tstr = "float64";
-    add_tstr:
-        pstrcat(buf, buf_size, tstr);
-        break;
-    case VT_STRUCT:
-        error("structures not handled yet");
-        break;
-    case VT_FUNC:
-        s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
-        il_type_to_str(buf, buf_size, s->t, varstr);
-        pstrcat(buf, buf_size, "(");
-        sa = s->next;
-        while (sa != NULL) {
-            il_type_to_str(buf1, sizeof(buf1), sa->t, NULL);
-            pstrcat(buf, buf_size, buf1);
-            sa = sa->next;
-            if (sa)
-                pstrcat(buf, buf_size, ", ");
-        }
-        pstrcat(buf, buf_size, ")");
-        goto no_var;
-    case VT_PTR:
-        s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
-        pstrcpy(buf1, sizeof(buf1), "*");
-        if (varstr)
-            pstrcat(buf1, sizeof(buf1), varstr);
-        il_type_to_str(buf, buf_size, s->t, buf1);
-        goto no_var;
-    }
-    if (varstr) {
-        pstrcat(buf, buf_size, " ");
-        pstrcat(buf, buf_size, varstr);
-    }
- no_var: ;
-}
-
-
-/* patch relocation entry with value 'val' */
-void greloc_patch1(Reloc *p, int val)
-{
-}
-
-/* output a symbol and patch all calls to it */
-void gsym_addr(t, a)
-{
-}
-
-/* output jump and return symbol */
-static int out_opj(int op, int c)
-{
-    out_op1(op);
-    out_le32(0);
-    if (c == 0) {
-        c = ind - (int)cur_text_section->data;
-    }
-    fprintf(il_outfile, " %s L%d\n", il_opcodes_str[op], c);
-    return c;
-}
-
-void gsym(int t)
-{
-    fprintf(il_outfile, "L%d:\n", t);
-}
-
-/* load 'r' from value 'sv' */
-void load(int r, SValue *sv)
-{
-    int v, fc, ft;
-
-    v = sv->r & VT_VALMASK;
-    fc = sv->c.i;
-    ft = sv->t;
-
-    if (sv->r & VT_LVAL) {
-        if (v == VT_LOCAL) {
-            if (fc >= ARG_BASE) {
-                fc -= ARG_BASE;
-                if (fc >= 0 && fc <= 4) {
-                    out_op(IL_OP_LDARG_0 + fc);
-                } else if (fc <= 0xff) {
-                    out_opb(IL_OP_LDARG_S, fc);
-                } else {
-                    out_opi(IL_OP_LDARG, fc);
-                }
-            } else {
-                if (fc >= 0 && fc <= 4) {
-                    out_op(IL_OP_LDLOC_0 + fc);
-                } else if (fc <= 0xff) {
-                    out_opb(IL_OP_LDLOC_S, fc);
-                } else {
-                    out_opi(IL_OP_LDLOC, fc);
-                }
-            }
-        } else if (v == VT_CONST) {
-                /* XXX: handle globals */
-                out_opi(IL_OP_LDSFLD, 0);
-        } else {
-            if ((ft & VT_BTYPE) == VT_FLOAT) {
-                out_op(IL_OP_LDIND_R4);
-            } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
-                out_op(IL_OP_LDIND_R8);
-            } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
-                out_op(IL_OP_LDIND_R8);
-            } else if ((ft & VT_TYPE) == VT_BYTE)
-                out_op(IL_OP_LDIND_I1);
-            else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED))
-                out_op(IL_OP_LDIND_U1);
-            else if ((ft & VT_TYPE) == VT_SHORT)
-                out_op(IL_OP_LDIND_I2);
-            else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED))
-                out_op(IL_OP_LDIND_U2);
-            else
-                out_op(IL_OP_LDIND_I4);
-        } 
-    } else {
-        if (v == VT_CONST) {
-            /* XXX: handle globals */
-            if (fc >= -1 && fc <= 8) {
-                out_op(IL_OP_LDC_I4_M1 + fc + 1); 
-            } else {
-                out_opi(IL_OP_LDC_I4, fc);
-            }
-        } else if (v == VT_LOCAL) {
-            if (fc >= ARG_BASE) {
-                fc -= ARG_BASE;
-                if (fc <= 0xff) {
-                    out_opb(IL_OP_LDARGA_S, fc);
-                } else {
-                    out_opi(IL_OP_LDARGA, fc);
-                }
-            } else {
-                if (fc <= 0xff) {
-                    out_opb(IL_OP_LDLOCA_S, fc);
-                } else {
-                    out_opi(IL_OP_LDLOCA, fc);
-                }
-            }
-        } else {
-            /* XXX: do it */
-        }
-    }
-}
-
-/* store register 'r' in lvalue 'v' */
-void store(int r, SValue *sv)
-{
-    int v, fc, ft;
-
-    v = sv->r & VT_VALMASK;
-    fc = sv->c.i;
-    ft = sv->t;
-    if (v == VT_LOCAL) {
-        if (fc >= ARG_BASE) {
-            fc -= ARG_BASE;
-            /* XXX: check IL arg store semantics */
-            if (fc <= 0xff) {
-                out_opb(IL_OP_STARG_S, fc);
-            } else {
-                out_opi(IL_OP_STARG, fc);
-            }
-        } else {
-            if (fc >= 0 && fc <= 4) {
-                out_op(IL_OP_STLOC_0 + fc);
-            } else if (fc <= 0xff) {
-                out_opb(IL_OP_STLOC_S, fc);
-            } else {
-                out_opi(IL_OP_STLOC, fc);
-            }
-        }
-    } else if (v == VT_CONST) {
-        /* XXX: handle globals */
-        out_opi(IL_OP_STSFLD, 0);
-    } else {
-        if ((ft & VT_BTYPE) == VT_FLOAT)
-            out_op(IL_OP_STIND_R4);
-        else if ((ft & VT_BTYPE) == VT_DOUBLE)
-            out_op(IL_OP_STIND_R8);
-        else if ((ft & VT_BTYPE) == VT_LDOUBLE)
-            out_op(IL_OP_STIND_R8);
-        else if ((ft & VT_BTYPE) == VT_BYTE)
-            out_op(IL_OP_STIND_I1);
-        else if ((ft & VT_BTYPE) == VT_SHORT)
-            out_op(IL_OP_STIND_I2);
-        else
-            out_op(IL_OP_STIND_I4);
-    }
-}
-
-/* start function call and return function call context */
-void gfunc_start(GFuncContext *c, int func_call)
-{
-    c->func_call = func_call;
-}
-
-/* push function parameter which is in (vtop->t, vtop->c). Stack entry
-   is then popped. */
-void gfunc_param(GFuncContext *c)
-{
-    if ((vtop->t & VT_BTYPE) == VT_STRUCT) {
-        error("structures passed as value not handled yet");
-    } else {
-        /* simply push on stack */
-        gv(RC_ST0);
-    }
-    vtop--;
-}
-
-/* generate function call with address in (vtop->t, vtop->c) and free function
-   context. Stack entry is popped */
-void gfunc_call(GFuncContext *c)
-{
-    char buf[1024];
-
-    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
-        /* XXX: more info needed from tcc */
-        il_type_to_str(buf, sizeof(buf), vtop->t, "xxx");
-        fprintf(il_outfile, " call %s\n", buf);
-    } else {
-        /* indirect call */
-        gv(RC_INT);
-        il_type_to_str(buf, sizeof(buf), vtop->t, NULL);
-        fprintf(il_outfile, " calli %s\n", buf);
-    }
-    vtop--;
-}
-
-/* generate function prolog of type 't' */
-void gfunc_prolog(int t)
-{
-    int addr, u, func_call;
-    Sym *sym;
-    char buf[1024];
-
-    init_outfile();
-
-    /* XXX: pass function name to gfunc_prolog */
-    il_type_to_str(buf, sizeof(buf), t, funcname);
-    fprintf(il_outfile, ".method static %s il managed\n", buf);
-    fprintf(il_outfile, "{\n");
-    /* XXX: cannot do better now */
-    fprintf(il_outfile, " .maxstack %d\n", NB_REGS);
-    fprintf(il_outfile, " .locals (int32, int32, int32, int32, int32, int32, int32, int32)\n");
-    
-    if (!strcmp(funcname, "main"))
-        fprintf(il_outfile, " .entrypoint\n");
-        
-    sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
-    func_call = sym->r;
-
-    addr = ARG_BASE;
-    /* if the function returns a structure, then add an
-       implicit pointer parameter */
-    func_vt = sym->t;
-    if ((func_vt & VT_BTYPE) == VT_STRUCT) {
-        func_vc = addr;
-        addr++;
-    }
-    /* define parameters */
-    while ((sym = sym->next) != NULL) {
-        u = sym->t;
-        sym_push(sym->v & ~SYM_FIELD, u,
-                 VT_LOCAL | lvalue_type(sym->type.t), addr);
-        addr++;
-    }
-}
-
-/* generate function epilog */
-void gfunc_epilog(void)
-{
-    out_op(IL_OP_RET);
-    fprintf(il_outfile, "}\n\n");
-}
-
-/* generate a jump to a label */
-int gjmp(int t)
-{
-    return out_opj(IL_OP_BR, t);
-}
-
-/* generate a jump to a fixed address */
-void gjmp_addr(int a)
-{
-    /* XXX: handle syms */
-    out_opi(IL_OP_BR, a);
-}
-
-/* generate a test. set 'inv' to invert test. Stack entry is popped */
-int gtst(int inv, int t)
-{
-    int v, *p, c;
-
-    v = vtop->r & VT_VALMASK;
-    if (v == VT_CMP) {
-        c = vtop->c.i ^ inv;
-        switch(c) {
-        case TOK_EQ:
-            c = IL_OP_BEQ;
-            break;
-        case TOK_NE:
-            c = IL_OP_BNE_UN;
-            break;
-        case TOK_LT:
-            c = IL_OP_BLT;
-            break;
-        case TOK_LE:
-            c = IL_OP_BLE;
-            break;
-        case TOK_GT:
-            c = IL_OP_BGT;
-            break;
-        case TOK_GE:
-            c = IL_OP_BGE;
-            break;
-        case TOK_ULT:
-            c = IL_OP_BLT_UN;
-            break;
-        case TOK_ULE:
-            c = IL_OP_BLE_UN;
-            break;
-        case TOK_UGT:
-            c = IL_OP_BGT_UN;
-            break;
-        case TOK_UGE:
-            c = IL_OP_BGE_UN;
-            break;
-        }
-        t = out_opj(c, t);
-    } else if (v == VT_JMP || v == VT_JMPI) {
-        /* && or || optimization */
-        if ((v & 1) == inv) {
-            /* insert vtop->c jump list in t */
-            p = &vtop->c.i;
-            while (*p != 0)
-                p = (int *)*p;
-            *p = t;
-            t = vtop->c.i;
-        } else {
-            t = gjmp(t);
-            gsym(vtop->c.i);
-        }
-    } else {
-        if (is_float(vtop->t)) {
-            vpushi(0);
-            gen_op(TOK_NE);
-        }
-        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
-            /* constant jmp optimization */
-            if ((vtop->c.i != 0) != inv) 
-                t = gjmp(t);
-        } else {
-            v = gv(RC_INT);
-            t = out_opj(IL_OP_BRTRUE - inv, t);
-        }
-    }
-    vtop--;
-    return t;
-}
-
-/* generate an integer binary operation */
-void gen_opi(int op)
-{
-    gv2(RC_ST1, RC_ST0);
-    switch(op) {
-    case '+':
-        out_op(IL_OP_ADD);
-        goto std_op;
-    case '-':
-        out_op(IL_OP_SUB);
-        goto std_op;
-    case '&':
-        out_op(IL_OP_AND);
-        goto std_op;
-    case '^':
-        out_op(IL_OP_XOR);
-        goto std_op;
-    case '|':
-        out_op(IL_OP_OR);
-        goto std_op;
-    case '*':
-        out_op(IL_OP_MUL);
-        goto std_op;
-    case TOK_SHL:
-        out_op(IL_OP_SHL);
-        goto std_op;
-    case TOK_SHR:
-        out_op(IL_OP_SHR_UN);
-        goto std_op;
-    case TOK_SAR:
-        out_op(IL_OP_SHR);
-        goto std_op;
-    case '/':
-    case TOK_PDIV:
-        out_op(IL_OP_DIV);
-        goto std_op;
-    case TOK_UDIV:
-        out_op(IL_OP_DIV_UN);
-        goto std_op;
-    case '%':
-        out_op(IL_OP_REM);
-        goto std_op;
-    case TOK_UMOD:
-        out_op(IL_OP_REM_UN);
-    std_op:
-        vtop--;
-        vtop[0].r = REG_ST0;
-        break;
-    case TOK_EQ:
-    case TOK_NE:
-    case TOK_LT:
-    case TOK_LE:
-    case TOK_GT:
-    case TOK_GE:
-    case TOK_ULT:
-    case TOK_ULE:
-    case TOK_UGT:
-    case TOK_UGE:
-        vtop--;
-        vtop[0].r = VT_CMP;
-        vtop[0].c.i = op;
-        break;
-    }
-}
-
-/* generate a floating point operation 'v = t1 op t2' instruction. The
-   two operands are guaranted to have the same floating point type */
-void gen_opf(int op)
-{
-    /* same as integer */
-    gen_opi(op);
-}
-
-/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
-   and 'long long' cases. */
-void gen_cvt_itof(int t)
-{
-    gv(RC_ST0);
-    if (t == VT_FLOAT)
-        out_op(IL_OP_CONV_R4);
-    else
-        out_op(IL_OP_CONV_R8);
-}
-
-/* convert fp to int 't' type */
-/* XXX: handle long long case */
-void gen_cvt_ftoi(int t)
-{
-    gv(RC_ST0);
-    switch(t) {
-    case VT_INT | VT_UNSIGNED:
-        out_op(IL_OP_CONV_U4);
-        break;
-    case VT_LLONG:
-        out_op(IL_OP_CONV_I8);
-        break;
-    case VT_LLONG | VT_UNSIGNED:
-        out_op(IL_OP_CONV_U8);
-        break;
-    default:
-        out_op(IL_OP_CONV_I4);
-        break;
-    }
-}
-
-/* convert from one floating point type to another */
-void gen_cvt_ftof(int t)
-{
-    gv(RC_ST0);
-    if (t == VT_FLOAT) {
-        out_op(IL_OP_CONV_R4);
-    } else {
-        out_op(IL_OP_CONV_R8);
-    }
-}
-
-/* end of CIL code generator */
-/*************************************************************/
-

+ 0 - 251
src/modules/native/tcc/libtcc/il-opcodes.h

@@ -1,251 +0,0 @@
-/*
- *  CIL opcode definition
- * 
- *  Copyright (c) 2002 Fabrice Bellard
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-OP(NOP, "nop", 0x00)
-OP(BREAK, "break", 0x01)
-OP(LDARG_0, "ldarg.0", 0x02)
-OP(LDARG_1, "ldarg.1", 0x03)
-OP(LDARG_2, "ldarg.2", 0x04)
-OP(LDARG_3, "ldarg.3", 0x05)
-OP(LDLOC_0, "ldloc.0", 0x06)
-OP(LDLOC_1, "ldloc.1", 0x07)
-OP(LDLOC_2, "ldloc.2", 0x08)
-OP(LDLOC_3, "ldloc.3", 0x09)
-OP(STLOC_0, "stloc.0", 0x0a)
-OP(STLOC_1, "stloc.1", 0x0b)
-OP(STLOC_2, "stloc.2", 0x0c)
-OP(STLOC_3, "stloc.3", 0x0d)
-OP(LDARG_S, "ldarg.s", 0x0e)
-OP(LDARGA_S, "ldarga.s", 0x0f)
-OP(STARG_S, "starg.s", 0x10)
-OP(LDLOC_S, "ldloc.s", 0x11)
-OP(LDLOCA_S, "ldloca.s", 0x12)
-OP(STLOC_S, "stloc.s", 0x13)
-OP(LDNULL, "ldnull", 0x14)
-OP(LDC_I4_M1, "ldc.i4.m1", 0x15)
-OP(LDC_I4_0, "ldc.i4.0", 0x16)
-OP(LDC_I4_1, "ldc.i4.1", 0x17)
-OP(LDC_I4_2, "ldc.i4.2", 0x18)
-OP(LDC_I4_3, "ldc.i4.3", 0x19)
-OP(LDC_I4_4, "ldc.i4.4", 0x1a)
-OP(LDC_I4_5, "ldc.i4.5", 0x1b)
-OP(LDC_I4_6, "ldc.i4.6", 0x1c)
-OP(LDC_I4_7, "ldc.i4.7", 0x1d)
-OP(LDC_I4_8, "ldc.i4.8", 0x1e)
-OP(LDC_I4_S, "ldc.i4.s", 0x1f)
-OP(LDC_I4, "ldc.i4", 0x20)
-OP(LDC_I8, "ldc.i8", 0x21)
-OP(LDC_R4, "ldc.r4", 0x22)
-OP(LDC_R8, "ldc.r8", 0x23)
-OP(LDPTR, "ldptr", 0x24)
-OP(DUP, "dup", 0x25)
-OP(POP, "pop", 0x26)
-OP(JMP, "jmp", 0x27)
-OP(CALL, "call", 0x28)
-OP(CALLI, "calli", 0x29)
-OP(RET, "ret", 0x2a)
-OP(BR_S, "br.s", 0x2b)
-OP(BRFALSE_S, "brfalse.s", 0x2c)
-OP(BRTRUE_S, "brtrue.s", 0x2d)
-OP(BEQ_S, "beq.s", 0x2e)
-OP(BGE_S, "bge.s", 0x2f)
-OP(BGT_S, "bgt.s", 0x30)
-OP(BLE_S, "ble.s", 0x31)
-OP(BLT_S, "blt.s", 0x32)
-OP(BNE_UN_S, "bne.un.s", 0x33)
-OP(BGE_UN_S, "bge.un.s", 0x34)
-OP(BGT_UN_S, "bgt.un.s", 0x35)
-OP(BLE_UN_S, "ble.un.s", 0x36)
-OP(BLT_UN_S, "blt.un.s", 0x37)
-OP(BR, "br", 0x38)
-OP(BRFALSE, "brfalse", 0x39)
-OP(BRTRUE, "brtrue", 0x3a)
-OP(BEQ, "beq", 0x3b)
-OP(BGE, "bge", 0x3c)
-OP(BGT, "bgt", 0x3d)
-OP(BLE, "ble", 0x3e)
-OP(BLT, "blt", 0x3f)
-OP(BNE_UN, "bne.un", 0x40)
-OP(BGE_UN, "bge.un", 0x41)
-OP(BGT_UN, "bgt.un", 0x42)
-OP(BLE_UN, "ble.un", 0x43)
-OP(BLT_UN, "blt.un", 0x44)
-OP(SWITCH, "switch", 0x45)
-OP(LDIND_I1, "ldind.i1", 0x46)
-OP(LDIND_U1, "ldind.u1", 0x47)
-OP(LDIND_I2, "ldind.i2", 0x48)
-OP(LDIND_U2, "ldind.u2", 0x49)
-OP(LDIND_I4, "ldind.i4", 0x4a)
-OP(LDIND_U4, "ldind.u4", 0x4b)
-OP(LDIND_I8, "ldind.i8", 0x4c)
-OP(LDIND_I, "ldind.i", 0x4d)
-OP(LDIND_R4, "ldind.r4", 0x4e)
-OP(LDIND_R8, "ldind.r8", 0x4f)
-OP(LDIND_REF, "ldind.ref", 0x50)
-OP(STIND_REF, "stind.ref", 0x51)
-OP(STIND_I1, "stind.i1", 0x52)
-OP(STIND_I2, "stind.i2", 0x53)
-OP(STIND_I4, "stind.i4", 0x54)
-OP(STIND_I8, "stind.i8", 0x55)
-OP(STIND_R4, "stind.r4", 0x56)
-OP(STIND_R8, "stind.r8", 0x57)
-OP(ADD, "add", 0x58)
-OP(SUB, "sub", 0x59)
-OP(MUL, "mul", 0x5a)
-OP(DIV, "div", 0x5b)
-OP(DIV_UN, "div.un", 0x5c)
-OP(REM, "rem", 0x5d)
-OP(REM_UN, "rem.un", 0x5e)
-OP(AND, "and", 0x5f)
-OP(OR, "or", 0x60)
-OP(XOR, "xor", 0x61)
-OP(SHL, "shl", 0x62)
-OP(SHR, "shr", 0x63)
-OP(SHR_UN, "shr.un", 0x64)
-OP(NEG, "neg", 0x65)
-OP(NOT, "not", 0x66)
-OP(CONV_I1, "conv.i1", 0x67)
-OP(CONV_I2, "conv.i2", 0x68)
-OP(CONV_I4, "conv.i4", 0x69)
-OP(CONV_I8, "conv.i8", 0x6a)
-OP(CONV_R4, "conv.r4", 0x6b)
-OP(CONV_R8, "conv.r8", 0x6c)
-OP(CONV_U4, "conv.u4", 0x6d)
-OP(CONV_U8, "conv.u8", 0x6e)
-OP(CALLVIRT, "callvirt", 0x6f)
-OP(CPOBJ, "cpobj", 0x70)
-OP(LDOBJ, "ldobj", 0x71)
-OP(LDSTR, "ldstr", 0x72)
-OP(NEWOBJ, "newobj", 0x73)
-OP(CASTCLASS, "castclass", 0x74)
-OP(ISINST, "isinst", 0x75)
-OP(CONV_R_UN, "conv.r.un", 0x76)
-OP(ANN_DATA_S, "ann.data.s", 0x77)
-OP(UNBOX, "unbox", 0x79)
-OP(THROW, "throw", 0x7a)
-OP(LDFLD, "ldfld", 0x7b)
-OP(LDFLDA, "ldflda", 0x7c)
-OP(STFLD, "stfld", 0x7d)
-OP(LDSFLD, "ldsfld", 0x7e)
-OP(LDSFLDA, "ldsflda", 0x7f)
-OP(STSFLD, "stsfld", 0x80)
-OP(STOBJ, "stobj", 0x81)
-OP(CONV_OVF_I1_UN, "conv.ovf.i1.un", 0x82)
-OP(CONV_OVF_I2_UN, "conv.ovf.i2.un", 0x83)
-OP(CONV_OVF_I4_UN, "conv.ovf.i4.un", 0x84)
-OP(CONV_OVF_I8_UN, "conv.ovf.i8.un", 0x85)
-OP(CONV_OVF_U1_UN, "conv.ovf.u1.un", 0x86)
-OP(CONV_OVF_U2_UN, "conv.ovf.u2.un", 0x87)
-OP(CONV_OVF_U4_UN, "conv.ovf.u4.un", 0x88)
-OP(CONV_OVF_U8_UN, "conv.ovf.u8.un", 0x89)
-OP(CONV_OVF_I_UN, "conv.ovf.i.un", 0x8a)
-OP(CONV_OVF_U_UN, "conv.ovf.u.un", 0x8b)
-OP(BOX, "box", 0x8c)
-OP(NEWARR, "newarr", 0x8d)
-OP(LDLEN, "ldlen", 0x8e)
-OP(LDELEMA, "ldelema", 0x8f)
-OP(LDELEM_I1, "ldelem.i1", 0x90)
-OP(LDELEM_U1, "ldelem.u1", 0x91)
-OP(LDELEM_I2, "ldelem.i2", 0x92)
-OP(LDELEM_U2, "ldelem.u2", 0x93)
-OP(LDELEM_I4, "ldelem.i4", 0x94)
-OP(LDELEM_U4, "ldelem.u4", 0x95)
-OP(LDELEM_I8, "ldelem.i8", 0x96)
-OP(LDELEM_I, "ldelem.i", 0x97)
-OP(LDELEM_R4, "ldelem.r4", 0x98)
-OP(LDELEM_R8, "ldelem.r8", 0x99)
-OP(LDELEM_REF, "ldelem.ref", 0x9a)
-OP(STELEM_I, "stelem.i", 0x9b)
-OP(STELEM_I1, "stelem.i1", 0x9c)
-OP(STELEM_I2, "stelem.i2", 0x9d)
-OP(STELEM_I4, "stelem.i4", 0x9e)
-OP(STELEM_I8, "stelem.i8", 0x9f)
-OP(STELEM_R4, "stelem.r4", 0xa0)
-OP(STELEM_R8, "stelem.r8", 0xa1)
-OP(STELEM_REF, "stelem.ref", 0xa2)
-OP(CONV_OVF_I1, "conv.ovf.i1", 0xb3)
-OP(CONV_OVF_U1, "conv.ovf.u1", 0xb4)
-OP(CONV_OVF_I2, "conv.ovf.i2", 0xb5)
-OP(CONV_OVF_U2, "conv.ovf.u2", 0xb6)
-OP(CONV_OVF_I4, "conv.ovf.i4", 0xb7)
-OP(CONV_OVF_U4, "conv.ovf.u4", 0xb8)
-OP(CONV_OVF_I8, "conv.ovf.i8", 0xb9)
-OP(CONV_OVF_U8, "conv.ovf.u8", 0xba)
-OP(REFANYVAL, "refanyval", 0xc2)
-OP(CKFINITE, "ckfinite", 0xc3)
-OP(MKREFANY, "mkrefany", 0xc6)
-OP(ANN_CALL, "ann.call", 0xc7)
-OP(ANN_CATCH, "ann.catch", 0xc8)
-OP(ANN_DEAD, "ann.dead", 0xc9)
-OP(ANN_HOISTED, "ann.hoisted", 0xca)
-OP(ANN_HOISTED_CALL, "ann.hoisted.call", 0xcb)
-OP(ANN_LAB, "ann.lab", 0xcc)
-OP(ANN_DEF, "ann.def", 0xcd)
-OP(ANN_REF_S, "ann.ref.s", 0xce)
-OP(ANN_PHI, "ann.phi", 0xcf)
-OP(LDTOKEN, "ldtoken", 0xd0)
-OP(CONV_U2, "conv.u2", 0xd1)
-OP(CONV_U1, "conv.u1", 0xd2)
-OP(CONV_I, "conv.i", 0xd3)
-OP(CONV_OVF_I, "conv.ovf.i", 0xd4)
-OP(CONV_OVF_U, "conv.ovf.u", 0xd5)
-OP(ADD_OVF, "add.ovf", 0xd6)
-OP(ADD_OVF_UN, "add.ovf.un", 0xd7)
-OP(MUL_OVF, "mul.ovf", 0xd8)
-OP(MUL_OVF_UN, "mul.ovf.un", 0xd9)
-OP(SUB_OVF, "sub.ovf", 0xda)
-OP(SUB_OVF_UN, "sub.ovf.un", 0xdb)
-OP(ENDFINALLY, "endfinally", 0xdc)
-OP(LEAVE, "leave", 0xdd)
-OP(LEAVE_S, "leave.s", 0xde)
-OP(STIND_I, "stind.i", 0xdf)
-OP(CONV_U, "conv.u", 0xe0)
-
-/* prefix instructions. we use an opcode >= 256 to ease coding */
-
-OP(ARGLIST, "arglist", 0x100)
-OP(CEQ, "ceq", 0x101)
-OP(CGT, "cgt", 0x102)
-OP(CGT_UN, "cgt.un", 0x103)
-OP(CLT, "clt", 0x104)
-OP(CLT_UN, "clt.un", 0x105)
-OP(LDFTN, "ldftn", 0x106)
-OP(LDVIRTFTN, "ldvirtftn", 0x107)
-OP(JMPI, "jmpi", 0x108)
-OP(LDARG, "ldarg", 0x109)
-OP(LDARGA, "ldarga", 0x10a)
-OP(STARG, "starg", 0x10b)
-OP(LDLOC, "ldloc", 0x10c)
-OP(LDLOCA, "ldloca", 0x10d)
-OP(STLOC, "stloc", 0x10e)
-OP(LOCALLOC, "localloc", 0x10f)
-OP(ENDFILTER, "endfilter", 0x111)
-OP(UNALIGNED, "unaligned", 0x112)
-OP(VOLATILE, "volatile", 0x113)
-OP(TAIL, "tail", 0x114)
-OP(INITOBJ, "initobj", 0x115)
-OP(ANN_LIVE, "ann.live", 0x116)
-OP(CPBLK, "cpblk", 0x117)
-OP(INITBLK, "initblk", 0x118)
-OP(ANN_REF, "ann.ref", 0x119)
-OP(RETHROW, "rethrow", 0x11a)
-OP(SIZEOF, "sizeof", 0x11c)
-OP(REFANYTYPE, "refanytype", 0x11d)
-OP(ANN_DATA, "ann.data", 0x122)
-OP(ANN_ARG, "ann.arg", 0x123)

+ 0 - 2263
src/modules/native/tcc/libtcc/libtcc.c

@@ -1,2263 +0,0 @@
-/*
- *  TCC - Tiny C Compiler
- * 
- *  Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "tcc.h"
-
-/********************************************************/
-/* global variables */
-
-/* display benchmark infos */
-int total_lines;
-int total_bytes;
-
-/* parser */
-static struct BufferedFile *file;
-static int ch, tok;
-static CValue tokc;
-static CString tokcstr; /* current parsed string, if any */
-/* additional informations about token */
-static int tok_flags;
-#define TOK_FLAG_BOL   0x0001 /* beginning of line before */
-#define TOK_FLAG_BOF   0x0002 /* beginning of file before */
-#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
-#define TOK_FLAG_EOF   0x0008 /* end of file */
-
-static int *macro_ptr, *macro_ptr_allocated;
-static int *unget_saved_macro_ptr;
-static int unget_saved_buffer[TOK_MAX_SIZE + 1];
-static int unget_buffer_enabled;
-static int parse_flags;
-#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
-#define PARSE_FLAG_TOK_NUM    0x0002 /* return numbers instead of TOK_PPNUM */
-#define PARSE_FLAG_LINEFEED   0x0004 /* line feed is returned as a
-                                        token. line feed is also
-                                        returned at eof */
-#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
-#define PARSE_FLAG_SPACES     0x0010 /* next() returns space tokens (for -E) */
- 
-static Section *text_section, *data_section, *bss_section; /* predefined sections */
-static Section *cur_text_section; /* current section where function code is
-                              generated */
-#ifdef CONFIG_TCC_ASM
-static Section *last_text_section; /* to handle .previous asm directive */
-#endif
-/* bound check related sections */
-static Section *bounds_section; /* contains global data bound description */
-static Section *lbounds_section; /* contains local data bound description */
-/* symbol sections */
-static Section *symtab_section, *strtab_section;
-
-/* debug sections */
-static Section *stab_section, *stabstr_section;
-
-/* loc : local variable index
-   ind : output code index
-   rsym: return symbol
-   anon_sym: anonymous symbol index
-*/
-static int rsym, anon_sym, ind, loc;
-/* expression generation modifiers */
-static int const_wanted; /* true if constant wanted */
-static int nocode_wanted; /* true if no code generation wanted for an expression */
-static int global_expr;  /* true if compound literals must be allocated
-                            globally (used during initializers parsing */
-static CType func_vt; /* current function return type (used by return
-                         instruction) */
-static int func_vc;
-static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
-static int tok_ident;
-static TokenSym **table_ident;
-static TokenSym *hash_ident[TOK_HASH_SIZE];
-static char token_buf[STRING_MAX_SIZE + 1];
-static char *funcname;
-static Sym *global_stack, *local_stack;
-static Sym *define_stack;
-static Sym *global_label_stack, *local_label_stack;
-/* symbol allocator */
-#define SYM_POOL_NB (8192 / sizeof(Sym))
-static Sym *sym_free_first;
-static void **sym_pools;
-static int nb_sym_pools;
-
-static SValue vstack[VSTACK_SIZE], *vtop;
-/* some predefined types */
-static CType char_pointer_type, func_old_type, int_type;
-
-/* use GNU C extensions */
-static int gnu_ext = 1;
-
-/* use Tiny C extensions */
-static int tcc_ext = 1;
-
-/* max number of callers shown if error */
-#ifdef CONFIG_TCC_BACKTRACE
-int num_callers = 6;
-const char **rt_bound_error_msg;
-#endif
-
-/* XXX: get rid of this ASAP */
-static struct TCCState *tcc_state;
-
-/********************************************************/
-/* function prototypes */
-
-/* tccpp.c */
-static void next(void);
-char *get_tok_str(int v, CValue *cv);
-
-/* tccgen.c */
-static void parse_expr_type(CType *type);
-static void expr_type(CType *type);
-static void unary_type(CType *type);
-static void block(int *bsym, int *csym, int *case_sym, int *def_sym, 
-                  int case_reg, int is_expr);
-static int expr_const(void);
-static void expr_eq(void);
-static void gexpr(void);
-static void gen_inline_functions(void);
-static void decl(int l);
-static void decl_initializer(CType *type, Section *sec, unsigned long c, 
-                             int first, int size_only);
-static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, 
-                                   int has_init, int v, int scope);
-int gv(int rc);
-void gv2(int rc1, int rc2);
-void move_reg(int r, int s);
-void save_regs(int n);
-void save_reg(int r);
-void vpop(void);
-void vswap(void);
-void vdup(void);
-int get_reg(int rc);
-int get_reg_ex(int rc,int rc2);
-
-void gen_op(int op);
-void force_charshort_cast(int t);
-static void gen_cast(CType *type);
-void vstore(void);
-static Sym *sym_find(int v);
-static Sym *sym_push(int v, CType *type, int r, int c);
-
-/* type handling */
-static int type_size(CType *type, int *a);
-static inline CType *pointed_type(CType *type);
-static int pointed_size(CType *type);
-static int lvalue_type(int t);
-static int parse_btype(CType *type, AttributeDef *ad);
-static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
-static int compare_types(CType *type1, CType *type2, int unqualified);
-static int is_compatible_types(CType *type1, CType *type2);
-static int is_compatible_parameter_types(CType *type1, CType *type2);
-
-int ieee_finite(double d);
-void vpushi(int v);
-void vpushll(long long v);
-void vrott(int n);
-void vnrott(int n);
-void lexpand_nr(void);
-static void vpush_global_sym(CType *type, int v);
-void vset(CType *type, int r, int v);
-void type_to_str(char *buf, int buf_size, 
-                 CType *type, const char *varstr);
-static Sym *get_sym_ref(CType *type, Section *sec,
-                        unsigned long offset, unsigned long size);
-static Sym *external_global_sym(int v, CType *type, int r);
-
-/* section generation */
-static void section_realloc(Section *sec, unsigned long new_size);
-static void *section_ptr_add(Section *sec, unsigned long size);
-static void put_extern_sym(Sym *sym, Section *section, 
-                           unsigned long value, unsigned long size);
-static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
-static int put_elf_str(Section *s, const char *sym);
-static int put_elf_sym(Section *s, 
-                       unsigned long value, unsigned long size,
-                       int info, int other, int shndx, const char *name);
-static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
-                       int info, int other, int sh_num, const char *name);
-static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
-                          int type, int symbol);
-static void put_stabs(const char *str, int type, int other, int desc, 
-                      unsigned long value);
-static void put_stabs_r(const char *str, int type, int other, int desc, 
-                        unsigned long value, Section *sec, int sym_index);
-static void put_stabn(int type, int other, int desc, int value);
-static void put_stabd(int type, int other, int desc);
-static int tcc_add_dll(TCCState *s, const char *filename, int flags);
-
-#define AFF_PRINT_ERROR     0x0001 /* print error if file not found */
-#define AFF_REFERENCED_DLL  0x0002 /* load a referenced dll from another dll */
-#define AFF_PREPROCESS      0x0004 /* preprocess file */
-static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
-
-/* tcccoff.c */
-int tcc_output_coff(TCCState *s1, FILE *f);
-
-/* tccpe.c */
-void *resolve_sym(TCCState *s1, const char *sym, int type);
-int pe_load_def_file(struct TCCState *s1, int fd);
-int pe_test_res_file(void *v, int size);
-int pe_load_res_file(struct TCCState *s1, int fd);
-void pe_add_runtime(struct TCCState *s1);
-void pe_guess_outfile(char *objfilename, int output_type);
-int pe_output_file(struct TCCState *s1, const char *filename);
-
-/* tccasm.c */
-#ifdef CONFIG_TCC_ASM
-static void asm_expr(TCCState *s1, ExprValue *pe);
-static int asm_int_expr(TCCState *s1);
-static int find_constraint(ASMOperand *operands, int nb_operands, 
-                           const char *name, const char **pp);
-
-static int tcc_assemble(TCCState *s1, int do_preprocess);
-#endif
-
-static void asm_instr(void);
-static void asm_global_instr(void);
-
-/********************************************************/
-/* global variables */
-
-#ifdef TCC_TARGET_I386
-#include "i386-gen.c"
-#endif
-
-#ifdef TCC_TARGET_ARM
-#include "arm-gen.c"
-#endif
-
-#ifdef TCC_TARGET_C67
-#include "c67-gen.c"
-#endif
-
-#ifdef TCC_TARGET_X86_64
-#include "x86_64-gen.c"
-#endif
-
-#ifdef CONFIG_TCC_STATIC
-
-#define RTLD_LAZY       0x001
-#define RTLD_NOW        0x002
-#define RTLD_GLOBAL     0x100
-#define RTLD_DEFAULT    NULL
-
-/* dummy function for profiling */
-void *dlopen(const char *filename, int flag)
-{
-    return NULL;
-}
-
-void dlclose(void *p)
-{
-}
-
-const char *dlerror(void)
-{
-    return "error";
-}
-
-typedef struct TCCSyms {
-    char *str;
-    void *ptr;
-} TCCSyms;
-
-#define TCCSYM(a) { #a, &a, },
-
-/* add the symbol you want here if no dynamic linking is done */
-static TCCSyms tcc_syms[] = {
-#if !defined(CONFIG_TCCBOOT)
-    TCCSYM(printf)
-    TCCSYM(fprintf)
-    TCCSYM(fopen)
-    TCCSYM(fclose)
-#endif
-    { NULL, NULL },
-};
-
-void *resolve_sym(TCCState *s1, const char *symbol, int type)
-{
-    TCCSyms *p;
-    p = tcc_syms;
-    while (p->str != NULL) {
-        if (!strcmp(p->str, symbol))
-            return p->ptr;
-        p++;
-    }
-    return NULL;
-}
-
-#elif !defined(_WIN32)
-
-#include <dlfcn.h>
-
-void *resolve_sym(TCCState *s1, const char *sym, int type)
-{
-    return dlsym(RTLD_DEFAULT, sym);
-}
-
-#endif
-
-/********************************************************/
-
-/* we use our own 'finite' function to avoid potential problems with
-   non standard math libs */
-/* XXX: endianness dependent */
-int ieee_finite(double d)
-{
-    int *p = (int *)&d;
-    return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
-}
-
-/* copy a string and truncate it. */
-char *pstrcpy(char *buf, int buf_size, const char *s)
-{
-    char *q, *q_end;
-    int c;
-
-    if (buf_size > 0) {
-        q = buf;
-        q_end = buf + buf_size - 1;
-        while (q < q_end) {
-            c = *s++;
-            if (c == '\0')
-                break;
-            *q++ = c;
-        }
-        *q = '\0';
-    }
-    return buf;
-}
-
-/* strcat and truncate. */
-char *pstrcat(char *buf, int buf_size, const char *s)
-{
-    int len;
-    len = strlen(buf);
-    if (len < buf_size) 
-        pstrcpy(buf + len, buf_size - len, s);
-    return buf;
-}
-
-/* extract the basename of a file */
-char *tcc_basename(const char *name)
-{
-    char *p = strchr(name, 0);
-    while (p > name && !IS_PATHSEP(p[-1]))
-        --p;
-    return p;
-}
-
-char *tcc_fileextension (const char *name)
-{
-    char *b = tcc_basename(name);
-    char *e = strrchr(b, '.');
-    return e ? e : strchr(b, 0);
-}
-
-#ifdef _WIN32
-char *normalize_slashes(char *path)
-{
-    char *p;
-    for (p = path; *p; ++p)
-        if (*p == '\\')
-            *p = '/';
-    return path;
-}
-
-void tcc_set_lib_path_w32(TCCState *s)
-{
-    /* on win32, we suppose the lib and includes are at the location
-       of 'tcc.exe' */
-    char path[1024], *p;
-    GetModuleFileNameA(NULL, path, sizeof path);
-    p = tcc_basename(normalize_slashes(strlwr(path)));
-    if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
-        p -= 5;
-    else if (p > path)
-        p--;
-    *p = 0;
-    tcc_set_lib_path(s, path);
-}
-#endif
-
-void set_pages_executable(void *ptr, unsigned long length)
-{
-#ifdef _WIN32
-    unsigned long old_protect;
-    VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
-#else
-    unsigned long start, end;
-    start = (unsigned long)ptr & ~(PAGESIZE - 1);
-    end = (unsigned long)ptr + length;
-    end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
-    mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
-#endif            
-}
-
-/* memory management */
-#ifdef MEM_DEBUG
-int mem_cur_size;
-int mem_max_size;
-unsigned malloc_usable_size(void*);
-#endif
-
-void tcc_free(void *ptr)
-{
-#ifdef MEM_DEBUG
-    mem_cur_size -= malloc_usable_size(ptr);
-#endif
-    free(ptr);
-}
-
-void *tcc_malloc(unsigned long size)
-{
-    void *ptr;
-    ptr = malloc(size);
-    if (!ptr && size)
-        error("memory full");
-#ifdef MEM_DEBUG
-    mem_cur_size += malloc_usable_size(ptr);
-    if (mem_cur_size > mem_max_size)
-        mem_max_size = mem_cur_size;
-#endif
-    return ptr;
-}
-
-void *tcc_mallocz(unsigned long size)
-{
-    void *ptr;
-    ptr = tcc_malloc(size);
-    memset(ptr, 0, size);
-    return ptr;
-}
-
-void *tcc_realloc(void *ptr, unsigned long size)
-{
-    void *ptr1;
-#ifdef MEM_DEBUG
-    mem_cur_size -= malloc_usable_size(ptr);
-#endif
-    ptr1 = realloc(ptr, size);
-#ifdef MEM_DEBUG
-    /* NOTE: count not correct if alloc error, but not critical */
-    mem_cur_size += malloc_usable_size(ptr1);
-    if (mem_cur_size > mem_max_size)
-        mem_max_size = mem_cur_size;
-#endif
-    return ptr1;
-}
-
-char *tcc_strdup(const char *str)
-{
-    char *ptr;
-    ptr = tcc_malloc(strlen(str) + 1);
-    strcpy(ptr, str);
-    return ptr;
-}
-
-#define free(p) use_tcc_free(p)
-#define malloc(s) use_tcc_malloc(s)
-#define realloc(p, s) use_tcc_realloc(p, s)
-
-void dynarray_add(void ***ptab, int *nb_ptr, void *data)
-{
-    int nb, nb_alloc;
-    void **pp;
-    
-    nb = *nb_ptr;
-    pp = *ptab;
-    /* every power of two we double array size */
-    if ((nb & (nb - 1)) == 0) {
-        if (!nb)
-            nb_alloc = 1;
-        else
-            nb_alloc = nb * 2;
-        pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
-        if (!pp)
-            error("memory full");
-        *ptab = pp;
-    }
-    pp[nb++] = data;
-    *nb_ptr = nb;
-}
-
-void dynarray_reset(void *pp, int *n)
-{
-    void **p;
-    for (p = *(void***)pp; *n; ++p, --*n)
-        if (*p)
-            tcc_free(*p);
-    tcc_free(*(void**)pp);
-    *(void**)pp = NULL;
-}
-
-/* symbol allocator */
-static Sym *__sym_malloc(void)
-{
-    Sym *sym_pool, *sym, *last_sym;
-    int i;
-
-    sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
-    dynarray_add(&sym_pools, &nb_sym_pools, sym_pool);
-
-    last_sym = sym_free_first;
-    sym = sym_pool;
-    for(i = 0; i < SYM_POOL_NB; i++) {
-        sym->next = last_sym;
-        last_sym = sym;
-        sym++;
-    }
-    sym_free_first = last_sym;
-    return last_sym;
-}
-
-static inline Sym *sym_malloc(void)
-{
-    Sym *sym;
-    sym = sym_free_first;
-    if (!sym)
-        sym = __sym_malloc();
-    sym_free_first = sym->next;
-    return sym;
-}
-
-static inline void sym_free(Sym *sym)
-{
-    sym->next = sym_free_first;
-    sym_free_first = sym;
-}
-
-Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
-{
-    Section *sec;
-
-    sec = tcc_mallocz(sizeof(Section) + strlen(name));
-    strcpy(sec->name, name);
-    sec->sh_type = sh_type;
-    sec->sh_flags = sh_flags;
-    switch(sh_type) {
-    case SHT_HASH:
-    case SHT_REL:
-    case SHT_RELA:
-    case SHT_DYNSYM:
-    case SHT_SYMTAB:
-    case SHT_DYNAMIC:
-        sec->sh_addralign = 4;
-        break;
-    case SHT_STRTAB:
-        sec->sh_addralign = 1;
-        break;
-    default:
-        sec->sh_addralign = 32; /* default conservative alignment */
-        break;
-    }
-
-    if (sh_flags & SHF_PRIVATE) {
-        dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec);
-    } else {
-        sec->sh_num = s1->nb_sections;
-        dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
-    }
-
-    return sec;
-}
-
-static void free_section(Section *s)
-{
-    tcc_free(s->data);
-}
-
-/* realloc section and set its content to zero */
-static void section_realloc(Section *sec, unsigned long new_size)
-{
-    unsigned long size;
-    unsigned char *data;
-    
-    size = sec->data_allocated;
-    if (size == 0)
-        size = 1;
-    while (size < new_size)
-        size = size * 2;
-    data = tcc_realloc(sec->data, size);
-    if (!data)
-        error("memory full");
-    memset(data + sec->data_allocated, 0, size - sec->data_allocated);
-    sec->data = data;
-    sec->data_allocated = size;
-}
-
-/* reserve at least 'size' bytes in section 'sec' from
-   sec->data_offset. */
-static void *section_ptr_add(Section *sec, unsigned long size)
-{
-    unsigned long offset, offset1;
-
-    offset = sec->data_offset;
-    offset1 = offset + size;
-    if (offset1 > sec->data_allocated)
-        section_realloc(sec, offset1);
-    sec->data_offset = offset1;
-    return sec->data + offset;
-}
-
-/* return a reference to a section, and create it if it does not
-   exists */
-Section *find_section(TCCState *s1, const char *name)
-{
-    Section *sec;
-    int i;
-    for(i = 1; i < s1->nb_sections; i++) {
-        sec = s1->sections[i];
-        if (!strcmp(name, sec->name)) 
-            return sec;
-    }
-    /* sections are created as PROGBITS */
-    return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
-}
-
-/* update sym->c so that it points to an external symbol in section
-   'section' with value 'value' */
-static void put_extern_sym2(Sym *sym, Section *section, 
-                            unsigned long value, unsigned long size,
-                            int can_add_underscore)
-{
-    int sym_type, sym_bind, sh_num, info, other, attr;
-    ElfW(Sym) *esym;
-    const char *name;
-    char buf1[256];
-
-    if (section == NULL)
-        sh_num = SHN_UNDEF;
-    else if (section == SECTION_ABS) 
-        sh_num = SHN_ABS;
-    else
-        sh_num = section->sh_num;
-
-    other = attr = 0;
-
-    if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
-        sym_type = STT_FUNC;
-#ifdef TCC_TARGET_PE
-        if (sym->type.ref)
-            attr = sym->type.ref->r;
-        if (FUNC_EXPORT(attr))
-            other |= 1;
-        if (FUNC_CALL(attr) == FUNC_STDCALL)
-            other |= 2;
-#endif
-    } else {
-        sym_type = STT_OBJECT;
-    }
-
-    if (sym->type.t & VT_STATIC)
-        sym_bind = STB_LOCAL;
-    else
-        sym_bind = STB_GLOBAL;
-
-    if (!sym->c) {
-        name = get_tok_str(sym->v, NULL);
-#ifdef CONFIG_TCC_BCHECK
-        if (tcc_state->do_bounds_check) {
-            char buf[32];
-
-            /* XXX: avoid doing that for statics ? */
-            /* if bound checking is activated, we change some function
-               names by adding the "__bound" prefix */
-            switch(sym->v) {
-#if 0
-            /* XXX: we rely only on malloc hooks */
-            case TOK_malloc: 
-            case TOK_free: 
-            case TOK_realloc: 
-            case TOK_memalign: 
-            case TOK_calloc: 
-#endif
-            case TOK_memcpy: 
-            case TOK_memmove:
-            case TOK_memset:
-            case TOK_strlen:
-            case TOK_strcpy:
-            case TOK_alloca:
-                strcpy(buf, "__bound_");
-                strcat(buf, name);
-                name = buf;
-                break;
-            }
-        }
-#endif
-
-#ifdef TCC_TARGET_PE
-        if ((other & 2) && can_add_underscore) {
-            sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
-            name = buf1;
-        } else
-#endif
-        if (tcc_state->leading_underscore && can_add_underscore) {
-            buf1[0] = '_';
-            pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
-            name = buf1;
-        }
-        info = ELFW(ST_INFO)(sym_bind, sym_type);
-        sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
-    } else {
-        esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
-        esym->st_value = value;
-        esym->st_size = size;
-        esym->st_shndx = sh_num;
-        esym->st_other |= other;
-    }
-}
-
-static void put_extern_sym(Sym *sym, Section *section, 
-                           unsigned long value, unsigned long size)
-{
-    put_extern_sym2(sym, section, value, size, 1);
-}
-
-/* add a new relocation entry to symbol 'sym' in section 's' */
-static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
-{
-    if (!sym->c) 
-        put_extern_sym(sym, NULL, 0, 0);
-    /* now we can add ELF relocation info */
-    put_elf_reloc(symtab_section, s, offset, type, sym->c);
-}
-
-static inline int isid(int c)
-{
-    return (c >= 'a' && c <= 'z') ||
-        (c >= 'A' && c <= 'Z') ||
-        c == '_';
-}
-
-static inline int isnum(int c)
-{
-    return c >= '0' && c <= '9';
-}
-
-static inline int isoct(int c)
-{
-    return c >= '0' && c <= '7';
-}
-
-static inline int toup(int c)
-{
-    if (c >= 'a' && c <= 'z')
-        return c - 'a' + 'A';
-    else
-        return c;
-}
-
-static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
-{
-    int len;
-    len = strlen(buf);
-    vsnprintf(buf + len, buf_size - len, fmt, ap);
-}
-
-static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    strcat_vprintf(buf, buf_size, fmt, ap);
-    va_end(ap);
-}
-
-void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
-{
-    char buf[2048];
-    BufferedFile **f;
-    
-    buf[0] = '\0';
-    if (file) {
-        for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
-            strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n", 
-                          (*f)->filename, (*f)->line_num);
-        if (file->line_num > 0) {
-            strcat_printf(buf, sizeof(buf), 
-                          "%s:%d: ", file->filename, file->line_num);
-        } else {
-            strcat_printf(buf, sizeof(buf),
-                          "%s: ", file->filename);
-        }
-    } else {
-        strcat_printf(buf, sizeof(buf),
-                      "tcc: ");
-    }
-    if (is_warning)
-        strcat_printf(buf, sizeof(buf), "warning: ");
-    strcat_vprintf(buf, sizeof(buf), fmt, ap);
-
-    if (!s1->error_func) {
-        /* default case: stderr */
-        fprintf(stderr, "%s\n", buf);
-    } else {
-        s1->error_func(s1->error_opaque, buf);
-    }
-    if (!is_warning || s1->warn_error)
-        s1->nb_errors++;
-}
-
-void tcc_set_error_func(TCCState *s, void *error_opaque,
-                        void (*error_func)(void *opaque, const char *msg))
-{
-    s->error_opaque = error_opaque;
-    s->error_func = error_func;
-}
-
-/* error without aborting current compilation */
-void error_noabort(const char *fmt, ...)
-{
-    TCCState *s1 = tcc_state;
-    va_list ap;
-
-    va_start(ap, fmt);
-    error1(s1, 0, fmt, ap);
-    va_end(ap);
-}
-
-void error(const char *fmt, ...)
-{
-    TCCState *s1 = tcc_state;
-    va_list ap;
-
-    va_start(ap, fmt);
-    error1(s1, 0, fmt, ap);
-    va_end(ap);
-    /* better than nothing: in some cases, we accept to handle errors */
-    if (s1->error_set_jmp_enabled) {
-        longjmp(s1->error_jmp_buf, 1);
-    } else {
-        /* XXX: eliminate this someday */
-        exit(1);
-    }
-}
-
-void expect(const char *msg)
-{
-    error("%s expected", msg);
-}
-
-void warning(const char *fmt, ...)
-{
-    TCCState *s1 = tcc_state;
-    va_list ap;
-
-    if (s1->warn_none)
-        return;
-
-    va_start(ap, fmt);
-    error1(s1, 1, fmt, ap);
-    va_end(ap);
-}
-
-void skip(int c)
-{
-    if (tok != c)
-        error("'%c' expected", c);
-    next();
-}
-
-static void test_lvalue(void)
-{
-    if (!(vtop->r & VT_LVAL))
-        expect("lvalue");
-}
-
-/* CString handling */
-
-static void cstr_realloc(CString *cstr, int new_size)
-{
-    int size;
-    void *data;
-
-    size = cstr->size_allocated;
-    if (size == 0)
-        size = 8; /* no need to allocate a too small first string */
-    while (size < new_size)
-        size = size * 2;
-    data = tcc_realloc(cstr->data_allocated, size);
-    if (!data)
-        error("memory full");
-    cstr->data_allocated = data;
-    cstr->size_allocated = size;
-    cstr->data = data;
-}
-
-/* add a byte */
-static inline void cstr_ccat(CString *cstr, int ch)
-{
-    int size;
-    size = cstr->size + 1;
-    if (size > cstr->size_allocated)
-        cstr_realloc(cstr, size);
-    ((unsigned char *)cstr->data)[size - 1] = ch;
-    cstr->size = size;
-}
-
-static void cstr_cat(CString *cstr, const char *str)
-{
-    int c;
-    for(;;) {
-        c = *str;
-        if (c == '\0')
-            break;
-        cstr_ccat(cstr, c);
-        str++;
-    }
-}
-
-/* add a wide char */
-static void cstr_wccat(CString *cstr, int ch)
-{
-    int size;
-    size = cstr->size + sizeof(nwchar_t);
-    if (size > cstr->size_allocated)
-        cstr_realloc(cstr, size);
-    *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
-    cstr->size = size;
-}
-
-static void cstr_new(CString *cstr)
-{
-    memset(cstr, 0, sizeof(CString));
-}
-
-/* free string and reset it to NULL */
-static void cstr_free(CString *cstr)
-{
-    tcc_free(cstr->data_allocated);
-    cstr_new(cstr);
-}
-
-#define cstr_reset(cstr) cstr_free(cstr)
-
-/* XXX: unicode ? */
-static void add_char(CString *cstr, int c)
-{
-    if (c == '\'' || c == '\"' || c == '\\') {
-        /* XXX: could be more precise if char or string */
-        cstr_ccat(cstr, '\\');
-    }
-    if (c >= 32 && c <= 126) {
-        cstr_ccat(cstr, c);
-    } else {
-        cstr_ccat(cstr, '\\');
-        if (c == '\n') {
-            cstr_ccat(cstr, 'n');
-        } else {
-            cstr_ccat(cstr, '0' + ((c >> 6) & 7));
-            cstr_ccat(cstr, '0' + ((c >> 3) & 7));
-            cstr_ccat(cstr, '0' + (c & 7));
-        }
-    }
-}
-
-/* push, without hashing */
-static Sym *sym_push2(Sym **ps, int v, int t, long c)
-{
-    Sym *s;
-    s = sym_malloc();
-    s->v = v;
-    s->type.t = t;
-    s->c = c;
-    s->next = NULL;
-    /* add in stack */
-    s->prev = *ps;
-    *ps = s;
-    return s;
-}
-
-/* find a symbol and return its associated structure. 's' is the top
-   of the symbol stack */
-static Sym *sym_find2(Sym *s, int v)
-{
-    while (s) {
-        if (s->v == v)
-            return s;
-        s = s->prev;
-    }
-    return NULL;
-}
-
-/* structure lookup */
-static inline Sym *struct_find(int v)
-{
-    v -= TOK_IDENT;
-    if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
-        return NULL;
-    return table_ident[v]->sym_struct;
-}
-
-/* find an identifier */
-static inline Sym *sym_find(int v)
-{
-    v -= TOK_IDENT;
-    if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
-        return NULL;
-    return table_ident[v]->sym_identifier;
-}
-
-/* push a given symbol on the symbol stack */
-static Sym *sym_push(int v, CType *type, int r, int c)
-{
-    Sym *s, **ps;
-    TokenSym *ts;
-
-    if (local_stack)
-        ps = &local_stack;
-    else
-        ps = &global_stack;
-    s = sym_push2(ps, v, type->t, c);
-    s->type.ref = type->ref;
-    s->r = r;
-    /* don't record fields or anonymous symbols */
-    /* XXX: simplify */
-    if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
-        /* record symbol in token array */
-        ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
-        if (v & SYM_STRUCT)
-            ps = &ts->sym_struct;
-        else
-            ps = &ts->sym_identifier;
-        s->prev_tok = *ps;
-        *ps = s;
-    }
-    return s;
-}
-
-/* push a global identifier */
-static Sym *global_identifier_push(int v, int t, int c)
-{
-    Sym *s, **ps;
-    s = sym_push2(&global_stack, v, t, c);
-    /* don't record anonymous symbol */
-    if (v < SYM_FIRST_ANOM) {
-        ps = &table_ident[v - TOK_IDENT]->sym_identifier;
-        /* modify the top most local identifier, so that
-           sym_identifier will point to 's' when popped */
-        while (*ps != NULL)
-            ps = &(*ps)->prev_tok;
-        s->prev_tok = NULL;
-        *ps = s;
-    }
-    return s;
-}
-
-/* pop symbols until top reaches 'b' */
-static void sym_pop(Sym **ptop, Sym *b)
-{
-    Sym *s, *ss, **ps;
-    TokenSym *ts;
-    int v;
-
-    s = *ptop;
-    while(s != b) {
-        ss = s->prev;
-        v = s->v;
-        /* remove symbol in token array */
-        /* XXX: simplify */
-        if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
-            ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
-            if (v & SYM_STRUCT)
-                ps = &ts->sym_struct;
-            else
-                ps = &ts->sym_identifier;
-            *ps = s->prev_tok;
-        }
-        sym_free(s);
-        s = ss;
-    }
-    *ptop = b;
-}
-
-/* I/O layer */
-
-BufferedFile *tcc_open(TCCState *s1, const char *filename)
-{
-    int fd;
-    BufferedFile *bf;
-
-    if (strcmp(filename, "-") == 0)
-        fd = 0, filename = "stdin";
-    else
-        fd = open(filename, O_RDONLY | O_BINARY);
-    if ((s1->verbose == 2 && fd >= 0) || s1->verbose == 3)
-        printf("%s %*s%s\n", fd < 0 ? "nf":"->",
-               (s1->include_stack_ptr - s1->include_stack), "", filename);
-    if (fd < 0)
-        return NULL;
-    bf = tcc_malloc(sizeof(BufferedFile));
-    bf->fd = fd;
-    bf->buf_ptr = bf->buffer;
-    bf->buf_end = bf->buffer;
-    bf->buffer[0] = CH_EOB; /* put eob symbol */
-    pstrcpy(bf->filename, sizeof(bf->filename), filename);
-#ifdef _WIN32
-    normalize_slashes(bf->filename);
-#endif
-    bf->line_num = 1;
-    bf->ifndef_macro = 0;
-    bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
-    //    printf("opening '%s'\n", filename);
-    return bf;
-}
-
-void tcc_close(BufferedFile *bf)
-{
-    total_lines += bf->line_num;
-    close(bf->fd);
-    tcc_free(bf);
-}
-
-#include "tccpp.c"
-#include "tccgen.c"
-
-
-/* compile the C file opened in 'file'. Return non zero if errors. */
-static int tcc_compile(TCCState *s1)
-{
-    Sym *define_start;
-    char buf[512];
-    volatile int section_sym;
-
-#ifdef INC_DEBUG
-    printf("%s: **** new file\n", file->filename);
-#endif
-    preprocess_init(s1);
-
-    cur_text_section = NULL;
-    funcname = "";
-    anon_sym = SYM_FIRST_ANOM; 
-
-    /* file info: full path + filename */
-    section_sym = 0; /* avoid warning */
-    if (s1->do_debug) {
-        section_sym = put_elf_sym(symtab_section, 0, 0, 
-                                  ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, 
-                                  text_section->sh_num, NULL);
-        getcwd(buf, sizeof(buf));
-#ifdef _WIN32
-        normalize_slashes(buf);
-#endif
-        pstrcat(buf, sizeof(buf), "/");
-        put_stabs_r(buf, N_SO, 0, 0, 
-                    text_section->data_offset, text_section, section_sym);
-        put_stabs_r(file->filename, N_SO, 0, 0, 
-                    text_section->data_offset, text_section, section_sym);
-    }
-    /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
-       symbols can be safely used */
-    put_elf_sym(symtab_section, 0, 0, 
-                ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, 
-                SHN_ABS, file->filename);
-
-    /* define some often used types */
-    int_type.t = VT_INT;
-
-    char_pointer_type.t = VT_BYTE;
-    mk_pointer(&char_pointer_type);
-
-    func_old_type.t = VT_FUNC;
-    func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
-
-#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
-    float_type.t = VT_FLOAT;
-    double_type.t = VT_DOUBLE;
-
-    func_float_type.t = VT_FUNC;
-    func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
-    func_double_type.t = VT_FUNC;
-    func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
-#endif
-
-#if 0
-    /* define 'void *alloca(unsigned int)' builtin function */
-    {
-        Sym *s1;
-
-        p = anon_sym++;
-        sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
-        s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
-        s1->next = NULL;
-        sym->next = s1;
-        sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
-    }
-#endif
-
-    define_start = define_stack;
-    nocode_wanted = 1;
-
-    if (setjmp(s1->error_jmp_buf) == 0) {
-        s1->nb_errors = 0;
-        s1->error_set_jmp_enabled = 1;
-
-        ch = file->buf_ptr[0];
-        tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
-        parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
-        next();
-        decl(VT_CONST);
-        if (tok != TOK_EOF)
-            expect("declaration");
-
-        /* end of translation unit info */
-        if (s1->do_debug) {
-            put_stabs_r(NULL, N_SO, 0, 0, 
-                        text_section->data_offset, text_section, section_sym);
-        }
-    }
-    s1->error_set_jmp_enabled = 0;
-
-    /* reset define stack, but leave -Dsymbols (may be incorrect if
-       they are undefined) */
-    free_defines(define_start); 
-
-    gen_inline_functions();
-
-    sym_pop(&global_stack, NULL);
-    sym_pop(&local_stack, NULL);
-
-    return s1->nb_errors != 0 ? -1 : 0;
-}
-
-int tcc_compile_string(TCCState *s, const char *str)
-{
-    BufferedFile bf1, *bf = &bf1;
-    int ret, len;
-    char *buf;
-
-    /* init file structure */
-    bf->fd = -1;
-    /* XXX: avoid copying */
-    len = strlen(str);
-    buf = tcc_malloc(len + 1);
-    if (!buf)
-        return -1;
-    memcpy(buf, str, len);
-    buf[len] = CH_EOB;
-    bf->buf_ptr = buf;
-    bf->buf_end = buf + len;
-    pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
-    bf->line_num = 1;
-    file = bf;
-    ret = tcc_compile(s);
-    file = NULL;
-    tcc_free(buf);
-
-    /* currently, no need to close */
-    return ret;
-}
-
-/* define a preprocessor symbol. A value can also be provided with the '=' operator */
-void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
-{
-    BufferedFile bf1, *bf = &bf1;
-
-    pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
-    pstrcat(bf->buffer, IO_BUF_SIZE, " ");
-    /* default value */
-    if (!value) 
-        value = "1";
-    pstrcat(bf->buffer, IO_BUF_SIZE, value);
-    
-    /* init file structure */
-    bf->fd = -1;
-    bf->buf_ptr = bf->buffer;
-    bf->buf_end = bf->buffer + strlen(bf->buffer);
-    *bf->buf_end = CH_EOB;
-    bf->filename[0] = '\0';
-    bf->line_num = 1;
-    file = bf;
-    
-    s1->include_stack_ptr = s1->include_stack;
-
-    /* parse with define parser */
-    ch = file->buf_ptr[0];
-    next_nomacro();
-    parse_define();
-    file = NULL;
-}
-
-/* undefine a preprocessor symbol */
-void tcc_undefine_symbol(TCCState *s1, const char *sym)
-{
-    TokenSym *ts;
-    Sym *s;
-    ts = tok_alloc(sym, strlen(sym));
-    s = define_find(ts->tok);
-    /* undefine symbol by putting an invalid name */
-    if (s)
-        define_undef(s);
-}
-
-#ifdef CONFIG_TCC_ASM
-
-#ifdef TCC_TARGET_I386
-#include "i386-asm.c"
-#endif
-#include "tccasm.c"
-
-#else
-static void asm_instr(void)
-{
-    error("inline asm() not supported");
-}
-static void asm_global_instr(void)
-{
-    error("inline asm() not supported");
-}
-#endif
-
-#include "tccelf.c"
-
-#ifdef TCC_TARGET_COFF
-#include "tcccoff.c"
-#endif
-
-#ifdef TCC_TARGET_PE
-#include "tccpe.c"
-#endif
-
-#ifdef CONFIG_TCC_BACKTRACE
-/* print the position in the source file of PC value 'pc' by reading
-   the stabs debug information */
-static void rt_printline(unsigned long wanted_pc)
-{
-    Stab_Sym *sym, *sym_end;
-    char func_name[128], last_func_name[128];
-    unsigned long func_addr, last_pc, pc;
-    const char *incl_files[INCLUDE_STACK_SIZE];
-    int incl_index, len, last_line_num, i;
-    const char *str, *p;
-
-    fprintf(stderr, "0x%08lx:", wanted_pc);
-
-    func_name[0] = '\0';
-    func_addr = 0;
-    incl_index = 0;
-    last_func_name[0] = '\0';
-    last_pc = 0xffffffff;
-    last_line_num = 1;
-    sym = (Stab_Sym *)stab_section->data + 1;
-    sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
-    while (sym < sym_end) {
-        switch(sym->n_type) {
-            /* function start or end */
-        case N_FUN:
-            if (sym->n_strx == 0) {
-                /* we test if between last line and end of function */
-                pc = sym->n_value + func_addr;
-                if (wanted_pc >= last_pc && wanted_pc < pc)
-                    goto found;
-                func_name[0] = '\0';
-                func_addr = 0;
-            } else {
-                str = stabstr_section->data + sym->n_strx;
-                p = strchr(str, ':');
-                if (!p) {
-                    pstrcpy(func_name, sizeof(func_name), str);
-                } else {
-                    len = p - str;
-                    if (len > sizeof(func_name) - 1)
-                        len = sizeof(func_name) - 1;
-                    memcpy(func_name, str, len);
-                    func_name[len] = '\0';
-                }
-                func_addr = sym->n_value;
-            }
-            break;
-            /* line number info */
-        case N_SLINE:
-            pc = sym->n_value + func_addr;
-            if (wanted_pc >= last_pc && wanted_pc < pc)
-                goto found;
-            last_pc = pc;
-            last_line_num = sym->n_desc;
-            /* XXX: slow! */
-            strcpy(last_func_name, func_name);
-            break;
-            /* include files */
-        case N_BINCL:
-            str = stabstr_section->data + sym->n_strx;
-        add_incl:
-            if (incl_index < INCLUDE_STACK_SIZE) {
-                incl_files[incl_index++] = str;
-            }
-            break;
-        case N_EINCL:
-            if (incl_index > 1)
-                incl_index--;
-            break;
-        case N_SO:
-            if (sym->n_strx == 0) {
-                incl_index = 0; /* end of translation unit */
-            } else {
-                str = stabstr_section->data + sym->n_strx;
-                /* do not add path */
-                len = strlen(str);
-                if (len > 0 && str[len - 1] != '/')
-                    goto add_incl;
-            }
-            break;
-        }
-        sym++;
-    }
-
-    /* second pass: we try symtab symbols (no line number info) */
-    incl_index = 0;
-    {
-        ElfW(Sym) *sym, *sym_end;
-        int type;
-
-        sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
-        for(sym = (ElfW(Sym) *)symtab_section->data + 1; 
-            sym < sym_end;
-            sym++) {
-            type = ELFW(ST_TYPE)(sym->st_info);
-            if (type == STT_FUNC) {
-                if (wanted_pc >= sym->st_value &&
-                    wanted_pc < sym->st_value + sym->st_size) {
-                    pstrcpy(last_func_name, sizeof(last_func_name),
-                            strtab_section->data + sym->st_name);
-                    goto found;
-                }
-            }
-        }
-    }
-    /* did not find any info: */
-    fprintf(stderr, " ???\n");
-    return;
- found:
-    if (last_func_name[0] != '\0') {
-        fprintf(stderr, " %s()", last_func_name);
-    }
-    if (incl_index > 0) {
-        fprintf(stderr, " (%s:%d", 
-                incl_files[incl_index - 1], last_line_num);
-        for(i = incl_index - 2; i >= 0; i--)
-            fprintf(stderr, ", included from %s", incl_files[i]);
-        fprintf(stderr, ")");
-    }
-    fprintf(stderr, "\n");
-}
-
-#ifdef __i386__
-/* fix for glibc 2.1 */
-#ifndef REG_EIP
-#define REG_EIP EIP
-#define REG_EBP EBP
-#endif
-
-/* return the PC at frame level 'level'. Return non zero if not found */
-static int rt_get_caller_pc(unsigned long *paddr, 
-                            ucontext_t *uc, int level)
-{
-    unsigned long fp;
-    int i;
-
-    if (level == 0) {
-#if defined(__FreeBSD__)
-        *paddr = uc->uc_mcontext.mc_eip;
-#elif defined(__dietlibc__)
-        *paddr = uc->uc_mcontext.eip;
-#elif defined(__APPLE__)
-		fp = uc->uc_mcontext->__ss.__eip;
-#else
-        *paddr = uc->uc_mcontext.gregs[REG_EIP];
-#endif
-        return 0;
-    } else {
-#if defined(__FreeBSD__) 
-        fp = uc->uc_mcontext.mc_ebp;
-#elif defined(__dietlibc__)
-        fp = uc->uc_mcontext.ebp;
-#elif defined(__APPLE__)
-		fp = uc->uc_mcontext->__ss.__ebp;
-#else
-        fp = uc->uc_mcontext.gregs[REG_EBP];
-#endif
-        for(i=1;i<level;i++) {
-            /* XXX: check address validity with program info */
-            if (fp <= 0x1000 || fp >= 0xc0000000)
-                return -1;
-            fp = ((unsigned long *)fp)[0];
-        }
-        *paddr = ((unsigned long *)fp)[1];
-        return 0;
-    }
-}
-#elif defined(__x86_64__)
-/* return the PC at frame level 'level'. Return non zero if not found */
-static int rt_get_caller_pc(unsigned long *paddr,
-                            ucontext_t *uc, int level)
-{
-    unsigned long fp;
-    int i;
-
-    if (level == 0) {
-        /* XXX: only support linux */
-        *paddr = uc->uc_mcontext.gregs[REG_RIP];
-        return 0;
-    } else {
-        fp = uc->uc_mcontext.gregs[REG_RBP];
-        for(i=1;i<level;i++) {
-            /* XXX: check address validity with program info */
-            if (fp <= 0x1000)
-                return -1;
-            fp = ((unsigned long *)fp)[0];
-        }
-        *paddr = ((unsigned long *)fp)[1];
-        return 0;
-    }
-}
-#else
-#warning add arch specific rt_get_caller_pc()
-static int rt_get_caller_pc(unsigned long *paddr,
-                            ucontext_t *uc, int level)
-{
-    return -1;
-}
-#endif
-
-/* emit a run time error at position 'pc' */
-void rt_error(ucontext_t *uc, const char *fmt, ...)
-{
-    va_list ap;
-    unsigned long pc;
-    int i;
-
-    va_start(ap, fmt);
-    fprintf(stderr, "Runtime error: ");
-    vfprintf(stderr, fmt, ap);
-    fprintf(stderr, "\n");
-    for(i=0;i<num_callers;i++) {
-        if (rt_get_caller_pc(&pc, uc, i) < 0)
-            break;
-        if (i == 0)
-            fprintf(stderr, "at ");
-        else
-            fprintf(stderr, "by ");
-        rt_printline(pc);
-    }
-    exit(255);
-    va_end(ap);
-}
-
-/* signal handler for fatal errors */
-static void sig_error(int signum, siginfo_t *siginf, void *puc)
-{
-    ucontext_t *uc = puc;
-
-    switch(signum) {
-    case SIGFPE:
-        switch(siginf->si_code) {
-        case FPE_INTDIV:
-        case FPE_FLTDIV:
-            rt_error(uc, "division by zero");
-            break;
-        default:
-            rt_error(uc, "floating point exception");
-            break;
-        }
-        break;
-    case SIGBUS:
-    case SIGSEGV:
-        if (rt_bound_error_msg && *rt_bound_error_msg)
-            rt_error(uc, *rt_bound_error_msg);
-        else
-            rt_error(uc, "dereferencing invalid pointer");
-        break;
-    case SIGILL:
-        rt_error(uc, "illegal instruction");
-        break;
-    case SIGABRT:
-        rt_error(uc, "abort() called");
-        break;
-    default:
-        rt_error(uc, "caught signal %d", signum);
-        break;
-    }
-    exit(255);
-}
-
-#endif
-
-/* copy code into memory passed in by the caller and do all relocations
-   (needed before using tcc_get_symbol()).
-   returns -1 on error and required size if ptr is NULL */
-int tcc_relocate(TCCState *s1, void *ptr)
-{
-    Section *s;
-    unsigned long offset, length, mem;
-    int i;
-
-    if (0 == s1->runtime_added) {
-        s1->runtime_added = 1;
-        s1->nb_errors = 0;
-#ifdef TCC_TARGET_PE
-        pe_add_runtime(s1);
-        relocate_common_syms();
-        tcc_add_linker_symbols(s1);
-#else
-        tcc_add_runtime(s1);
-        relocate_common_syms();
-        tcc_add_linker_symbols(s1);
-        build_got_entries(s1);
-#endif
-    }
-
-    offset = 0, mem = (unsigned long)ptr;
-    for(i = 1; i < s1->nb_sections; i++) {
-        s = s1->sections[i];
-        if (0 == (s->sh_flags & SHF_ALLOC))
-            continue;
-        length = s->data_offset;
-        s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0;
-        offset = (offset + length + 15) & ~15;
-    }
-
-    /* relocate symbols */
-    relocate_syms(s1, 1);
-    if (s1->nb_errors)
-        return -1;
-
-#ifdef TCC_TARGET_X86_64
-    s1->runtime_plt_and_got_offset = 0;
-    s1->runtime_plt_and_got = (char *)(mem + offset);
-    /* double the size of the buffer for got and plt entries
-       XXX: calculate exact size for them? */
-    offset *= 2;
-#endif
-
-    if (0 == mem)
-        return offset + 15;
-
-    /* relocate each section */
-    for(i = 1; i < s1->nb_sections; i++) {
-        s = s1->sections[i];
-        if (s->reloc)
-            relocate_section(s1, s);
-    }
-
-    for(i = 1; i < s1->nb_sections; i++) {
-        s = s1->sections[i];
-        if (0 == (s->sh_flags & SHF_ALLOC))
-            continue;
-        length = s->data_offset;
-        // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
-        ptr = (void*)s->sh_addr;
-        if (NULL == s->data || s->sh_type == SHT_NOBITS)
-            memset(ptr, 0, length);
-        else
-            memcpy(ptr, s->data, length);
-        /* mark executable sections as executable in memory */
-        if (s->sh_flags & SHF_EXECINSTR)
-            set_pages_executable(ptr, length);
-    }
-#ifdef TCC_TARGET_X86_64
-    set_pages_executable(s1->runtime_plt_and_got,
-                         s1->runtime_plt_and_got_offset);
-#endif
-    return 0;
-}
-
-/* launch the compiled program with the given arguments */
-int tcc_run(TCCState *s1, int argc, char **argv)
-{
-    int (*prog_main)(int, char **);
-    void *ptr;
-    int ret;
-
-    ret = tcc_relocate(s1, NULL);
-    if (ret < 0)
-        return -1;
-    ptr = tcc_malloc(ret);
-    tcc_relocate(s1, ptr);
-
-    prog_main = tcc_get_symbol_err(s1, "main");
-    
-    if (s1->do_debug) {
-#ifdef CONFIG_TCC_BACKTRACE
-        struct sigaction sigact;
-        /* install TCC signal handlers to print debug info on fatal
-           runtime errors */
-        sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
-        sigact.sa_sigaction = sig_error;
-        sigemptyset(&sigact.sa_mask);
-        sigaction(SIGFPE, &sigact, NULL);
-        sigaction(SIGILL, &sigact, NULL);
-        sigaction(SIGSEGV, &sigact, NULL);
-        sigaction(SIGBUS, &sigact, NULL);
-        sigaction(SIGABRT, &sigact, NULL);
-#else        
-        error("debug mode not available");
-#endif
-    }
-
-#ifdef CONFIG_TCC_BCHECK
-    if (s1->do_bounds_check) {
-        void (*bound_init)(void);
-
-        /* set error function */
-        rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
-
-        /* XXX: use .init section so that it also work in binary ? */
-        bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
-        bound_init();
-    }
-#endif
-    ret = (*prog_main)(argc, argv);
-    tcc_free(ptr);
-    return ret;
-}
-
-void tcc_memstats(void)
-{
-#ifdef MEM_DEBUG
-    printf("memory in use: %d\n", mem_cur_size);
-#endif
-}
-
-static void tcc_cleanup(void)
-{
-    int i, n;
-
-    if (NULL == tcc_state)
-        return;
-    tcc_state = NULL;
-
-    /* free -D defines */
-    free_defines(NULL);
-
-    /* free tokens */
-    n = tok_ident - TOK_IDENT;
-    for(i = 0; i < n; i++)
-        tcc_free(table_ident[i]);
-    tcc_free(table_ident);
-
-    /* free sym_pools */
-    dynarray_reset(&sym_pools, &nb_sym_pools);
-    /* string buffer */
-    cstr_free(&tokcstr);
-    /* reset symbol stack */
-    sym_free_first = NULL;
-    /* cleanup from error/setjmp */
-    macro_ptr = NULL;
-}
-
-TCCState *tcc_new(void)
-{
-    TCCState *s;
-
-    tcc_cleanup();
-
-    s = tcc_mallocz(sizeof(TCCState));
-    if (!s)
-        return NULL;
-    tcc_state = s;
-    s->output_type = TCC_OUTPUT_MEMORY;
-    s->tcc_lib_path = CONFIG_TCCDIR;
-
-    preprocess_new();
-
-    /* we add dummy defines for some special macros to speed up tests
-       and to have working defined() */
-    define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
-    define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
-    define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
-    define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
-
-    /* standard defines */
-    tcc_define_symbol(s, "__STDC__", NULL);
-    tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
-#if defined(TCC_TARGET_I386)
-    tcc_define_symbol(s, "__i386__", NULL);
-#endif
-#if defined(TCC_TARGET_X86_64)
-    tcc_define_symbol(s, "__x86_64__", NULL);
-#endif
-#if defined(TCC_TARGET_ARM)
-    tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
-    tcc_define_symbol(s, "__arm_elf__", NULL);
-    tcc_define_symbol(s, "__arm_elf", NULL);
-    tcc_define_symbol(s, "arm_elf", NULL);
-    tcc_define_symbol(s, "__arm__", NULL);
-    tcc_define_symbol(s, "__arm", NULL);
-    tcc_define_symbol(s, "arm", NULL);
-    tcc_define_symbol(s, "__APCS_32__", NULL);
-#endif
-#ifdef TCC_TARGET_PE
-    tcc_define_symbol(s, "_WIN32", NULL);
-#else
-    tcc_define_symbol(s, "__unix__", NULL);
-    tcc_define_symbol(s, "__unix", NULL);
-#if defined(__linux)
-    tcc_define_symbol(s, "__linux__", NULL);
-    tcc_define_symbol(s, "__linux", NULL);
-#endif
-#endif
-    /* tiny C specific defines */
-    tcc_define_symbol(s, "__TINYC__", NULL);
-
-    /* tiny C & gcc defines */
-    tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
-    tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
-#ifdef TCC_TARGET_PE
-    tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
-#else
-    tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
-#endif
-    
-#ifndef TCC_TARGET_PE
-    /* default library paths */
-    tcc_add_library_path(s, CONFIG_SYSROOT "/usr/local/lib");
-    tcc_add_library_path(s, CONFIG_SYSROOT "/usr/lib");
-    tcc_add_library_path(s, CONFIG_SYSROOT "/lib");
-#endif
-
-    /* no section zero */
-    dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
-
-    /* create standard sections */
-    text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
-    data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
-    bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
-
-    /* symbols are always generated for linking stage */
-    symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
-                                ".strtab",
-                                ".hashtab", SHF_PRIVATE); 
-    strtab_section = symtab_section->link;
-    
-    /* private symbol table for dynamic symbols */
-    s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
-                                      ".dynstrtab", 
-                                      ".dynhashtab", SHF_PRIVATE);
-    s->alacarte_link = 1;
-
-#ifdef CHAR_IS_UNSIGNED
-    s->char_is_unsigned = 1;
-#endif
-#if defined(TCC_TARGET_PE) && 0
-    /* XXX: currently the PE linker is not ready to support that */
-    s->leading_underscore = 1;
-#endif
-    return s;
-}
-
-void tcc_delete(TCCState *s1)
-{
-    int i;
-
-    tcc_cleanup();
-
-    /* free all sections */
-    for(i = 1; i < s1->nb_sections; i++)
-        free_section(s1->sections[i]);
-    dynarray_reset(&s1->sections, &s1->nb_sections);
-
-    for(i = 0; i < s1->nb_priv_sections; i++)
-        free_section(s1->priv_sections[i]);
-    dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
-        
-    /* free any loaded DLLs */
-    for ( i = 0; i < s1->nb_loaded_dlls; i++) {
-        DLLReference *ref = s1->loaded_dlls[i];
-        if ( ref->handle )
-            dlclose(ref->handle);
-    }
-    
-    /* free loaded dlls array */
-    dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
-
-    /* free library paths */
-    dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
-
-    /* free include paths */
-    dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
-    dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
-    dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
-
-    tcc_free(s1);
-}
-
-int tcc_add_include_path(TCCState *s1, const char *pathname)
-{
-    char *pathname1;
-    
-    pathname1 = tcc_strdup(pathname);
-    dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
-    return 0;
-}
-
-int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
-{
-    char *pathname1;
-    
-    pathname1 = tcc_strdup(pathname);
-    dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
-    return 0;
-}
-
-static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
-{
-    const char *ext;
-    ElfW(Ehdr) ehdr;
-    int fd, ret;
-    BufferedFile *saved_file;
-
-    /* find source file type with extension */
-    ext = tcc_fileextension(filename);
-    if (ext[0])
-        ext++;
-
-    /* open the file */
-    saved_file = file;
-    file = tcc_open(s1, filename);
-    if (!file) {
-        if (flags & AFF_PRINT_ERROR) {
-            error_noabort("file '%s' not found", filename);
-        }
-        ret = -1;
-        goto fail1;
-    }
-
-    if (flags & AFF_PREPROCESS) {
-        ret = tcc_preprocess(s1);
-    } else if (!ext[0] || !PATHCMP(ext, "c")) {
-        /* C file assumed */
-        ret = tcc_compile(s1);
-    } else 
-#ifdef CONFIG_TCC_ASM
-    if (!strcmp(ext, "S")) {
-        /* preprocessed assembler */
-        ret = tcc_assemble(s1, 1);
-    } else if (!strcmp(ext, "s")) {
-        /* non preprocessed assembler */
-        ret = tcc_assemble(s1, 0);
-    } else 
-#endif
-#ifdef TCC_TARGET_PE
-    if (!PATHCMP(ext, "def")) {
-        ret = pe_load_def_file(s1, file->fd);
-    } else
-#endif
-    {
-        fd = file->fd;
-        /* assume executable format: auto guess file type */
-        ret = read(fd, &ehdr, sizeof(ehdr));
-        lseek(fd, 0, SEEK_SET);
-        if (ret <= 0) {
-            error_noabort("could not read header");
-            goto fail;
-        } else if (ret != sizeof(ehdr)) {
-            goto try_load_script;
-        }
-
-        if (ehdr.e_ident[0] == ELFMAG0 &&
-            ehdr.e_ident[1] == ELFMAG1 &&
-            ehdr.e_ident[2] == ELFMAG2 &&
-            ehdr.e_ident[3] == ELFMAG3) {
-            file->line_num = 0; /* do not display line number if error */
-            if (ehdr.e_type == ET_REL) {
-                ret = tcc_load_object_file(s1, fd, 0);
-            } else if (ehdr.e_type == ET_DYN) {
-                if (s1->output_type == TCC_OUTPUT_MEMORY) {
-#ifdef TCC_TARGET_PE
-                    ret = -1;
-#else
-                    void *h;
-                    h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
-                    if (h)
-                        ret = 0;
-                    else
-                        ret = -1;
-#endif
-                } else {
-                    ret = tcc_load_dll(s1, fd, filename, 
-                                       (flags & AFF_REFERENCED_DLL) != 0);
-                }
-            } else {
-                error_noabort("unrecognized ELF file");
-                goto fail;
-            }
-        } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
-            file->line_num = 0; /* do not display line number if error */
-            ret = tcc_load_archive(s1, fd);
-        } else 
-#ifdef TCC_TARGET_COFF
-        if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
-            ret = tcc_load_coff(s1, fd);
-        } else
-#endif
-#ifdef TCC_TARGET_PE
-        if (pe_test_res_file(&ehdr, ret)) {
-            ret = pe_load_res_file(s1, fd);
-        } else
-#endif
-        {
-            /* as GNU ld, consider it is an ld script if not recognized */
-        try_load_script:
-            ret = tcc_load_ldscript(s1);
-            if (ret < 0) {
-                error_noabort("unrecognized file type");
-                goto fail;
-            }
-        }
-    }
- the_end:
-    tcc_close(file);
- fail1:
-    file = saved_file;
-    return ret;
- fail:
-    ret = -1;
-    goto the_end;
-}
-
-int tcc_add_file(TCCState *s, const char *filename)
-{
-    if (s->output_type == TCC_OUTPUT_PREPROCESS)
-        return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR | AFF_PREPROCESS);
-    else
-        return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
-}
-
-int tcc_add_library_path(TCCState *s, const char *pathname)
-{
-    char *pathname1;
-    
-    pathname1 = tcc_strdup(pathname);
-    dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
-    return 0;
-}
-
-/* find and load a dll. Return non zero if not found */
-/* XXX: add '-rpath' option support ? */
-static int tcc_add_dll(TCCState *s, const char *filename, int flags)
-{
-    char buf[1024];
-    int i;
-
-    for(i = 0; i < s->nb_library_paths; i++) {
-        snprintf(buf, sizeof(buf), "%s/%s", 
-                 s->library_paths[i], filename);
-        if (tcc_add_file_internal(s, buf, flags) == 0)
-            return 0;
-    }
-    return -1;
-}
-
-/* the library name is the same as the argument of the '-l' option */
-int tcc_add_library(TCCState *s, const char *libraryname)
-{
-    char buf[1024];
-    int i;
-    
-    /* first we look for the dynamic library if not static linking */
-    if (!s->static_link) {
-#ifdef TCC_TARGET_PE
-        snprintf(buf, sizeof(buf), "%s.def", libraryname);
-#else
-        snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
-#endif
-        if (tcc_add_dll(s, buf, 0) == 0)
-            return 0;
-    }
-
-    /* then we look for the static library */
-    for(i = 0; i < s->nb_library_paths; i++) {
-        snprintf(buf, sizeof(buf), "%s/lib%s.a", 
-                 s->library_paths[i], libraryname);
-        if (tcc_add_file_internal(s, buf, 0) == 0)
-            return 0;
-    }
-    return -1;
-}
-
-int tcc_add_symbol(TCCState *s, const char *name, void *val)
-{
-    add_elf_sym(symtab_section, (unsigned long)val, 0, 
-                ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
-                SHN_ABS, name);
-    return 0;
-}
-
-int tcc_set_output_type(TCCState *s, int output_type)
-{
-    char buf[1024];
-
-    s->output_type = output_type;
-
-    if (!s->nostdinc) {
-        /* default include paths */
-        /* XXX: reverse order needed if -isystem support */
-#ifndef TCC_TARGET_PE
-        tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/local/include");
-        tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/include");
-#endif
-        snprintf(buf, sizeof(buf), "%s/include", s->tcc_lib_path);
-        tcc_add_sysinclude_path(s, buf);
-#ifdef TCC_TARGET_PE
-        snprintf(buf, sizeof(buf), "%s/include/winapi", s->tcc_lib_path);
-        tcc_add_sysinclude_path(s, buf);
-#endif
-    }
-
-    /* if bound checking, then add corresponding sections */
-#ifdef CONFIG_TCC_BCHECK
-    if (s->do_bounds_check) {
-        /* define symbol */
-        tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
-        /* create bounds sections */
-        bounds_section = new_section(s, ".bounds", 
-                                     SHT_PROGBITS, SHF_ALLOC);
-        lbounds_section = new_section(s, ".lbounds", 
-                                      SHT_PROGBITS, SHF_ALLOC);
-    }
-#endif
-
-    if (s->char_is_unsigned) {
-        tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
-    }
-
-    /* add debug sections */
-    if (s->do_debug) {
-        /* stab symbols */
-        stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
-        stab_section->sh_entsize = sizeof(Stab_Sym);
-        stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
-        put_elf_str(stabstr_section, "");
-        stab_section->link = stabstr_section;
-        /* put first entry */
-        put_stabs("", 0, 0, 0, 0);
-    }
-
-    /* add libc crt1/crti objects */
-#ifndef TCC_TARGET_PE
-    if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
-        !s->nostdlib) {
-        if (output_type != TCC_OUTPUT_DLL)
-            tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
-        tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
-    }
-#endif
-
-#ifdef TCC_TARGET_PE
-    snprintf(buf, sizeof(buf), "%s/lib", s->tcc_lib_path);
-    tcc_add_library_path(s, buf);
-#endif
-
-    return 0;
-}
-
-#define WD_ALL    0x0001 /* warning is activated when using -Wall */
-#define FD_INVERT 0x0002 /* invert value before storing */
-
-typedef struct FlagDef {
-    uint16_t offset;
-    uint16_t flags;
-    const char *name;
-} FlagDef;
-
-static const FlagDef warning_defs[] = {
-    { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
-    { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
-    { offsetof(TCCState, warn_error), 0, "error" },
-    { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
-      "implicit-function-declaration" },
-};
-
-static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
-                    const char *name, int value)
-{
-    int i;
-    const FlagDef *p;
-    const char *r;
-
-    r = name;
-    if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
-        r += 3;
-        value = !value;
-    }
-    for(i = 0, p = flags; i < nb_flags; i++, p++) {
-        if (!strcmp(r, p->name))
-            goto found;
-    }
-    return -1;
- found:
-    if (p->flags & FD_INVERT)
-        value = !value;
-    *(int *)((uint8_t *)s + p->offset) = value;
-    return 0;
-}
-
-
-/* set/reset a warning */
-int tcc_set_warning(TCCState *s, const char *warning_name, int value)
-{
-    int i;
-    const FlagDef *p;
-
-    if (!strcmp(warning_name, "all")) {
-        for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
-            if (p->flags & WD_ALL)
-                *(int *)((uint8_t *)s + p->offset) = 1;
-        }
-        return 0;
-    } else {
-        return set_flag(s, warning_defs, countof(warning_defs),
-                        warning_name, value);
-    }
-}
-
-static const FlagDef flag_defs[] = {
-    { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
-    { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
-    { offsetof(TCCState, nocommon), FD_INVERT, "common" },
-    { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
-};
-
-/* set/reset a flag */
-int tcc_set_flag(TCCState *s, const char *flag_name, int value)
-{
-    return set_flag(s, flag_defs, countof(flag_defs),
-                    flag_name, value);
-}
-
-/* set CONFIG_TCCDIR at runtime */
-void tcc_set_lib_path(TCCState *s, const char *path)
-{
-    s->tcc_lib_path = tcc_strdup(path);
-}
-
-void tcc_print_stats(TCCState *s, int64_t total_time)
-{
-    double tt;
-    tt = (double)total_time / 1000000.0;
-    if (tt < 0.001)
-        tt = 0.001;
-    if (total_bytes < 1)
-        total_bytes = 1;
-    printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n", 
-           tok_ident - TOK_IDENT, total_lines, total_bytes,
-           tt, (int)(total_lines / tt),
-           total_bytes / tt / 1000000.0);
-}

+ 0 - 108
src/modules/native/tcc/libtcc/libtcc.h

@@ -1,108 +0,0 @@
-#ifndef LIBTCC_H
-#define LIBTCC_H
-
-#ifdef LIBTCC_AS_DLL
-#define LIBTCCAPI __declspec(dllexport)
-#else
-#define LIBTCCAPI
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct TCCState;
-
-typedef struct TCCState TCCState;
-
-/* create a new TCC compilation context */
-LIBTCCAPI TCCState *tcc_new(void);
-
-/* free a TCC compilation context */
-LIBTCCAPI void tcc_delete(TCCState *s);
-
-/* add debug information in the generated code */
-LIBTCCAPI void tcc_enable_debug(TCCState *s);
-
-/* set error/warning display callback */
-LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
-                        void (*error_func)(void *opaque, const char *msg));
-
-/* set/reset a warning */
-LIBTCCAPI int tcc_set_warning(TCCState *s, const char *warning_name, int value);
-
-/*****************************/
-/* preprocessor */
-
-/* add include path */
-LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname);
-
-/* add in system include path */
-LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
-
-/* define preprocessor symbol 'sym'. Can put optional value */
-LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
-
-/* undefine preprocess symbol 'sym' */
-LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
-
-/*****************************/
-/* compiling */
-
-/* add a file (either a C file, dll, an object, a library or an ld
-   script). Return -1 if error. */
-LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
-
-/* compile a string containing a C source. Return non zero if
-   error. */
-LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
-
-/*****************************/
-/* linking commands */
-
-/* set output type. MUST BE CALLED before any compilation */
-#define TCC_OUTPUT_MEMORY   0 /* output will be ran in memory (no
-                                 output file) (default) */
-#define TCC_OUTPUT_EXE      1 /* executable file */
-#define TCC_OUTPUT_DLL      2 /* dynamic library */
-#define TCC_OUTPUT_OBJ      3 /* object file */
-#define TCC_OUTPUT_PREPROCESS 4 /* preprocessed file (used internally) */
-LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
-
-#define TCC_OUTPUT_FORMAT_ELF    0 /* default output format: ELF */
-#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
-#define TCC_OUTPUT_FORMAT_COFF   2 /* COFF */
-
-/* equivalent to -Lpath option */
-LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
-
-/* the library name is the same as the argument of the '-l' option */
-LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname);
-
-/* add a symbol to the compiled program */
-LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, void *val);
-
-/* output an executable, library or object file. DO NOT call
-   tcc_relocate() before. */
-LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
-
-/* link and run main() function and return its value. DO NOT call
-   tcc_relocate() before. */
-LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
-
-/* copy code into memory passed in by the caller and do all relocations
-   (needed before using tcc_get_symbol()).
-   returns -1 on error and required size if ptr is NULL */
-LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
-
-/* return symbol value or NULL if not found */
-LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
-
-/* set CONFIG_TCCDIR at runtime */
-LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 0 - 234
src/modules/native/tcc/libtcc/stab.def

@@ -1,234 +0,0 @@
-/* Table of DBX symbol codes for the GNU system.
-   Copyright (C) 1988, 1997 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-/* This contains contribution from Cygnus Support.  */
-
-/* Global variable.  Only the name is significant.
-   To find the address, look in the corresponding external symbol.  */
-__define_stab (N_GSYM, 0x20, "GSYM")
-
-/* Function name for BSD Fortran.  Only the name is significant.
-   To find the address, look in the corresponding external symbol.  */
-__define_stab (N_FNAME, 0x22, "FNAME")
-
-/* Function name or text-segment variable for C.  Value is its address.
-   Desc is supposedly starting line number, but GCC doesn't set it
-   and DBX seems not to miss it.  */
-__define_stab (N_FUN, 0x24, "FUN")
-
-/* Data-segment variable with internal linkage.  Value is its address.
-   "Static Sym".  */
-__define_stab (N_STSYM, 0x26, "STSYM")
-
-/* BSS-segment variable with internal linkage.  Value is its address.  */
-__define_stab (N_LCSYM, 0x28, "LCSYM")
-
-/* Name of main routine.  Only the name is significant.
-   This is not used in C.  */
-__define_stab (N_MAIN, 0x2a, "MAIN")
-
-/* Global symbol in Pascal.
-   Supposedly the value is its line number; I'm skeptical.  */
-__define_stab (N_PC, 0x30, "PC")
-
-/* Number of symbols:  0, files,,funcs,lines according to Ultrix V4.0. */
-__define_stab (N_NSYMS, 0x32, "NSYMS")
-
-/* "No DST map for sym: name, ,0,type,ignored"  according to Ultrix V4.0. */
-__define_stab (N_NOMAP, 0x34, "NOMAP")
-
-/* New stab from Solaris.  I don't know what it means, but it
-   don't seem to contain useful information.  */
-__define_stab (N_OBJ, 0x38, "OBJ")
-
-/* New stab from Solaris.  I don't know what it means, but it
-   don't seem to contain useful information.  Possibly related to the
-   optimization flags used in this module.  */
-__define_stab (N_OPT, 0x3c, "OPT")
-
-/* Register variable.  Value is number of register.  */
-__define_stab (N_RSYM, 0x40, "RSYM")
-
-/* Modula-2 compilation unit.  Can someone say what info it contains?  */
-__define_stab (N_M2C, 0x42, "M2C")
-
-/* Line number in text segment.  Desc is the line number;
-   value is corresponding address.  */
-__define_stab (N_SLINE, 0x44, "SLINE")
-
-/* Similar, for data segment.  */
-__define_stab (N_DSLINE, 0x46, "DSLINE")
-
-/* Similar, for bss segment.  */
-__define_stab (N_BSLINE, 0x48, "BSLINE")
-
-/* Sun's source-code browser stabs.  ?? Don't know what the fields are.
-   Supposedly the field is "path to associated .cb file".  THIS VALUE
-   OVERLAPS WITH N_BSLINE!  */
-__define_stab (N_BROWS, 0x48, "BROWS")
-
-/* GNU Modula-2 definition module dependency.  Value is the modification time
-   of the definition file.  Other is non-zero if it is imported with the
-   GNU M2 keyword %INITIALIZE.  Perhaps N_M2C can be used if there
-   are enough empty fields? */
-__define_stab(N_DEFD, 0x4a, "DEFD")
-
-/* THE FOLLOWING TWO STAB VALUES CONFLICT.  Happily, one is for Modula-2
-   and one is for C++.   Still,... */
-/* GNU C++ exception variable.  Name is variable name.  */
-__define_stab (N_EHDECL, 0x50, "EHDECL")
-/* Modula2 info "for imc":  name,,0,0,0  according to Ultrix V4.0.  */
-__define_stab (N_MOD2, 0x50, "MOD2")
-
-/* GNU C++ `catch' clause.  Value is its address.  Desc is nonzero if
-   this entry is immediately followed by a CAUGHT stab saying what exception
-   was caught.  Multiple CAUGHT stabs means that multiple exceptions
-   can be caught here.  If Desc is 0, it means all exceptions are caught
-   here.  */
-__define_stab (N_CATCH, 0x54, "CATCH")
-
-/* Structure or union element.  Value is offset in the structure.  */
-__define_stab (N_SSYM, 0x60, "SSYM")
-
-/* Name of main source file.
-   Value is starting text address of the compilation.  */
-__define_stab (N_SO, 0x64, "SO")
-
-/* Automatic variable in the stack.  Value is offset from frame pointer.
-   Also used for type descriptions.  */
-__define_stab (N_LSYM, 0x80, "LSYM")
-
-/* Beginning of an include file.  Only Sun uses this.
-   In an object file, only the name is significant.
-   The Sun linker puts data into some of the other fields.  */
-__define_stab (N_BINCL, 0x82, "BINCL")
-
-/* Name of sub-source file (#include file).
-   Value is starting text address of the compilation.  */
-__define_stab (N_SOL, 0x84, "SOL")
-
-/* Parameter variable.  Value is offset from argument pointer.
-   (On most machines the argument pointer is the same as the frame pointer.  */
-__define_stab (N_PSYM, 0xa0, "PSYM")
-
-/* End of an include file.  No name.
-   This and N_BINCL act as brackets around the file's output.
-   In an object file, there is no significant data in this entry.
-   The Sun linker puts data into some of the fields.  */
-__define_stab (N_EINCL, 0xa2, "EINCL")
-
-/* Alternate entry point.  Value is its address.  */
-__define_stab (N_ENTRY, 0xa4, "ENTRY")
-
-/* Beginning of lexical block.
-   The desc is the nesting level in lexical blocks.
-   The value is the address of the start of the text for the block.
-   The variables declared inside the block *precede* the N_LBRAC symbol.  */
-__define_stab (N_LBRAC, 0xc0, "LBRAC")
-
-/* Place holder for deleted include file.  Replaces a N_BINCL and everything
-   up to the corresponding N_EINCL.  The Sun linker generates these when
-   it finds multiple identical copies of the symbols from an include file.
-   This appears only in output from the Sun linker.  */
-__define_stab (N_EXCL, 0xc2, "EXCL")
-
-/* Modula-2 scope information.  Can someone say what info it contains?  */
-__define_stab (N_SCOPE, 0xc4, "SCOPE")
-
-/* End of a lexical block.  Desc matches the N_LBRAC's desc.
-   The value is the address of the end of the text for the block.  */
-__define_stab (N_RBRAC, 0xe0, "RBRAC")
-
-/* Begin named common block.  Only the name is significant.  */
-__define_stab (N_BCOMM, 0xe2, "BCOMM")
-
-/* End named common block.  Only the name is significant
-   (and it should match the N_BCOMM).  */
-__define_stab (N_ECOMM, 0xe4, "ECOMM")
-
-/* End common (local name): value is address.
-   I'm not sure how this is used.  */
-__define_stab (N_ECOML, 0xe8, "ECOML")
-
-/* These STAB's are used on Gould systems for Non-Base register symbols
-   or something like that.  FIXME.  I have assigned the values at random
-   since I don't have a Gould here.  Fixups from Gould folk welcome... */
-__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
-__define_stab (N_NBDATA, 0xF2, "NBDATA")
-__define_stab (N_NBBSS,  0xF4, "NBBSS")
-__define_stab (N_NBSTS,  0xF6, "NBSTS")
-__define_stab (N_NBLCS,  0xF8, "NBLCS")
-
-/* Second symbol entry containing a length-value for the preceding entry.
-   The value is the length.  */
-__define_stab (N_LENG, 0xfe, "LENG")
-
-/* The above information, in matrix format.
-
-			STAB MATRIX
-	_________________________________________________
-	| 00 - 1F are not dbx stab symbols		|
-	| In most cases, the low bit is the EXTernal bit|
-
-	| 00 UNDEF  | 02 ABS	| 04 TEXT   | 06 DATA	|
-	| 01  |EXT  | 03  |EXT	| 05  |EXT  | 07  |EXT	|
-
-	| 08 BSS    | 0A INDR	| 0C FN_SEQ | 0E   	|
-	| 09  |EXT  | 0B 	| 0D	    | 0F	|
-
-	| 10 	    | 12 COMM	| 14 SETA   | 16 SETT	|
-	| 11	    | 13	| 15 	    | 17	|
-
-	| 18 SETD   | 1A SETB	| 1C SETV   | 1E WARNING|
-	| 19	    | 1B	| 1D 	    | 1F FN	|
-
-	|_______________________________________________|
-	| Debug entries with bit 01 set are unused.	|
-	| 20 GSYM   | 22 FNAME	| 24 FUN    | 26 STSYM	|
-	| 28 LCSYM  | 2A MAIN	| 2C	    | 2E	|
-	| 30 PC	    | 32 NSYMS	| 34 NOMAP  | 36	|
-	| 38 OBJ    | 3A	| 3C OPT    | 3E	|
-	| 40 RSYM   | 42 M2C	| 44 SLINE  | 46 DSLINE |
-	| 48 BSLINE*| 4A DEFD	| 4C        | 4E	|
-	| 50 EHDECL*| 52	| 54 CATCH  | 56        |
-	| 58        | 5A        | 5C        | 5E	|
-	| 60 SSYM   | 62	| 64 SO	    | 66 	|
-	| 68 	    | 6A	| 6C	    | 6E	|
-	| 70	    | 72	| 74	    | 76	|
-	| 78	    | 7A	| 7C	    | 7E	|
-	| 80 LSYM   | 82 BINCL	| 84 SOL    | 86	|
-	| 88	    | 8A	| 8C	    | 8E	|
-	| 90	    | 92	| 94	    | 96	|
-	| 98	    | 9A	| 9C	    | 9E	|
-	| A0 PSYM   | A2 EINCL	| A4 ENTRY  | A6	|
-	| A8	    | AA	| AC	    | AE	|
-	| B0	    | B2	| B4	    | B6	|
-	| B8	    | BA	| BC	    | BE	|
-	| C0 LBRAC  | C2 EXCL	| C4 SCOPE  | C6	|
-	| C8	    | CA	| CC	    | CE	|
-	| D0	    | D2	| D4	    | D6	|
-	| D8	    | DA	| DC	    | DE	|
-	| E0 RBRAC  | E2 BCOMM	| E4 ECOMM  | E6	|
-	| E8 ECOML  | EA	| EC	    | EE	|
-	| F0	    | F2	| F4	    | F6	|
-	| F8	    | FA	| FC	    | FE LENG	|
-	+-----------------------------------------------+
- * 50 EHDECL is also MOD2.
- * 48 BSLINE is also BROWS.
- */

+ 0 - 17
src/modules/native/tcc/libtcc/stab.h

@@ -1,17 +0,0 @@
-#ifndef __GNU_STAB__
-
-/* Indicate the GNU stab.h is in use.  */
-
-#define __GNU_STAB__
-
-#define __define_stab(NAME, CODE, STRING) NAME=CODE,
-
-enum __stab_debug_code
-{
-#include "stab.def"
-LAST_UNUSED_STAB_CODE
-};
-
-#undef __define_stab
-
-#endif /* __GNU_STAB_ */

+ 0 - 553
src/modules/native/tcc/libtcc/tcc.c

@@ -1,553 +0,0 @@
-/*
- *  TCC - Tiny C Compiler
- * 
- *  Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "libtcc.c"
-
-void help(void)
-{
-    printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
-           "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
-           "           [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
-           "           [-static] [infile1 infile2...] [-run infile args...]\n"
-           "\n"
-           "General options:\n"
-           "  -v          display current version, increase verbosity\n"
-           "  -c          compile only - generate an object file\n"
-           "  -o outfile  set output filename\n"
-           "  -Bdir       set tcc internal library path\n"
-           "  -bench      output compilation statistics\n"
-           "  -run        run compiled source\n"
-           "  -fflag      set or reset (with 'no-' prefix) 'flag' (see man page)\n"
-           "  -Wwarning   set or reset (with 'no-' prefix) 'warning' (see man page)\n"
-           "  -w          disable all warnings\n"
-           "Preprocessor options:\n"
-           "  -E          preprocess only\n"
-           "  -Idir       add include path 'dir'\n"
-           "  -Dsym[=val] define 'sym' with value 'val'\n"
-           "  -Usym       undefine 'sym'\n"
-           "Linker options:\n"
-           "  -Ldir       add library path 'dir'\n"
-           "  -llib       link with dynamic or static library 'lib'\n"
-           "  -shared     generate a shared library\n"
-           "  -soname     set name for shared library to be used at runtime\n"
-           "  -static     static linking\n"
-           "  -rdynamic   export all global symbols to dynamic linker\n"
-           "  -r          generate (relocatable) object file\n"
-           "Debugger options:\n"
-           "  -g          generate runtime debug info\n"
-#ifdef CONFIG_TCC_BCHECK
-           "  -b          compile with built-in memory and bounds checker (implies -g)\n"
-#endif
-#ifdef CONFIG_TCC_BACKTRACE
-           "  -bt N       show N callers in stack traces\n"
-#endif
-           );
-}
-
-static char **files;
-static int nb_files, nb_libraries;
-static int multiple_files;
-static int print_search_dirs;
-static int output_type;
-static int reloc_output;
-static const char *outfile;
-static int do_bench = 0;
-
-#define TCC_OPTION_HAS_ARG 0x0001
-#define TCC_OPTION_NOSEP   0x0002 /* cannot have space before option and arg */
-
-typedef struct TCCOption {
-    const char *name;
-    uint16_t index;
-    uint16_t flags;
-} TCCOption;
-
-enum {
-    TCC_OPTION_HELP,
-    TCC_OPTION_I,
-    TCC_OPTION_D,
-    TCC_OPTION_U,
-    TCC_OPTION_L,
-    TCC_OPTION_B,
-    TCC_OPTION_l,
-    TCC_OPTION_bench,
-    TCC_OPTION_bt,
-    TCC_OPTION_b,
-    TCC_OPTION_g,
-    TCC_OPTION_c,
-    TCC_OPTION_static,
-    TCC_OPTION_shared,
-    TCC_OPTION_soname,
-    TCC_OPTION_o,
-    TCC_OPTION_r,
-    TCC_OPTION_Wl,
-    TCC_OPTION_W,
-    TCC_OPTION_O,
-    TCC_OPTION_m,
-    TCC_OPTION_f,
-    TCC_OPTION_nostdinc,
-    TCC_OPTION_nostdlib,
-    TCC_OPTION_print_search_dirs,
-    TCC_OPTION_rdynamic,
-    TCC_OPTION_run,
-    TCC_OPTION_v,
-    TCC_OPTION_w,
-    TCC_OPTION_pipe,
-    TCC_OPTION_E,
-};
-
-static const TCCOption tcc_options[] = {
-    { "h", TCC_OPTION_HELP, 0 },
-    { "?", TCC_OPTION_HELP, 0 },
-    { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
-    { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
-    { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
-    { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
-    { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
-    { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "bench", TCC_OPTION_bench, 0 },
-    { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
-#ifdef CONFIG_TCC_BCHECK
-    { "b", TCC_OPTION_b, 0 },
-#endif
-    { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "c", TCC_OPTION_c, 0 },
-    { "static", TCC_OPTION_static, 0 },
-    { "shared", TCC_OPTION_shared, 0 },
-    { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
-    { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
-    { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "rdynamic", TCC_OPTION_rdynamic, 0 },
-    { "r", TCC_OPTION_r, 0 },
-    { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
-    { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "nostdinc", TCC_OPTION_nostdinc, 0 },
-    { "nostdlib", TCC_OPTION_nostdlib, 0 },
-    { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, 
-    { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-    { "w", TCC_OPTION_w, 0 },
-    { "pipe", TCC_OPTION_pipe, 0},
-    { "E", TCC_OPTION_E, 0},
-    { NULL },
-};
-
-static int64_t getclock_us(void)
-{
-#ifdef _WIN32
-    struct _timeb tb;
-    _ftime(&tb);
-    return (tb.time * 1000LL + tb.millitm) * 1000LL;
-#else
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    return tv.tv_sec * 1000000LL + tv.tv_usec;
-#endif
-}
-
-static int strstart(const char *str, const char *val, const char **ptr)
-{
-    const char *p, *q;
-    p = str;
-    q = val;
-    while (*q != '\0') {
-        if (*p != *q)
-            return 0;
-        p++;
-        q++;
-    }
-    if (ptr)
-        *ptr = p;
-    return 1;
-}
-
-/* convert 'str' into an array of space separated strings */
-static int expand_args(char ***pargv, const char *str)
-{
-    const char *s1;
-    char **argv, *arg;
-    int argc, len;
-
-    argc = 0;
-    argv = NULL;
-    for(;;) {
-        while (is_space(*str))
-            str++;
-        if (*str == '\0')
-            break;
-        s1 = str;
-        while (*str != '\0' && !is_space(*str))
-            str++;
-        len = str - s1;
-        arg = tcc_malloc(len + 1);
-        memcpy(arg, s1, len);
-        arg[len] = '\0';
-        dynarray_add((void ***)&argv, &argc, arg);
-    }
-    *pargv = argv;
-    return argc;
-}
-
-int parse_args(TCCState *s, int argc, char **argv)
-{
-    int optind;
-    const TCCOption *popt;
-    const char *optarg, *p1, *r1;
-    char *r;
-
-    optind = 0;
-    while (optind < argc) {
-
-        r = argv[optind++];
-        if (r[0] != '-' || r[1] == '\0') {
-            /* add a new file */
-            dynarray_add((void ***)&files, &nb_files, r);
-            if (!multiple_files) {
-                optind--;
-                /* argv[0] will be this file */
-                break;
-            }
-        } else {
-            /* find option in table (match only the first chars */
-            popt = tcc_options;
-            for(;;) {
-                p1 = popt->name;
-                if (p1 == NULL)
-                    error("invalid option -- '%s'", r);
-                r1 = r + 1;
-                for(;;) {
-                    if (*p1 == '\0')
-                        goto option_found;
-                    if (*r1 != *p1)
-                        break;
-                    p1++;
-                    r1++;
-                }
-                popt++;
-            }
-        option_found:
-            if (popt->flags & TCC_OPTION_HAS_ARG) {
-                if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
-                    optarg = r1;
-                } else {
-                    if (optind >= argc)
-                        error("argument to '%s' is missing", r);
-                    optarg = argv[optind++];
-                }
-            } else {
-                if (*r1 != '\0')
-                    return 0;
-                optarg = NULL;
-            }
-                
-            switch(popt->index) {
-            case TCC_OPTION_HELP:
-                return 0;
-
-            case TCC_OPTION_I:
-                if (tcc_add_include_path(s, optarg) < 0)
-                    error("too many include paths");
-                break;
-            case TCC_OPTION_D:
-                {
-                    char *sym, *value;
-                    sym = (char *)optarg;
-                    value = strchr(sym, '=');
-                    if (value) {
-                        *value = '\0';
-                        value++;
-                    }
-                    tcc_define_symbol(s, sym, value);
-                }
-                break;
-            case TCC_OPTION_U:
-                tcc_undefine_symbol(s, optarg);
-                break;
-            case TCC_OPTION_L:
-                tcc_add_library_path(s, optarg);
-                break;
-            case TCC_OPTION_B:
-                /* set tcc utilities path (mainly for tcc development) */
-                tcc_set_lib_path(s, optarg);
-                break;
-            case TCC_OPTION_l:
-                dynarray_add((void ***)&files, &nb_files, r);
-                nb_libraries++;
-                break;
-            case TCC_OPTION_bench:
-                do_bench = 1;
-                break;
-#ifdef CONFIG_TCC_BACKTRACE
-            case TCC_OPTION_bt:
-                num_callers = atoi(optarg);
-                break;
-#endif
-#ifdef CONFIG_TCC_BCHECK
-            case TCC_OPTION_b:
-                s->do_bounds_check = 1;
-                s->do_debug = 1;
-                break;
-#endif
-            case TCC_OPTION_g:
-                s->do_debug = 1;
-                break;
-            case TCC_OPTION_c:
-                multiple_files = 1;
-                output_type = TCC_OUTPUT_OBJ;
-                break;
-            case TCC_OPTION_static:
-                s->static_link = 1;
-                break;
-            case TCC_OPTION_shared:
-                output_type = TCC_OUTPUT_DLL;
-                break;
-            case TCC_OPTION_soname:
-                s->soname = optarg; 
-                break;
-            case TCC_OPTION_o:
-                multiple_files = 1;
-                outfile = optarg;
-                break;
-            case TCC_OPTION_r:
-                /* generate a .o merging several output files */
-                reloc_output = 1;
-                output_type = TCC_OUTPUT_OBJ;
-                break;
-            case TCC_OPTION_nostdinc:
-                s->nostdinc = 1;
-                break;
-            case TCC_OPTION_nostdlib:
-                s->nostdlib = 1;
-                break;
-            case TCC_OPTION_print_search_dirs:
-                print_search_dirs = 1;
-                break;
-            case TCC_OPTION_run:
-                {
-                    int argc1;
-                    char **argv1;
-                    argc1 = expand_args(&argv1, optarg);
-                    if (argc1 > 0) {
-                        parse_args(s, argc1, argv1);
-                    }
-                    multiple_files = 0;
-                    output_type = TCC_OUTPUT_MEMORY;
-                }
-                break;
-            case TCC_OPTION_v:
-                do {
-                    if (0 == s->verbose++)
-                        printf("tcc version %s\n", TCC_VERSION);
-                } while (*optarg++ == 'v');
-                break;
-            case TCC_OPTION_f:
-                if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
-                    goto unsupported_option;
-                break;
-            case TCC_OPTION_W:
-                if (tcc_set_warning(s, optarg, 1) < 0 && 
-                    s->warn_unsupported)
-                    goto unsupported_option;
-                break;
-            case TCC_OPTION_w:
-                s->warn_none = 1;
-                break;
-            case TCC_OPTION_rdynamic:
-                s->rdynamic = 1;
-                break;
-            case TCC_OPTION_Wl:
-                {
-                    const char *p;
-                    if (strstart(optarg, "-Ttext,", &p)) {
-                        s->text_addr = strtoul(p, NULL, 16);
-                        s->has_text_addr = 1;
-                    } else if (strstart(optarg, "--oformat,", &p)) {
-                        if (strstart(p, "elf32-", NULL)) {
-                            s->output_format = TCC_OUTPUT_FORMAT_ELF;
-                        } else if (!strcmp(p, "binary")) {
-                            s->output_format = TCC_OUTPUT_FORMAT_BINARY;
-                        } else
-#ifdef TCC_TARGET_COFF
-                        if (!strcmp(p, "coff")) {
-                            s->output_format = TCC_OUTPUT_FORMAT_COFF;
-                        } else
-#endif
-                        {
-                            error("target %s not found", p);
-                        }
-                    } else {
-                        error("unsupported linker option '%s'", optarg);
-                    }
-                }
-                break;
-            case TCC_OPTION_E:
-                output_type = TCC_OUTPUT_PREPROCESS;
-                break;
-            default:
-                if (s->warn_unsupported) {
-                unsupported_option:
-                    warning("unsupported option '%s'", r);
-                }
-                break;
-            }
-        }
-    }
-    return optind + 1;
-}
-
-int main(int argc, char **argv)
-{
-    int i;
-    TCCState *s;
-    int nb_objfiles, ret, optind;
-    char objfilename[1024];
-    int64_t start_time = 0;
-
-    s = tcc_new();
-#ifdef _WIN32
-    tcc_set_lib_path_w32(s);
-#endif
-    output_type = TCC_OUTPUT_EXE;
-    outfile = NULL;
-    multiple_files = 1;
-    files = NULL;
-    nb_files = 0;
-    nb_libraries = 0;
-    reloc_output = 0;
-    print_search_dirs = 0;
-    ret = 0;
-
-    optind = parse_args(s, argc - 1, argv + 1);
-    if (print_search_dirs) {
-        /* enough for Linux kernel */
-        printf("install: %s/\n", s->tcc_lib_path);
-        return 0;
-    }
-    if (optind == 0 || nb_files == 0) {
-        if (optind && s->verbose)
-            return 0;
-        help();
-        return 1;
-    }
-
-    nb_objfiles = nb_files - nb_libraries;
-
-    /* if outfile provided without other options, we output an
-       executable */
-    if (outfile && output_type == TCC_OUTPUT_MEMORY)
-        output_type = TCC_OUTPUT_EXE;
-
-    /* check -c consistency : only single file handled. XXX: checks file type */
-    if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
-        /* accepts only a single input file */
-        if (nb_objfiles != 1)
-            error("cannot specify multiple files with -c");
-        if (nb_libraries != 0)
-            error("cannot specify libraries with -c");
-    }
-    
-
-    if (output_type == TCC_OUTPUT_PREPROCESS) {
-        if (!outfile) {
-            s->outfile = stdout;
-        } else {
-            s->outfile = fopen(outfile, "w");
-            if (!s->outfile)
-                error("could not open '%s", outfile);
-        }
-    } else if (output_type != TCC_OUTPUT_MEMORY) {
-        if (!outfile) {
-            /* compute default outfile name */
-            char *ext;
-            const char *name = 
-                strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
-            pstrcpy(objfilename, sizeof(objfilename), name);
-            ext = tcc_fileextension(objfilename);
-#ifdef TCC_TARGET_PE
-            if (output_type == TCC_OUTPUT_DLL)
-                strcpy(ext, ".dll");
-            else
-            if (output_type == TCC_OUTPUT_EXE)
-                strcpy(ext, ".exe");
-            else
-#endif
-            if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
-                strcpy(ext, ".o");
-            else
-                pstrcpy(objfilename, sizeof(objfilename), "a.out");
-            outfile = objfilename;
-        }
-    }
-
-    if (do_bench) {
-        start_time = getclock_us();
-    }
-
-    tcc_set_output_type(s, output_type);
-
-    /* compile or add each files or library */
-    for(i = 0; i < nb_files && ret == 0; i++) {
-        const char *filename;
-
-        filename = files[i];
-        if (filename[0] == '-' && filename[1]) {
-            if (tcc_add_library(s, filename + 2) < 0) {
-                error_noabort("cannot find %s", filename);
-                ret = 1;
-            }
-        } else {
-            if (1 == s->verbose)
-                printf("-> %s\n", filename);
-            if (tcc_add_file(s, filename) < 0)
-                ret = 1;
-        }
-    }
-
-    /* free all files */
-    tcc_free(files);
-
-    if (ret)
-        goto the_end;
-
-    if (do_bench)
-        tcc_print_stats(s, getclock_us() - start_time);
-
-    if (s->output_type == TCC_OUTPUT_PREPROCESS) {
-        if (outfile)
-            fclose(s->outfile);
-    } else if (s->output_type == TCC_OUTPUT_MEMORY) {
-        ret = tcc_run(s, argc - optind, argv + optind);
-    } else
-        ret = tcc_output_file(s, outfile) ? 1 : 0;
- the_end:
-    /* XXX: cannot do it with bound checking because of the malloc hooks */
-    if (!s->do_bounds_check)
-        tcc_delete(s);
-
-#ifdef MEM_DEBUG
-    if (do_bench) {
-        printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
-    }
-#endif
-    return ret;
-}
-

+ 0 - 766
src/modules/native/tcc/libtcc/tcc.h

@@ -1,766 +0,0 @@
-/*
- *  TCC - Tiny C Compiler
- * 
- *  Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#define _GNU_SOURCE
-#include "config.h"
-
-#ifdef CONFIG_TCCBOOT
-
-#include "tccboot.h"
-#define CONFIG_TCC_STATIC
-
-#else
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <math.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <setjmp.h>
-#include <time.h>
-
-#ifdef _WIN32
-#include <windows.h>
-#include <sys/timeb.h>
-#include <io.h> /* open, close etc. */
-#include <direct.h> /* getcwd */
-#define inline __inline
-#define inp next_inp
-#endif
-
-#ifndef _WIN32
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/ucontext.h>
-#include <sys/mman.h>
-#endif
-
-#endif /* !CONFIG_TCCBOOT */
-
-#ifndef PAGESIZE
-#define PAGESIZE 4096
-#endif
-
-#include "elf.h"
-#include "stab.h"
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-#include "libtcc.h"
-
-/* parser debug */
-//#define PARSE_DEBUG
-/* preprocessor debug */
-//#define PP_DEBUG
-/* include file debug */
-//#define INC_DEBUG
-
-//#define MEM_DEBUG
-
-/* assembler debug */
-//#define ASM_DEBUG
-
-/* target selection */
-//#define TCC_TARGET_I386   /* i386 code generator */
-//#define TCC_TARGET_ARM    /* ARMv4 code generator */
-//#define TCC_TARGET_C67    /* TMS320C67xx code generator */
-//#define TCC_TARGET_X86_64 /* x86-64 code generator */
-
-/* default target is I386 */
-#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
-    !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
-#define TCC_TARGET_I386
-#endif
-
-#if !defined(_WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
-    !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
-#define CONFIG_TCC_BCHECK /* enable bound checking code */
-#endif
-
-#if defined(_WIN32) && !defined(TCC_TARGET_PE)
-#define CONFIG_TCC_STATIC
-#endif
-
-/* define it to include assembler support */
-#if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67) && \
-    !defined(TCC_TARGET_X86_64)
-#define CONFIG_TCC_ASM
-#endif
-
-/* object format selection */
-#if defined(TCC_TARGET_C67)
-#define TCC_TARGET_COFF
-#endif
-
-#if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
-#define CONFIG_TCC_BACKTRACE
-#endif
-
-#define FALSE 0
-#define false 0
-#define TRUE 1
-#define true 1
-typedef int BOOL;
-
-/* path to find crt1.o, crti.o and crtn.o. Only needed when generating
-   executables or dlls */
-#define CONFIG_TCC_CRT_PREFIX CONFIG_SYSROOT "/usr/lib"
-
-#define INCLUDE_STACK_SIZE  32
-#define IFDEF_STACK_SIZE    64
-#define VSTACK_SIZE         256
-#define STRING_MAX_SIZE     1024
-#define PACK_STACK_SIZE     8
-
-#define TOK_HASH_SIZE       8192 /* must be a power of two */
-#define TOK_ALLOC_INCR      512  /* must be a power of two */
-#define TOK_MAX_SIZE        4 /* token max size in int unit when stored in string */
-
-/* token symbol management */
-typedef struct TokenSym {
-    struct TokenSym *hash_next;
-    struct Sym *sym_define; /* direct pointer to define */
-    struct Sym *sym_label; /* direct pointer to label */
-    struct Sym *sym_struct; /* direct pointer to structure */
-    struct Sym *sym_identifier; /* direct pointer to identifier */
-    int tok; /* token number */
-    int len;
-    char str[1];
-} TokenSym;
-
-#ifdef TCC_TARGET_PE
-typedef unsigned short nwchar_t;
-#else
-typedef int nwchar_t;
-#endif
-
-typedef struct CString {
-    int size; /* size in bytes */
-    void *data; /* either 'char *' or 'nwchar_t *' */
-    int size_allocated;
-    void *data_allocated; /* if non NULL, data has been malloced */
-} CString;
-
-/* type definition */
-typedef struct CType {
-    int t;
-    struct Sym *ref;
-} CType;
-
-/* constant value */
-typedef union CValue {
-    long double ld;
-    double d;
-    float f;
-    int i;
-    unsigned int ui;
-    unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
-    long long ll;
-    unsigned long long ull;
-    struct CString *cstr;
-    void *ptr;
-    int tab[1];
-} CValue;
-
-/* value on stack */
-typedef struct SValue {
-    CType type;      /* type */
-    unsigned short r;      /* register + flags */
-    unsigned short r2;     /* second register, used for 'long long'
-                              type. If not used, set to VT_CONST */
-    CValue c;              /* constant, if VT_CONST */
-    struct Sym *sym;       /* symbol, if (VT_SYM | VT_CONST) */
-} SValue;
-
-/* symbol management */
-typedef struct Sym {
-    int v;    /* symbol token */
-    long r;    /* associated register */
-    long c;    /* associated number */
-    CType type;    /* associated type */
-    struct Sym *next; /* next related symbol */
-    struct Sym *prev; /* prev symbol in stack */
-    struct Sym *prev_tok; /* previous symbol for this token */
-} Sym;
-
-/* section definition */
-/* XXX: use directly ELF structure for parameters ? */
-/* special flag to indicate that the section should not be linked to
-   the other ones */
-#define SHF_PRIVATE 0x80000000
-
-/* special flag, too */
-#define SECTION_ABS ((void *)1)
-
-typedef struct Section {
-    unsigned long data_offset; /* current data offset */
-    unsigned char *data;       /* section data */
-    unsigned long data_allocated; /* used for realloc() handling */
-    int sh_name;             /* elf section name (only used during output) */
-    int sh_num;              /* elf section number */
-    int sh_type;             /* elf section type */
-    int sh_flags;            /* elf section flags */
-    int sh_info;             /* elf section info */
-    int sh_addralign;        /* elf section alignment */
-    int sh_entsize;          /* elf entry size */
-    unsigned long sh_size;   /* section size (only used during output) */
-    unsigned long sh_addr;      /* address at which the section is relocated */
-    unsigned long sh_offset;    /* file offset */
-    int nb_hashed_syms;      /* used to resize the hash table */
-    struct Section *link;    /* link to another section */
-    struct Section *reloc;   /* corresponding section for relocation, if any */
-    struct Section *hash;     /* hash table for symbols */
-    struct Section *next;
-    char name[1];           /* section name */
-} Section;
-
-typedef struct DLLReference {
-    int level;
-    void *handle;
-    char name[1];
-} DLLReference;
-
-/* GNUC attribute definition */
-typedef struct AttributeDef {
-    int aligned;
-    int packed; 
-    Section *section;
-    int func_attr; /* calling convention, exports, ... */
-} AttributeDef;
-
-/* -------------------------------------------------- */
-/* gr: wrappers for casting sym->r for other purposes */
-typedef struct {
-    unsigned
-      func_call : 8,
-      func_args : 8,
-      func_export : 1;
-} func_attr_t;
-
-#define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
-#define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
-#define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
-#define INLINE_DEF(r) (*(int **)&(r))
-/* -------------------------------------------------- */
-
-#define SYM_STRUCT     0x40000000 /* struct/union/enum symbol space */
-#define SYM_FIELD      0x20000000 /* struct/union field symbol space */
-#define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
-
-/* stored in 'Sym.c' field */
-#define FUNC_NEW       1 /* ansi function prototype */
-#define FUNC_OLD       2 /* old function prototype */
-#define FUNC_ELLIPSIS  3 /* ansi function prototype with ... */
-
-/* stored in 'Sym.r' field */
-#define FUNC_CDECL     0 /* standard c call */
-#define FUNC_STDCALL   1 /* pascal c call */
-#define FUNC_FASTCALL1 2 /* first param in %eax */
-#define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
-#define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
-#define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
-
-/* field 'Sym.t' for macros */
-#define MACRO_OBJ      0 /* object like macro */
-#define MACRO_FUNC     1 /* function like macro */
-
-/* field 'Sym.r' for C labels */
-#define LABEL_DEFINED  0 /* label is defined */
-#define LABEL_FORWARD  1 /* label is forward defined */
-#define LABEL_DECLARED 2 /* label is declared but never used */
-
-/* type_decl() types */
-#define TYPE_ABSTRACT  1 /* type without variable */
-#define TYPE_DIRECT    2 /* type with variable */
-
-#define IO_BUF_SIZE 8192
-
-typedef struct BufferedFile {
-    uint8_t *buf_ptr;
-    uint8_t *buf_end;
-    int fd;
-    int line_num;    /* current line number - here to simplify code */
-    int ifndef_macro;  /* #ifndef macro / #endif search */
-    int ifndef_macro_saved; /* saved ifndef_macro */
-    int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
-    char inc_type;          /* type of include */
-    char inc_filename[512]; /* filename specified by the user */
-    char filename[1024];    /* current filename - here to simplify code */
-    unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
-} BufferedFile;
-
-#define CH_EOB   '\\'       /* end of buffer or '\0' char in file */
-#define CH_EOF   (-1)   /* end of file */
-
-/* parsing state (used to save parser state to reparse part of the
-   source several times) */
-typedef struct ParseState {
-    int *macro_ptr;
-    int line_num;
-    int tok;
-    CValue tokc;
-} ParseState;
-
-/* used to record tokens */
-typedef struct TokenString {
-    int *str;
-    int len;
-    int allocated_len;
-    int last_line_num;
-} TokenString;
-
-/* include file cache, used to find files faster and also to eliminate
-   inclusion if the include file is protected by #ifndef ... #endif */
-typedef struct CachedInclude {
-    int ifndef_macro;
-    int hash_next; /* -1 if none */
-    char type; /* '"' or '>' to give include type */
-    char filename[1]; /* path specified in #include */
-} CachedInclude;
-
-#define CACHED_INCLUDES_HASH_SIZE 512
-
-#ifdef CONFIG_TCC_ASM
-typedef struct ExprValue {
-    uint32_t v;
-    Sym *sym;
-} ExprValue;
-
-#define MAX_ASM_OPERANDS 30
-typedef struct ASMOperand {
-    int id; /* GCC 3 optionnal identifier (0 if number only supported */
-    char *constraint;
-    char asm_str[16]; /* computed asm string for operand */
-    SValue *vt; /* C value of the expression */
-    int ref_index; /* if >= 0, gives reference to a output constraint */
-    int input_index; /* if >= 0, gives reference to an input constraint */
-    int priority; /* priority, used to assign registers */
-    int reg; /* if >= 0, register number used for this operand */
-    int is_llong; /* true if double register value */
-    int is_memory; /* true if memory operand */
-    int is_rw;     /* for '+' modifier */
-} ASMOperand;
-
-#endif
-
-struct TCCState {
-    int output_type;
- 
-    BufferedFile **include_stack_ptr;
-    int *ifdef_stack_ptr;
-
-    /* include file handling */
-    char **include_paths;
-    int nb_include_paths;
-    char **sysinclude_paths;
-    int nb_sysinclude_paths;
-    CachedInclude **cached_includes;
-    int nb_cached_includes;
-
-    char **library_paths;
-    int nb_library_paths;
-
-    /* array of all loaded dlls (including those referenced by loaded
-       dlls) */
-    DLLReference **loaded_dlls;
-    int nb_loaded_dlls;
-
-    /* sections */
-    Section **sections;
-    int nb_sections; /* number of sections, including first dummy section */
-
-    Section **priv_sections;
-    int nb_priv_sections; /* number of private sections */
-
-    /* got handling */
-    Section *got;
-    Section *plt;
-    unsigned long *got_offsets;
-    int nb_got_offsets;
-    /* give the correspondance from symtab indexes to dynsym indexes */
-    int *symtab_to_dynsym;
-
-    /* temporary dynamic symbol sections (for dll loading) */
-    Section *dynsymtab_section;
-    /* exported dynamic symbol section */
-    Section *dynsym;
-
-    int nostdinc; /* if true, no standard headers are added */
-    int nostdlib; /* if true, no standard libraries are added */
-    int nocommon; /* if true, do not use common symbols for .bss data */
-
-    /* if true, static linking is performed */
-    int static_link;
-
-    /* soname as specified on the command line (-soname) */
-    const char *soname;
-
-    /* if true, all symbols are exported */
-    int rdynamic;
-
-    /* if true, only link in referenced objects from archive */
-    int alacarte_link;
-
-    /* address of text section */
-    unsigned long text_addr;
-    int has_text_addr;
-    
-    /* output format, see TCC_OUTPUT_FORMAT_xxx */
-    int output_format;
-
-    /* C language options */
-    int char_is_unsigned;
-    int leading_underscore;
-    
-    /* warning switches */
-    int warn_write_strings;
-    int warn_unsupported;
-    int warn_error;
-    int warn_none;
-    int warn_implicit_function_declaration;
-
-    /* display some information during compilation */
-    int verbose;
-    /* compile with debug symbol (and use them if error during execution) */
-    int do_debug;
-    /* compile with built-in memory and bounds checker */
-    int do_bounds_check;
-    /* give the path of the tcc libraries */
-    const char *tcc_lib_path;
-
-    /* error handling */
-    void *error_opaque;
-    void (*error_func)(void *opaque, const char *msg);
-    int error_set_jmp_enabled;
-    jmp_buf error_jmp_buf;
-    int nb_errors;
-
-    /* tiny assembler state */
-    Sym *asm_labels;
-
-    /* see include_stack_ptr */
-    BufferedFile *include_stack[INCLUDE_STACK_SIZE];
-
-    /* see ifdef_stack_ptr */
-    int ifdef_stack[IFDEF_STACK_SIZE];
-
-    /* see cached_includes */
-    int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
-
-    /* pack stack */
-    int pack_stack[PACK_STACK_SIZE];
-    int *pack_stack_ptr;
-
-    /* output file for preprocessing */
-    FILE *outfile;
-
-    /* for tcc_relocate */
-    int runtime_added;
-
-#ifdef TCC_TARGET_X86_64
-    /* write PLT and GOT here */
-    char *runtime_plt_and_got;
-    unsigned int runtime_plt_and_got_offset;
-#endif
-};
-
-/* The current value can be: */
-#define VT_VALMASK   0x00ff
-#define VT_CONST     0x00f0  /* constant in vc 
-                              (must be first non register value) */
-#define VT_LLOCAL    0x00f1  /* lvalue, offset on stack */
-#define VT_LOCAL     0x00f2  /* offset on stack */
-#define VT_CMP       0x00f3  /* the value is stored in processor flags (in vc) */
-#define VT_JMP       0x00f4  /* value is the consequence of jmp true (even) */
-#define VT_JMPI      0x00f5  /* value is the consequence of jmp false (odd) */
-#define VT_LVAL      0x0100  /* var is an lvalue */
-#define VT_SYM       0x0200  /* a symbol value is added */
-#define VT_MUSTCAST  0x0400  /* value must be casted to be correct (used for
-                                char/short stored in integer registers) */
-#define VT_MUSTBOUND 0x0800  /* bound checking must be done before
-                                dereferencing value */
-#define VT_BOUNDED   0x8000  /* value is bounded. The address of the
-                                bounding function call point is in vc */
-#define VT_LVAL_BYTE     0x1000  /* lvalue is a byte */
-#define VT_LVAL_SHORT    0x2000  /* lvalue is a short */
-#define VT_LVAL_UNSIGNED 0x4000  /* lvalue is unsigned */
-#define VT_LVAL_TYPE     (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
-
-/* types */
-#define VT_INT        0  /* integer type */
-#define VT_BYTE       1  /* signed byte type */
-#define VT_SHORT      2  /* short type */
-#define VT_VOID       3  /* void type */
-#define VT_PTR        4  /* pointer */
-#define VT_ENUM       5  /* enum definition */
-#define VT_FUNC       6  /* function type */
-#define VT_STRUCT     7  /* struct/union definition */
-#define VT_FLOAT      8  /* IEEE float */
-#define VT_DOUBLE     9  /* IEEE double */
-#define VT_LDOUBLE   10  /* IEEE long double */
-#define VT_BOOL      11  /* ISOC99 boolean type */
-#define VT_LLONG     12  /* 64 bit integer */
-#define VT_LONG      13  /* long integer (NEVER USED as type, only
-                            during parsing) */
-#define VT_BTYPE      0x000f /* mask for basic type */
-#define VT_UNSIGNED   0x0010  /* unsigned type */
-#define VT_ARRAY      0x0020  /* array type (also has VT_PTR) */
-#define VT_BITFIELD   0x0040  /* bitfield modifier */
-#define VT_CONSTANT   0x0800  /* const modifier */
-#define VT_VOLATILE   0x1000  /* volatile modifier */
-#define VT_SIGNED     0x2000  /* signed type */
-
-/* storage */
-#define VT_EXTERN  0x00000080  /* extern definition */
-#define VT_STATIC  0x00000100  /* static variable */
-#define VT_TYPEDEF 0x00000200  /* typedef definition */
-#define VT_INLINE  0x00000400  /* inline definition */
-
-#define VT_STRUCT_SHIFT 16   /* shift for bitfield shift values */
-
-/* type mask (except storage) */
-#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
-#define VT_TYPE    (~(VT_STORAGE))
-
-/* token values */
-
-/* warning: the following compare tokens depend on i386 asm code */
-#define TOK_ULT 0x92
-#define TOK_UGE 0x93
-#define TOK_EQ  0x94
-#define TOK_NE  0x95
-#define TOK_ULE 0x96
-#define TOK_UGT 0x97
-#define TOK_Nset 0x98
-#define TOK_Nclear 0x99
-#define TOK_LT  0x9c
-#define TOK_GE  0x9d
-#define TOK_LE  0x9e
-#define TOK_GT  0x9f
-
-#define TOK_LAND  0xa0
-#define TOK_LOR   0xa1
-
-#define TOK_DEC   0xa2
-#define TOK_MID   0xa3 /* inc/dec, to void constant */
-#define TOK_INC   0xa4
-#define TOK_UDIV  0xb0 /* unsigned division */
-#define TOK_UMOD  0xb1 /* unsigned modulo */
-#define TOK_PDIV  0xb2 /* fast division with undefined rounding for pointers */
-#define TOK_CINT   0xb3 /* number in tokc */
-#define TOK_CCHAR 0xb4 /* char constant in tokc */
-#define TOK_STR   0xb5 /* pointer to string in tokc */
-#define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
-#define TOK_LCHAR    0xb7
-#define TOK_LSTR     0xb8
-#define TOK_CFLOAT   0xb9 /* float constant */
-#define TOK_LINENUM  0xba /* line number info */
-#define TOK_CDOUBLE  0xc0 /* double constant */
-#define TOK_CLDOUBLE 0xc1 /* long double constant */
-#define TOK_UMULL    0xc2 /* unsigned 32x32 -> 64 mul */
-#define TOK_ADDC1    0xc3 /* add with carry generation */
-#define TOK_ADDC2    0xc4 /* add with carry use */
-#define TOK_SUBC1    0xc5 /* add with carry generation */
-#define TOK_SUBC2    0xc6 /* add with carry use */
-#define TOK_CUINT    0xc8 /* unsigned int constant */
-#define TOK_CLLONG   0xc9 /* long long constant */
-#define TOK_CULLONG  0xca /* unsigned long long constant */
-#define TOK_ARROW    0xcb
-#define TOK_DOTS     0xcc /* three dots */
-#define TOK_SHR      0xcd /* unsigned shift right */
-#define TOK_PPNUM    0xce /* preprocessor number */
-
-#define TOK_SHL   0x01 /* shift left */
-#define TOK_SAR   0x02 /* signed shift right */
-  
-/* assignement operators : normal operator or 0x80 */
-#define TOK_A_MOD 0xa5
-#define TOK_A_AND 0xa6
-#define TOK_A_MUL 0xaa
-#define TOK_A_ADD 0xab
-#define TOK_A_SUB 0xad
-#define TOK_A_DIV 0xaf
-#define TOK_A_XOR 0xde
-#define TOK_A_OR  0xfc
-#define TOK_A_SHL 0x81
-#define TOK_A_SAR 0x82
-
-#ifndef offsetof
-#define offsetof(type, field) ((size_t) &((type *)0)->field)
-#endif
-
-#ifndef countof
-#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
-#endif
-
-#define TOK_EOF       (-1)  /* end of file */
-#define TOK_LINEFEED  10    /* line feed */
-
-/* all identificators and strings have token above that */
-#define TOK_IDENT 256
-
-/* only used for i386 asm opcodes definitions */
-#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
-
-#define DEF_BWL(x) \
- DEF(TOK_ASM_ ## x ## b, #x "b") \
- DEF(TOK_ASM_ ## x ## w, #x "w") \
- DEF(TOK_ASM_ ## x ## l, #x "l") \
- DEF(TOK_ASM_ ## x, #x)
-
-#define DEF_WL(x) \
- DEF(TOK_ASM_ ## x ## w, #x "w") \
- DEF(TOK_ASM_ ## x ## l, #x "l") \
- DEF(TOK_ASM_ ## x, #x)
-
-#define DEF_FP1(x) \
- DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
- DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
- DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
- DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
-
-#define DEF_FP(x) \
- DEF(TOK_ASM_ ## f ## x, "f" #x ) \
- DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
- DEF_FP1(x)
-
-#define DEF_ASMTEST(x) \
- DEF_ASM(x ## o) \
- DEF_ASM(x ## no) \
- DEF_ASM(x ## b) \
- DEF_ASM(x ## c) \
- DEF_ASM(x ## nae) \
- DEF_ASM(x ## nb) \
- DEF_ASM(x ## nc) \
- DEF_ASM(x ## ae) \
- DEF_ASM(x ## e) \
- DEF_ASM(x ## z) \
- DEF_ASM(x ## ne) \
- DEF_ASM(x ## nz) \
- DEF_ASM(x ## be) \
- DEF_ASM(x ## na) \
- DEF_ASM(x ## nbe) \
- DEF_ASM(x ## a) \
- DEF_ASM(x ## s) \
- DEF_ASM(x ## ns) \
- DEF_ASM(x ## p) \
- DEF_ASM(x ## pe) \
- DEF_ASM(x ## np) \
- DEF_ASM(x ## po) \
- DEF_ASM(x ## l) \
- DEF_ASM(x ## nge) \
- DEF_ASM(x ## nl) \
- DEF_ASM(x ## ge) \
- DEF_ASM(x ## le) \
- DEF_ASM(x ## ng) \
- DEF_ASM(x ## nle) \
- DEF_ASM(x ## g)
-
-#define TOK_ASM_int TOK_INT
-
-enum tcc_token {
-    TOK_LAST = TOK_IDENT - 1,
-#define DEF(id, str) id,
-#include "tcctok.h"
-#undef DEF
-};
-
-#define TOK_UIDENT TOK_DEFINE
-
-#ifdef _WIN32
-#define snprintf _snprintf
-#define vsnprintf _vsnprintf
-#ifndef __GNUC__
-  #define strtold (long double)strtod
-  #define strtof (float)strtod
-  #define strtoll (long long)strtol
-#endif
-#elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
-    || defined(__OpenBSD__)
-/* currently incorrect */
-long double strtold(const char *nptr, char **endptr)
-{
-    return (long double)strtod(nptr, endptr);
-}
-float strtof(const char *nptr, char **endptr)
-{
-    return (float)strtod(nptr, endptr);
-}
-#else
-/* XXX: need to define this to use them in non ISOC99 context */
-extern float strtof (const char *__nptr, char **__endptr);
-extern long double strtold (const char *__nptr, char **__endptr);
-#endif
-
-#ifdef _WIN32
-#define IS_PATHSEP(c) (c == '/' || c == '\\')
-#define IS_ABSPATH(p) (IS_PATHSEP(p[0]) || (p[0] && p[1] == ':' && IS_PATHSEP(p[2])))
-#define PATHCMP stricmp
-#else
-#define IS_PATHSEP(c) (c == '/')
-#define IS_ABSPATH(p) IS_PATHSEP(p[0])
-#define PATHCMP strcmp
-#endif
-
-void error(const char *fmt, ...);
-void error_noabort(const char *fmt, ...);
-void warning(const char *fmt, ...);
-
-void tcc_set_lib_path_w32(TCCState *s);
-int tcc_set_flag(TCCState *s, const char *flag_name, int value);
-void tcc_print_stats(TCCState *s, int64_t total_time);
-
-void tcc_free(void *ptr);
-void *tcc_malloc(unsigned long size);
-void *tcc_mallocz(unsigned long size);
-void *tcc_realloc(void *ptr, unsigned long size);
-char *tcc_strdup(const char *str);
-
-char *tcc_basename(const char *name);
-char *tcc_fileextension (const char *name);
-char *pstrcpy(char *buf, int buf_size, const char *s);
-char *pstrcat(char *buf, int buf_size, const char *s);
-void dynarray_add(void ***ptab, int *nb_ptr, void *data);
-void dynarray_reset(void *pp, int *n);
-
-#ifdef CONFIG_TCC_BACKTRACE
-extern int num_callers;
-extern const char **rt_bound_error_msg;
-#endif
-
-/* true if float/double/long double type */
-static inline int is_float(int t)
-{
-    int bt;
-    bt = t & VT_BTYPE;
-    return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
-}
-
-/* space exlcuding newline */
-static inline int is_space(int ch)
-{
-    return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
-}
-

+ 0 - 1021
src/modules/native/tcc/libtcc/tccasm.c

@@ -1,1021 +0,0 @@
-/*
- *  GAS like assembler for TCC
- * 
- *  Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-static int asm_get_local_label_name(TCCState *s1, unsigned int n)
-{
-    char buf[64];
-    TokenSym *ts;
-
-    snprintf(buf, sizeof(buf), "L..%u", n);
-    ts = tok_alloc(buf, strlen(buf));
-    return ts->tok;
-}
-
-static void asm_expr(TCCState *s1, ExprValue *pe);
-
-/* We do not use the C expression parser to handle symbols. Maybe the
-   C expression parser could be tweaked to do so. */
-
-static void asm_expr_unary(TCCState *s1, ExprValue *pe)
-{
-    Sym *sym;
-    int op, n, label;
-    const char *p;
-
-    switch(tok) {
-    case TOK_PPNUM:
-        p = tokc.cstr->data;
-        n = strtoul(p, (char **)&p, 0);
-        if (*p == 'b' || *p == 'f') {
-            /* backward or forward label */
-            label = asm_get_local_label_name(s1, n);
-            sym = label_find(label);
-            if (*p == 'b') {
-                /* backward : find the last corresponding defined label */
-                if (sym && sym->r == 0)
-                    sym = sym->prev_tok;
-                if (!sym)
-                    error("local label '%d' not found backward", n);
-            } else {
-                /* forward */
-                if (!sym || sym->r) {
-                    /* if the last label is defined, then define a new one */
-                    sym = label_push(&s1->asm_labels, label, 0);
-                    sym->type.t = VT_STATIC | VT_VOID;
-                }
-            }
-            pe->v = 0;
-            pe->sym = sym;
-        } else if (*p == '\0') {
-            pe->v = n;
-            pe->sym = NULL;
-        } else {
-            error("invalid number syntax");
-        }
-        next();
-        break;
-    case '+':
-        next();
-        asm_expr_unary(s1, pe);
-        break;
-    case '-':
-    case '~':
-        op = tok;
-        next();
-        asm_expr_unary(s1, pe);
-        if (pe->sym)
-            error("invalid operation with label");
-        if (op == '-')
-            pe->v = -pe->v;
-        else
-            pe->v = ~pe->v;
-        break;
-    case TOK_CCHAR:
-    case TOK_LCHAR:
-	pe->v = tokc.i;
-	pe->sym = NULL;
-	next();
-	break;
-    case '(':
-        next();
-        asm_expr(s1, pe);
-        skip(')');
-        break;
-    default:
-        if (tok >= TOK_IDENT) {
-            /* label case : if the label was not found, add one */
-            sym = label_find(tok);
-            if (!sym) {
-                sym = label_push(&s1->asm_labels, tok, 0);
-                /* NOTE: by default, the symbol is global */
-                sym->type.t = VT_VOID;
-            }
-            if (sym->r == SHN_ABS) {
-                /* if absolute symbol, no need to put a symbol value */
-                pe->v = (long)sym->next;
-                pe->sym = NULL;
-            } else {
-                pe->v = 0;
-                pe->sym = sym;
-            }
-            next();
-        } else {
-            error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
-        }
-        break;
-    }
-}
-    
-static void asm_expr_prod(TCCState *s1, ExprValue *pe)
-{
-    int op;
-    ExprValue e2;
-
-    asm_expr_unary(s1, pe);
-    for(;;) {
-        op = tok;
-        if (op != '*' && op != '/' && op != '%' && 
-            op != TOK_SHL && op != TOK_SAR)
-            break;
-        next();
-        asm_expr_unary(s1, &e2);
-        if (pe->sym || e2.sym)
-            error("invalid operation with label");
-        switch(op) {
-        case '*':
-            pe->v *= e2.v;
-            break;
-        case '/':  
-            if (e2.v == 0) {
-            div_error:
-                error("division by zero");
-            }
-            pe->v /= e2.v;
-            break;
-        case '%':  
-            if (e2.v == 0)
-                goto div_error;
-            pe->v %= e2.v;
-            break;
-        case TOK_SHL:
-            pe->v <<= e2.v;
-            break;
-        default:
-        case TOK_SAR:
-            pe->v >>= e2.v;
-            break;
-        }
-    }
-}
-
-static void asm_expr_logic(TCCState *s1, ExprValue *pe)
-{
-    int op;
-    ExprValue e2;
-
-    asm_expr_prod(s1, pe);
-    for(;;) {
-        op = tok;
-        if (op != '&' && op != '|' && op != '^')
-            break;
-        next();
-        asm_expr_prod(s1, &e2);
-        if (pe->sym || e2.sym)
-            error("invalid operation with label");
-        switch(op) {
-        case '&':
-            pe->v &= e2.v;
-            break;
-        case '|':  
-            pe->v |= e2.v;
-            break;
-        default:
-        case '^':
-            pe->v ^= e2.v;
-            break;
-        }
-    }
-}
-
-static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
-{
-    int op;
-    ExprValue e2;
-
-    asm_expr_logic(s1, pe);
-    for(;;) {
-        op = tok;
-        if (op != '+' && op != '-')
-            break;
-        next();
-        asm_expr_logic(s1, &e2);
-        if (op == '+') {
-            if (pe->sym != NULL && e2.sym != NULL)
-                goto cannot_relocate;
-            pe->v += e2.v;
-            if (pe->sym == NULL && e2.sym != NULL)
-                pe->sym = e2.sym;
-        } else {
-            pe->v -= e2.v;
-            /* NOTE: we are less powerful than gas in that case
-               because we store only one symbol in the expression */
-            if (!pe->sym && !e2.sym) {
-                /* OK */
-            } else if (pe->sym && !e2.sym) {
-                /* OK */
-            } else if (pe->sym && e2.sym) {
-                if (pe->sym == e2.sym) { 
-                    /* OK */
-                } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {
-                    /* we also accept defined symbols in the same section */
-                    pe->v += (long)pe->sym->next - (long)e2.sym->next;
-                } else {
-                    goto cannot_relocate;
-                }
-                pe->sym = NULL; /* same symbols can be substracted to NULL */
-            } else {
-            cannot_relocate:
-                error("invalid operation with label");
-            }
-        }
-    }
-}
-
-static void asm_expr(TCCState *s1, ExprValue *pe)
-{
-    asm_expr_sum(s1, pe);
-}
-
-static int asm_int_expr(TCCState *s1)
-{
-    ExprValue e;
-    asm_expr(s1, &e);
-    if (e.sym)
-        expect("constant");
-    return e.v;
-}
-
-/* NOTE: the same name space as C labels is used to avoid using too
-   much memory when storing labels in TokenStrings */
-static void asm_new_label1(TCCState *s1, int label, int is_local,
-                           int sh_num, int value)
-{
-    Sym *sym;
-
-    sym = label_find(label);
-    if (sym) {
-        if (sym->r) {
-            /* the label is already defined */
-            if (!is_local) {
-                error("assembler label '%s' already defined", 
-                      get_tok_str(label, NULL));
-            } else {
-                /* redefinition of local labels is possible */
-                goto new_label;
-            }
-        }
-    } else {
-    new_label:
-        sym = label_push(&s1->asm_labels, label, 0);
-        sym->type.t = VT_STATIC | VT_VOID;
-    }
-    sym->r = sh_num;
-    sym->next = (void *)value;
-}
-
-static void asm_new_label(TCCState *s1, int label, int is_local)
-{
-    asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind);
-}
-
-static void asm_free_labels(TCCState *st)
-{
-    Sym *s, *s1;
-    Section *sec;
-    
-    for(s = st->asm_labels; s != NULL; s = s1) {
-        s1 = s->prev;
-        /* define symbol value in object file */
-        if (s->r) {
-            if (s->r == SHN_ABS)
-                sec = SECTION_ABS;
-            else
-                sec = st->sections[s->r];
-            put_extern_sym2(s, sec, (long)s->next, 0, 0);
-        }
-        /* remove label */
-        table_ident[s->v - TOK_IDENT]->sym_label = NULL;
-        sym_free(s);
-    }
-    st->asm_labels = NULL;
-}
-
-static void use_section1(TCCState *s1, Section *sec)
-{
-    cur_text_section->data_offset = ind;
-    cur_text_section = sec;
-    ind = cur_text_section->data_offset;
-}
-
-static void use_section(TCCState *s1, const char *name)
-{
-    Section *sec;
-    sec = find_section(s1, name);
-    use_section1(s1, sec);
-}
-
-static void asm_parse_directive(TCCState *s1)
-{
-    int n, offset, v, size, tok1;
-    Section *sec;
-    uint8_t *ptr;
-
-    /* assembler directive */
-    next();
-    sec = cur_text_section;
-    switch(tok) {
-    case TOK_ASM_align:
-    case TOK_ASM_skip:
-    case TOK_ASM_space:
-        tok1 = tok;
-        next();
-        n = asm_int_expr(s1);
-        if (tok1 == TOK_ASM_align) {
-            if (n < 0 || (n & (n-1)) != 0)
-                error("alignment must be a positive power of two");
-            offset = (ind + n - 1) & -n;
-            size = offset - ind;
-            /* the section must have a compatible alignment */
-            if (sec->sh_addralign < n)
-                sec->sh_addralign = n;
-        } else {
-            size = n;
-        }
-        v = 0;
-        if (tok == ',') {
-            next();
-            v = asm_int_expr(s1);
-        }
-    zero_pad:
-        if (sec->sh_type != SHT_NOBITS) {
-            sec->data_offset = ind;
-            ptr = section_ptr_add(sec, size);
-            memset(ptr, v, size);
-        }
-        ind += size;
-        break;
-    case TOK_ASM_quad:
-        next();
-        for(;;) {
-            uint64_t vl;
-            const char *p;
-
-            p = tokc.cstr->data;
-            if (tok != TOK_PPNUM) {
-            error_constant:
-                error("64 bit constant");
-            }
-            vl = strtoll(p, (char **)&p, 0);
-            if (*p != '\0')
-                goto error_constant;
-            next();
-            if (sec->sh_type != SHT_NOBITS) {
-                /* XXX: endianness */
-                gen_le32(vl);
-                gen_le32(vl >> 32);
-            } else {
-                ind += 8;
-            }
-            if (tok != ',')
-                break;
-            next();
-        }
-        break;
-    case TOK_ASM_byte:
-        size = 1;
-        goto asm_data;
-    case TOK_ASM_word:
-    case TOK_SHORT:
-        size = 2;
-        goto asm_data;
-    case TOK_LONG:
-    case TOK_INT:
-        size = 4;
-    asm_data:
-        next();
-        for(;;) {
-            ExprValue e;
-            asm_expr(s1, &e);
-            if (sec->sh_type != SHT_NOBITS) {
-                if (size == 4) {
-                    gen_expr32(&e);
-                } else {
-                    if (e.sym)
-                        expect("constant");
-                    if (size == 1)
-                        g(e.v);
-                    else
-                        gen_le16(e.v);
-                }
-            } else {
-                ind += size;
-            }
-            if (tok != ',')
-                break;
-            next();
-        }
-        break;
-    case TOK_ASM_fill:
-        {
-            int repeat, size, val, i, j;
-            uint8_t repeat_buf[8];
-            next();
-            repeat = asm_int_expr(s1);
-            if (repeat < 0) {
-                error("repeat < 0; .fill ignored");
-                break;
-            }
-            size = 1;
-            val = 0;
-            if (tok == ',') {
-                next();
-                size = asm_int_expr(s1);
-                if (size < 0) {
-                    error("size < 0; .fill ignored");
-                    break;
-                }
-                if (size > 8)
-                    size = 8;
-                if (tok == ',') {
-                    next();
-                    val = asm_int_expr(s1);
-                }
-            }
-            /* XXX: endianness */
-            repeat_buf[0] = val;
-            repeat_buf[1] = val >> 8;
-            repeat_buf[2] = val >> 16;
-            repeat_buf[3] = val >> 24;
-            repeat_buf[4] = 0;
-            repeat_buf[5] = 0;
-            repeat_buf[6] = 0;
-            repeat_buf[7] = 0;
-            for(i = 0; i < repeat; i++) {
-                for(j = 0; j < size; j++) {
-                    g(repeat_buf[j]);
-                }
-            }
-        }
-        break;
-    case TOK_ASM_org:
-        {
-            unsigned long n;
-            next();
-            /* XXX: handle section symbols too */
-            n = asm_int_expr(s1);
-            if (n < ind)
-                error("attempt to .org backwards");
-            v = 0;
-            size = n - ind;
-            goto zero_pad;
-        }
-        break;
-    case TOK_ASM_globl:
-    case TOK_ASM_global:
-	{ 
-            Sym *sym;
-
-            next();
-            sym = label_find(tok);
-            if (!sym) {
-                sym = label_push(&s1->asm_labels, tok, 0);
-                sym->type.t = VT_VOID;
-            }
-            sym->type.t &= ~VT_STATIC;
-            next();
-	}
-	break;
-    case TOK_ASM_string:
-    case TOK_ASM_ascii:
-    case TOK_ASM_asciz:
-        {
-            const uint8_t *p;
-            int i, size, t;
-
-            t = tok;
-            next();
-            for(;;) {
-                if (tok != TOK_STR)
-                    expect("string constant");
-                p = tokc.cstr->data;
-                size = tokc.cstr->size;
-                if (t == TOK_ASM_ascii && size > 0)
-                    size--;
-                for(i = 0; i < size; i++)
-                    g(p[i]);
-                next();
-                if (tok == ',') {
-                    next();
-                } else if (tok != TOK_STR) {
-                    break;
-                }
-            }
-	}
-	break;
-    case TOK_ASM_text:
-    case TOK_ASM_data:
-    case TOK_ASM_bss:
-	{ 
-            char sname[64];
-            tok1 = tok;
-            n = 0;
-            next();
-            if (tok != ';' && tok != TOK_LINEFEED) {
-		n = asm_int_expr(s1);
-		next();
-            }
-            sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n);
-            use_section(s1, sname);
-	}
-	break;
-    case TOK_SECTION1:
-        {
-            char sname[256];
-
-            /* XXX: support more options */
-            next();
-            sname[0] = '\0';
-            while (tok != ';' && tok != TOK_LINEFEED && tok != ',') {
-                if (tok == TOK_STR)
-                    pstrcat(sname, sizeof(sname), tokc.cstr->data);
-                else
-                    pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL));
-                next();
-            }
-            if (tok == ',') {
-                /* skip section options */
-                next();
-                if (tok != TOK_STR)
-                    expect("string constant");
-                next();
-            }
-            last_text_section = cur_text_section;
-            use_section(s1, sname);
-        }
-        break;
-    case TOK_ASM_previous:
-        { 
-            Section *sec;
-            next();
-            if (!last_text_section)
-                error("no previous section referenced");
-            sec = cur_text_section;
-            use_section1(s1, last_text_section);
-            last_text_section = sec;
-        }
-        break;
-    default:
-        error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
-        break;
-    }
-}
-
-
-/* assemble a file */
-static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
-{
-    int opcode;
-
-#if 0
-    /* print stats about opcodes */
-    {
-        const ASMInstr *pa;
-        int freq[4];
-        int op_vals[500];
-        int nb_op_vals, i, j;
-
-        nb_op_vals = 0;
-        memset(freq, 0, sizeof(freq));
-        for(pa = asm_instrs; pa->sym != 0; pa++) {
-            freq[pa->nb_ops]++;
-            for(i=0;i<pa->nb_ops;i++) {
-                for(j=0;j<nb_op_vals;j++) {
-                    if (pa->op_type[i] == op_vals[j])
-                        goto found;
-                }
-                op_vals[nb_op_vals++] = pa->op_type[i];
-            found: ;
-            }
-        }
-        for(i=0;i<nb_op_vals;i++) {
-            int v = op_vals[i];
-            if ((v & (v - 1)) != 0)
-                printf("%3d: %08x\n", i, v);
-        }
-        printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n",
-               sizeof(asm_instrs), sizeof(asm_instrs) / sizeof(ASMInstr),
-               freq[0], freq[1], freq[2], freq[3]);
-    }
-#endif
-
-    /* XXX: undefine C labels */
-
-    ch = file->buf_ptr[0];
-    tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
-    parse_flags = PARSE_FLAG_ASM_COMMENTS;
-    if (do_preprocess)
-        parse_flags |= PARSE_FLAG_PREPROCESS;
-    next();
-    for(;;) {
-        if (tok == TOK_EOF)
-            break;
-        parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
-    redo:
-        if (tok == '#') {
-            /* horrible gas comment */
-            while (tok != TOK_LINEFEED)
-                next();
-        } else if (tok == '.') {
-            asm_parse_directive(s1);
-        } else if (tok == TOK_PPNUM) {
-            const char *p;
-            int n;
-            p = tokc.cstr->data;
-            n = strtoul(p, (char **)&p, 10);
-            if (*p != '\0')
-                expect("':'");
-            /* new local label */
-            asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
-            next();
-            skip(':');
-            goto redo;
-        } else if (tok >= TOK_IDENT) {
-            /* instruction or label */
-            opcode = tok;
-            next();
-            if (tok == ':') {
-                /* new label */
-                asm_new_label(s1, opcode, 0);
-                next();
-                goto redo;
-            } else if (tok == '=') {
-                int n;
-                next();
-                n = asm_int_expr(s1);
-                asm_new_label1(s1, opcode, 0, SHN_ABS, n);
-                goto redo;
-            } else {
-                asm_opcode(s1, opcode);
-            }
-        }
-        /* end of line */
-        if (tok != ';' && tok != TOK_LINEFEED){
-            expect("end of line");
-        }
-        parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
-        next();
-    }
-
-    asm_free_labels(s1);
-
-    return 0;
-}
-
-/* Assemble the current file */
-static int tcc_assemble(TCCState *s1, int do_preprocess)
-{
-    Sym *define_start;
-    int ret;
-
-    preprocess_init(s1);
-
-    /* default section is text */
-    cur_text_section = text_section;
-    ind = cur_text_section->data_offset;
-
-    define_start = define_stack;
-
-    ret = tcc_assemble_internal(s1, do_preprocess);
-
-    cur_text_section->data_offset = ind;
-
-    free_defines(define_start); 
-
-    return ret;
-}
-
-/********************************************************************/
-/* GCC inline asm support */
-
-/* assemble the string 'str' in the current C compilation unit without
-   C preprocessing. NOTE: str is modified by modifying the '\0' at the
-   end */
-static void tcc_assemble_inline(TCCState *s1, char *str, int len)
-{
-    BufferedFile *bf, *saved_file;
-    int saved_parse_flags, *saved_macro_ptr;
-
-    bf = tcc_malloc(sizeof(BufferedFile));
-    memset(bf, 0, sizeof(BufferedFile));
-    bf->fd = -1;
-    bf->buf_ptr = str;
-    bf->buf_end = str + len;
-    str[len] = CH_EOB;
-    /* same name as current file so that errors are correctly
-       reported */
-    pstrcpy(bf->filename, sizeof(bf->filename), file->filename);
-    bf->line_num = file->line_num;
-    saved_file = file;
-    file = bf;
-    saved_parse_flags = parse_flags;
-    saved_macro_ptr = macro_ptr;
-    macro_ptr = NULL;
-    
-    tcc_assemble_internal(s1, 0);
-
-    parse_flags = saved_parse_flags;
-    macro_ptr = saved_macro_ptr;
-    file = saved_file;
-    tcc_free(bf);
-}
-
-/* find a constraint by its number or id (gcc 3 extended
-   syntax). return -1 if not found. Return in *pp in char after the
-   constraint */
-static int find_constraint(ASMOperand *operands, int nb_operands, 
-                           const char *name, const char **pp)
-{
-    int index;
-    TokenSym *ts;
-    const char *p;
-
-    if (isnum(*name)) {
-        index = 0;
-        while (isnum(*name)) {
-            index = (index * 10) + (*name) - '0';
-            name++;
-        }
-        if ((unsigned)index >= nb_operands)
-            index = -1;
-    } else if (*name == '[') {
-        name++;
-        p = strchr(name, ']');
-        if (p) {
-            ts = tok_alloc(name, p - name);
-            for(index = 0; index < nb_operands; index++) {
-                if (operands[index].id == ts->tok)
-                    goto found;
-            }
-            index = -1;
-        found:
-            name = p + 1;
-        } else {
-            index = -1;
-        }
-    } else {
-        index = -1;
-    }
-    if (pp)
-        *pp = name;
-    return index;
-}
-
-static void subst_asm_operands(ASMOperand *operands, int nb_operands, 
-                               int nb_outputs,
-                               CString *out_str, CString *in_str)
-{
-    int c, index, modifier;
-    const char *str;
-    ASMOperand *op;
-    SValue sv;
-
-    cstr_new(out_str);
-    str = in_str->data;
-    for(;;) {
-        c = *str++;
-        if (c == '%') {
-            if (*str == '%') {
-                str++;
-                goto add_char;
-            }
-            modifier = 0;
-            if (*str == 'c' || *str == 'n' ||
-                *str == 'b' || *str == 'w' || *str == 'h')
-                modifier = *str++;
-            index = find_constraint(operands, nb_operands, str, &str);
-            if (index < 0)
-                error("invalid operand reference after %%");
-            op = &operands[index];
-            sv = *op->vt;
-            if (op->reg >= 0) {
-                sv.r = op->reg;
-                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL && op->is_memory)
-                    sv.r |= VT_LVAL;
-            }
-            subst_asm_operand(out_str, &sv, modifier);
-        } else {
-        add_char:
-            cstr_ccat(out_str, c);
-            if (c == '\0')
-                break;
-        }
-    }
-}
-
-
-static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
-                               int is_output)
-{
-    ASMOperand *op;
-    int nb_operands;
-
-    if (tok != ':') {
-        nb_operands = *nb_operands_ptr;
-        for(;;) {
-            if (nb_operands >= MAX_ASM_OPERANDS)
-                error("too many asm operands");
-            op = &operands[nb_operands++];
-            op->id = 0;
-            if (tok == '[') {
-                next();
-                if (tok < TOK_IDENT)
-                    expect("identifier");
-                op->id = tok;
-                next();
-                skip(']');
-            }
-            if (tok != TOK_STR)
-                expect("string constant");
-            op->constraint = tcc_malloc(tokc.cstr->size);
-            strcpy(op->constraint, tokc.cstr->data);
-            next();
-            skip('(');
-            gexpr();
-            if (is_output) {
-                test_lvalue();
-            } else {
-                /* we want to avoid LLOCAL case, except when the 'm'
-                   constraint is used. Note that it may come from
-                   register storage, so we need to convert (reg)
-                   case */
-                if ((vtop->r & VT_LVAL) &&
-                    ((vtop->r & VT_VALMASK) == VT_LLOCAL ||
-                     (vtop->r & VT_VALMASK) < VT_CONST) &&
-                    !strchr(op->constraint, 'm')) {
-                    gv(RC_INT);
-                }
-            }
-            op->vt = vtop;
-            skip(')');
-            if (tok == ',') {
-                next();
-            } else {
-                break;
-            }
-        }
-        *nb_operands_ptr = nb_operands;
-    }
-}
-
-static void parse_asm_str(CString *astr)
-{
-    skip('(');
-    /* read the string */
-    if (tok != TOK_STR)
-        expect("string constant");
-    cstr_new(astr);
-    while (tok == TOK_STR) {
-        /* XXX: add \0 handling too ? */
-        cstr_cat(astr, tokc.cstr->data);
-        next();
-    }
-    cstr_ccat(astr, '\0');
-}
-
-/* parse the GCC asm() instruction */
-static void asm_instr(void)
-{
-    CString astr, astr1;
-    ASMOperand operands[MAX_ASM_OPERANDS];
-    int nb_inputs, nb_outputs, nb_operands, i, must_subst, out_reg;
-    uint8_t clobber_regs[NB_ASM_REGS];
-
-    next();
-    /* since we always generate the asm() instruction, we can ignore
-       volatile */
-    if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) {
-        next();
-    }
-    parse_asm_str(&astr);
-    nb_operands = 0;
-    nb_outputs = 0;
-    must_subst = 0;
-    memset(clobber_regs, 0, sizeof(clobber_regs));
-    if (tok == ':') {
-        next();
-        must_subst = 1;
-        /* output args */
-        parse_asm_operands(operands, &nb_operands, 1);
-        nb_outputs = nb_operands;
-        if (tok == ':') {
-            next();
-            if (tok != ')') {
-                /* input args */
-                parse_asm_operands(operands, &nb_operands, 0);
-                if (tok == ':') {
-                    /* clobber list */
-                    /* XXX: handle registers */
-                    next();
-                    for(;;) {
-                        if (tok != TOK_STR)
-                            expect("string constant");
-                        asm_clobber(clobber_regs, tokc.cstr->data);
-                        next();
-                        if (tok == ',') {
-                            next();
-                        } else {
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-    }
-    skip(')');
-    /* NOTE: we do not eat the ';' so that we can restore the current
-       token after the assembler parsing */
-    if (tok != ';')
-        expect("';'");
-    nb_inputs = nb_operands - nb_outputs;
-    
-    /* save all values in the memory */
-    save_regs(0);
-
-    /* compute constraints */
-    asm_compute_constraints(operands, nb_operands, nb_outputs, 
-                            clobber_regs, &out_reg);
-
-    /* substitute the operands in the asm string. No substitution is
-       done if no operands (GCC behaviour) */
-#ifdef ASM_DEBUG
-    printf("asm: \"%s\"\n", (char *)astr.data);
-#endif
-    if (must_subst) {
-        subst_asm_operands(operands, nb_operands, nb_outputs, &astr1, &astr);
-        cstr_free(&astr);
-    } else {
-        astr1 = astr;
-    }
-#ifdef ASM_DEBUG
-    printf("subst_asm: \"%s\"\n", (char *)astr1.data);
-#endif
-
-    /* generate loads */
-    asm_gen_code(operands, nb_operands, nb_outputs, 0, 
-                 clobber_regs, out_reg);    
-
-    /* assemble the string with tcc internal assembler */
-    tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1);
-
-    /* restore the current C token */
-    next();
-
-    /* store the output values if needed */
-    asm_gen_code(operands, nb_operands, nb_outputs, 1, 
-                 clobber_regs, out_reg);
-    
-    /* free everything */
-    for(i=0;i<nb_operands;i++) {
-        ASMOperand *op;
-        op = &operands[i];
-        tcc_free(op->constraint);
-        vpop();
-    }
-    cstr_free(&astr1);
-}
-
-static void asm_global_instr(void)
-{
-    CString astr;
-
-    next();
-    parse_asm_str(&astr);
-    skip(')');
-    /* NOTE: we do not eat the ';' so that we can restore the current
-       token after the assembler parsing */
-    if (tok != ';')
-        expect("';'");
-    
-#ifdef ASM_DEBUG
-    printf("asm_global: \"%s\"\n", (char *)astr.data);
-#endif
-    cur_text_section = text_section;
-    ind = cur_text_section->data_offset;
-
-    /* assemble the string with tcc internal assembler */
-    tcc_assemble_inline(tcc_state, astr.data, astr.size - 1);
-    
-    cur_text_section->data_offset = ind;
-
-    /* restore the current C token */
-    next();
-
-    cstr_free(&astr);
-}

+ 0 - 957
src/modules/native/tcc/libtcc/tcccoff.c

@@ -1,957 +0,0 @@
-/*
- *  COFF file handling for TCC
- * 
- *  Copyright (c) 2003, 2004 TK
- *  Copyright (c) 2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include "coff.h"
-
-#define MAXNSCNS 255		/* MAXIMUM NUMBER OF SECTIONS         */
-#define MAX_STR_TABLE 1000000
-AOUTHDR o_filehdr;		/* OPTIONAL (A.OUT) FILE HEADER       */
-
-SCNHDR section_header[MAXNSCNS];
-
-#define MAX_FUNCS 1000
-#define MAX_FUNC_NAME_LENGTH 128
-
-int nFuncs;
-char Func[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
-char AssociatedFile[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
-int LineNoFilePtr[MAX_FUNCS];
-int EndAddress[MAX_FUNCS];
-int LastLineNo[MAX_FUNCS];
-int FuncEntries[MAX_FUNCS];
-
-BOOL OutputTheSection(Section * sect);
-short int GetCoffFlags(const char *s);
-void SortSymbolTable(void);
-Section *FindSection(TCCState * s1, const char *sname);
-
-int C67_main_entry_point;
-
-int FindCoffSymbolIndex(const char *func_name);
-int nb_syms;
-
-typedef struct {
-    long tag;
-    long size;
-    long fileptr;
-    long nextsym;
-    short int dummy;
-} AUXFUNC;
-
-typedef struct {
-    long regmask;
-    unsigned short lineno;
-    unsigned short nentries;
-    int localframe;
-    int nextentry;
-    short int dummy;
-} AUXBF;
-
-typedef struct {
-    long dummy;
-    unsigned short lineno;
-    unsigned short dummy1;
-    int dummy2;
-    int dummy3;
-    unsigned short dummy4;
-} AUXEF;
-
-int tcc_output_coff(TCCState *s1, FILE *f)
-{
-    Section *tcc_sect;
-    SCNHDR *coff_sec;
-    int file_pointer;
-    char *Coff_str_table, *pCoff_str_table;
-    int CoffTextSectionNo, coff_nb_syms;
-    FILHDR file_hdr;		/* FILE HEADER STRUCTURE              */
-    Section *stext, *sdata, *sbss;
-    int i, NSectionsToOutput = 0;
-
-    Coff_str_table = pCoff_str_table = NULL;
-
-    stext = FindSection(s1, ".text");
-    sdata = FindSection(s1, ".data");
-    sbss = FindSection(s1, ".bss");
-
-    nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
-    coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1");
-
-    file_hdr.f_magic = COFF_C67_MAGIC;	/* magic number */
-    file_hdr.f_timdat = 0;	/* time & date stamp */
-    file_hdr.f_opthdr = sizeof(AOUTHDR);	/* sizeof(optional hdr) */
-    file_hdr.f_flags = 0x1143;	/* flags (copied from what code composer does) */
-    file_hdr.f_TargetID = 0x99;	/* for C6x = 0x0099 */
-
-    o_filehdr.magic = 0x0108;	/* see magic.h                          */
-    o_filehdr.vstamp = 0x0190;	/* version stamp                        */
-    o_filehdr.tsize = stext->data_offset;	/* text size in bytes, padded to FW bdry */
-    o_filehdr.dsize = sdata->data_offset;	/* initialized data "  "                */
-    o_filehdr.bsize = sbss->data_offset;	/* uninitialized data "   "             */
-    o_filehdr.entrypt = C67_main_entry_point;	/* entry pt.                          */
-    o_filehdr.text_start = stext->sh_addr;	/* base of text used for this file      */
-    o_filehdr.data_start = sdata->sh_addr;	/* base of data used for this file      */
-
-
-    // create all the section headers
-
-    file_pointer = FILHSZ + sizeof(AOUTHDR);
-
-    CoffTextSectionNo = -1;
-
-    for (i = 1; i < s1->nb_sections; i++) {
-	coff_sec = &section_header[i];
-	tcc_sect = s1->sections[i];
-
-	if (OutputTheSection(tcc_sect)) {
-	    NSectionsToOutput++;
-
-	    if (CoffTextSectionNo == -1 && tcc_sect == stext)
-		CoffTextSectionNo = NSectionsToOutput;	// rem which coff sect number the .text sect is
-
-	    strcpy(coff_sec->s_name, tcc_sect->name);	/* section name */
-
-	    coff_sec->s_paddr = tcc_sect->sh_addr;	/* physical address */
-	    coff_sec->s_vaddr = tcc_sect->sh_addr;	/* virtual address */
-	    coff_sec->s_size = tcc_sect->data_offset;	/* section size */
-	    coff_sec->s_scnptr = 0;	/* file ptr to raw data for section */
-	    coff_sec->s_relptr = 0;	/* file ptr to relocation */
-	    coff_sec->s_lnnoptr = 0;	/* file ptr to line numbers */
-	    coff_sec->s_nreloc = 0;	/* number of relocation entries */
-	    coff_sec->s_flags = GetCoffFlags(coff_sec->s_name);	/* flags */
-	    coff_sec->s_reserved = 0;	/* reserved byte */
-	    coff_sec->s_page = 0;	/* memory page id */
-
-	    file_pointer += sizeof(SCNHDR);
-	}
-    }
-
-    file_hdr.f_nscns = NSectionsToOutput;	/* number of sections */
-
-    // now loop through and determine file pointer locations
-    // for the raw data
-
-
-    for (i = 1; i < s1->nb_sections; i++) {
-	coff_sec = &section_header[i];
-	tcc_sect = s1->sections[i];
-
-	if (OutputTheSection(tcc_sect)) {
-	    // put raw data
-	    coff_sec->s_scnptr = file_pointer;	/* file ptr to raw data for section */
-	    file_pointer += coff_sec->s_size;
-	}
-    }
-
-    // now loop through and determine file pointer locations
-    // for the relocation data
-
-    for (i = 1; i < s1->nb_sections; i++) {
-	coff_sec = &section_header[i];
-	tcc_sect = s1->sections[i];
-
-	if (OutputTheSection(tcc_sect)) {
-	    // put relocations data
-	    if (coff_sec->s_nreloc > 0) {
-		coff_sec->s_relptr = file_pointer;	/* file ptr to relocation */
-		file_pointer += coff_sec->s_nreloc * sizeof(struct reloc);
-	    }
-	}
-    }
-
-    // now loop through and determine file pointer locations
-    // for the line number data
-
-    for (i = 1; i < s1->nb_sections; i++) {
-	coff_sec = &section_header[i];
-	tcc_sect = s1->sections[i];
-
-	coff_sec->s_nlnno = 0;
-	coff_sec->s_lnnoptr = 0;
-
-	if (s1->do_debug && tcc_sect == stext) {
-	    // count how many line nos data
-
-	    // also find association between source file name and function
-	    // so we can sort the symbol table
-
-
-	    Stab_Sym *sym, *sym_end;
-	    char func_name[MAX_FUNC_NAME_LENGTH],
-		last_func_name[MAX_FUNC_NAME_LENGTH];
-	    unsigned long func_addr, last_pc, pc;
-	    const char *incl_files[INCLUDE_STACK_SIZE];
-	    int incl_index, len, last_line_num;
-	    const char *str, *p;
-
-	    coff_sec->s_lnnoptr = file_pointer;	/* file ptr to linno */
-
-
-	    func_name[0] = '\0';
-	    func_addr = 0;
-	    incl_index = 0;
-	    last_func_name[0] = '\0';
-	    last_pc = 0xffffffff;
-	    last_line_num = 1;
-	    sym = (Stab_Sym *) stab_section->data + 1;
-	    sym_end =
-		(Stab_Sym *) (stab_section->data +
-			      stab_section->data_offset);
-
-	    nFuncs = 0;
-	    while (sym < sym_end) {
-		switch (sym->n_type) {
-		    /* function start or end */
-		case N_FUN:
-		    if (sym->n_strx == 0) {
-			// end of function
-
-			coff_sec->s_nlnno++;
-			file_pointer += LINESZ;
-
-			pc = sym->n_value + func_addr;
-			func_name[0] = '\0';
-			func_addr = 0;
-			EndAddress[nFuncs] = pc;
-			FuncEntries[nFuncs] =
-			    (file_pointer -
-			     LineNoFilePtr[nFuncs]) / LINESZ - 1;
-			LastLineNo[nFuncs++] = last_line_num + 1;
-		    } else {
-			// beginning of function
-
-			LineNoFilePtr[nFuncs] = file_pointer;
-			coff_sec->s_nlnno++;
-			file_pointer += LINESZ;
-
-			str =
-			    (const char *) stabstr_section->data +
-			    sym->n_strx;
-
-			p = strchr(str, ':');
-			if (!p) {
-			    pstrcpy(func_name, sizeof(func_name), str);
-			    pstrcpy(Func[nFuncs], sizeof(func_name), str);
-			} else {
-			    len = p - str;
-			    if (len > sizeof(func_name) - 1)
-				len = sizeof(func_name) - 1;
-			    memcpy(func_name, str, len);
-			    memcpy(Func[nFuncs], str, len);
-			    func_name[len] = '\0';
-			}
-
-			// save the file that it came in so we can sort later
-			pstrcpy(AssociatedFile[nFuncs], sizeof(func_name),
-				incl_files[incl_index - 1]);
-
-			func_addr = sym->n_value;
-		    }
-		    break;
-
-		    /* line number info */
-		case N_SLINE:
-		    pc = sym->n_value + func_addr;
-
-		    last_pc = pc;
-		    last_line_num = sym->n_desc;
-
-		    /* XXX: slow! */
-		    strcpy(last_func_name, func_name);
-
-		    coff_sec->s_nlnno++;
-		    file_pointer += LINESZ;
-		    break;
-		    /* include files */
-		case N_BINCL:
-		    str =
-			(const char *) stabstr_section->data + sym->n_strx;
-		  add_incl:
-		    if (incl_index < INCLUDE_STACK_SIZE) {
-			incl_files[incl_index++] = str;
-		    }
-		    break;
-		case N_EINCL:
-		    if (incl_index > 1)
-			incl_index--;
-		    break;
-		case N_SO:
-		    if (sym->n_strx == 0) {
-			incl_index = 0;	/* end of translation unit */
-		    } else {
-			str =
-			    (const char *) stabstr_section->data +
-			    sym->n_strx;
-			/* do not add path */
-			len = strlen(str);
-			if (len > 0 && str[len - 1] != '/')
-			    goto add_incl;
-		    }
-		    break;
-		}
-		sym++;
-	    }
-	}
-
-    }
-
-    file_hdr.f_symptr = file_pointer;	/* file pointer to symtab */
-
-    if (s1->do_debug)
-	file_hdr.f_nsyms = coff_nb_syms;	/* number of symtab entries */
-    else
-	file_hdr.f_nsyms = 0;
-
-    file_pointer += file_hdr.f_nsyms * SYMNMLEN;
-
-    // OK now we are all set to write the file
-
-
-    fwrite(&file_hdr, FILHSZ, 1, f);
-    fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);
-
-    // write section headers
-    for (i = 1; i < s1->nb_sections; i++) {
-	coff_sec = &section_header[i];
-	tcc_sect = s1->sections[i];
-
-	if (OutputTheSection(tcc_sect)) {
-	    fwrite(coff_sec, sizeof(SCNHDR), 1, f);
-	}
-    }
-
-    // write raw data
-    for (i = 1; i < s1->nb_sections; i++) {
-	coff_sec = &section_header[i];
-	tcc_sect = s1->sections[i];
-
-	if (OutputTheSection(tcc_sect)) {
-	    fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
-	}
-    }
-
-    // write relocation data
-    for (i = 1; i < s1->nb_sections; i++) {
-	coff_sec = &section_header[i];
-	tcc_sect = s1->sections[i];
-
-	if (OutputTheSection(tcc_sect)) {
-	    // put relocations data
-	    if (coff_sec->s_nreloc > 0) {
-		fwrite(tcc_sect->reloc,
-		       coff_sec->s_nreloc * sizeof(struct reloc), 1, f);
-	    }
-	}
-    }
-
-
-    // group the symbols in order of filename, func1, func2, etc
-    // finally global symbols
-
-    if (s1->do_debug)
-	SortSymbolTable();
-
-    // write line no data
-
-    for (i = 1; i < s1->nb_sections; i++) {
-	coff_sec = &section_header[i];
-	tcc_sect = s1->sections[i];
-
-	if (s1->do_debug && tcc_sect == stext) {
-	    // count how many line nos data
-
-
-	    Stab_Sym *sym, *sym_end;
-	    char func_name[128], last_func_name[128];
-	    unsigned long func_addr, last_pc, pc;
-	    const char *incl_files[INCLUDE_STACK_SIZE];
-	    int incl_index, len, last_line_num;
-	    const char *str, *p;
-
-	    LINENO CoffLineNo;
-
-	    func_name[0] = '\0';
-	    func_addr = 0;
-	    incl_index = 0;
-	    last_func_name[0] = '\0';
-	    last_pc = 0;
-	    last_line_num = 1;
-	    sym = (Stab_Sym *) stab_section->data + 1;
-	    sym_end =
-		(Stab_Sym *) (stab_section->data +
-			      stab_section->data_offset);
-
-	    while (sym < sym_end) {
-		switch (sym->n_type) {
-		    /* function start or end */
-		case N_FUN:
-		    if (sym->n_strx == 0) {
-			// end of function
-
-			CoffLineNo.l_addr.l_paddr = last_pc;
-			CoffLineNo.l_lnno = last_line_num + 1;
-			fwrite(&CoffLineNo, 6, 1, f);
-
-			pc = sym->n_value + func_addr;
-			func_name[0] = '\0';
-			func_addr = 0;
-		    } else {
-			// beginning of function
-
-			str =
-			    (const char *) stabstr_section->data +
-			    sym->n_strx;
-
-
-			p = strchr(str, ':');
-			if (!p) {
-			    pstrcpy(func_name, sizeof(func_name), str);
-			} else {
-			    len = p - str;
-			    if (len > sizeof(func_name) - 1)
-				len = sizeof(func_name) - 1;
-			    memcpy(func_name, str, len);
-			    func_name[len] = '\0';
-			}
-			func_addr = sym->n_value;
-			last_pc = func_addr;
-			last_line_num = -1;
-
-			// output a function begin
-
-			CoffLineNo.l_addr.l_symndx =
-			    FindCoffSymbolIndex(func_name);
-			CoffLineNo.l_lnno = 0;
-
-			fwrite(&CoffLineNo, 6, 1, f);
-		    }
-		    break;
-
-		    /* line number info */
-		case N_SLINE:
-		    pc = sym->n_value + func_addr;
-
-
-		    /* XXX: slow! */
-		    strcpy(last_func_name, func_name);
-
-		    // output a line reference
-
-		    CoffLineNo.l_addr.l_paddr = last_pc;
-
-		    if (last_line_num == -1) {
-			CoffLineNo.l_lnno = sym->n_desc;
-		    } else {
-			CoffLineNo.l_lnno = last_line_num + 1;
-		    }
-
-		    fwrite(&CoffLineNo, 6, 1, f);
-
-		    last_pc = pc;
-		    last_line_num = sym->n_desc;
-
-		    break;
-
-		    /* include files */
-		case N_BINCL:
-		    str =
-			(const char *) stabstr_section->data + sym->n_strx;
-		  add_incl2:
-		    if (incl_index < INCLUDE_STACK_SIZE) {
-			incl_files[incl_index++] = str;
-		    }
-		    break;
-		case N_EINCL:
-		    if (incl_index > 1)
-			incl_index--;
-		    break;
-		case N_SO:
-		    if (sym->n_strx == 0) {
-			incl_index = 0;	/* end of translation unit */
-		    } else {
-			str =
-			    (const char *) stabstr_section->data +
-			    sym->n_strx;
-			/* do not add path */
-			len = strlen(str);
-			if (len > 0 && str[len - 1] != '/')
-			    goto add_incl2;
-		    }
-		    break;
-		}
-		sym++;
-	    }
-	}
-    }
-
-    // write symbol table
-    if (s1->do_debug) {
-	int k;
-	struct syment csym;
-	AUXFUNC auxfunc;
-	AUXBF auxbf;
-	AUXEF auxef;
-	int i;
-	Elf32_Sym *p;
-	const char *name;
-	int nstr;
-	int n = 0;
-
-	Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE);
-	pCoff_str_table = Coff_str_table;
-	nstr = 0;
-
-	p = (Elf32_Sym *) symtab_section->data;
-
-
-	for (i = 0; i < nb_syms; i++) {
-
-	    name = symtab_section->link->data + p->st_name;
-
-	    for (k = 0; k < 8; k++)
-		csym._n._n_name[k] = 0;
-
-	    if (strlen(name) <= 8) {
-		strcpy(csym._n._n_name, name);
-	    } else {
-		if (pCoff_str_table - Coff_str_table + strlen(name) >
-		    MAX_STR_TABLE - 1)
-		    error("String table too large");
-
-		csym._n._n_n._n_zeroes = 0;
-		csym._n._n_n._n_offset =
-		    pCoff_str_table - Coff_str_table + 4;
-
-		strcpy(pCoff_str_table, name);
-		pCoff_str_table += strlen(name) + 1;	// skip over null
-		nstr++;
-	    }
-
-	    if (p->st_info == 4) {
-		// put a filename symbol
-		csym.n_value = 33;	// ?????
-		csym.n_scnum = N_DEBUG;
-		csym.n_type = 0;
-		csym.n_sclass = C_FILE;
-		csym.n_numaux = 0;
-		fwrite(&csym, 18, 1, f);
-		n++;
-
-	    } else if (p->st_info == 0x12) {
-		// find the function data
-
-		for (k = 0; k < nFuncs; k++) {
-		    if (strcmp(name, Func[k]) == 0)
-			break;
-		}
-
-		if (k >= nFuncs) {
-		    char s[256];
-
-		    sprintf(s, "debug info can't find function: %s", name);
-
-		    error(s);
-		}
-		// put a Function Name
-
-		csym.n_value = p->st_value;	// physical address
-		csym.n_scnum = CoffTextSectionNo;
-		csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0);
-		csym.n_sclass = C_EXT;
-		csym.n_numaux = 1;
-		fwrite(&csym, 18, 1, f);
-
-		// now put aux info
-
-		auxfunc.tag = 0;
-		auxfunc.size = EndAddress[k] - p->st_value;
-		auxfunc.fileptr = LineNoFilePtr[k];
-		auxfunc.nextsym = n + 6;	// tktk
-		auxfunc.dummy = 0;
-		fwrite(&auxfunc, 18, 1, f);
-
-		// put a .bf
-
-		strcpy(csym._n._n_name, ".bf");
-		csym.n_value = p->st_value;	// physical address
-		csym.n_scnum = CoffTextSectionNo;
-		csym.n_type = 0;
-		csym.n_sclass = C_FCN;
-		csym.n_numaux = 1;
-		fwrite(&csym, 18, 1, f);
-
-		// now put aux info
-
-		auxbf.regmask = 0;
-		auxbf.lineno = 0;
-		auxbf.nentries = FuncEntries[k];
-		auxbf.localframe = 0;
-		auxbf.nextentry = n + 6;
-		auxbf.dummy = 0;
-		fwrite(&auxbf, 18, 1, f);
-
-		// put a .ef
-
-		strcpy(csym._n._n_name, ".ef");
-		csym.n_value = EndAddress[k];	// physical address  
-		csym.n_scnum = CoffTextSectionNo;
-		csym.n_type = 0;
-		csym.n_sclass = C_FCN;
-		csym.n_numaux = 1;
-		fwrite(&csym, 18, 1, f);
-
-		// now put aux info
-
-		auxef.dummy = 0;
-		auxef.lineno = LastLineNo[k];
-		auxef.dummy1 = 0;
-		auxef.dummy2 = 0;
-		auxef.dummy3 = 0;
-		auxef.dummy4 = 0;
-		fwrite(&auxef, 18, 1, f);
-
-		n += 6;
-
-	    } else {
-		// try an put some type info
-
-		if ((p->st_other & VT_BTYPE) == VT_DOUBLE) {
-		    csym.n_type = T_DOUBLE;	// int
-		    csym.n_sclass = C_EXT;
-		} else if ((p->st_other & VT_BTYPE) == VT_FLOAT) {
-		    csym.n_type = T_FLOAT;
-		    csym.n_sclass = C_EXT;
-		} else if ((p->st_other & VT_BTYPE) == VT_INT) {
-		    csym.n_type = T_INT;	// int
-		    csym.n_sclass = C_EXT;
-		} else if ((p->st_other & VT_BTYPE) == VT_SHORT) {
-		    csym.n_type = T_SHORT;
-		    csym.n_sclass = C_EXT;
-		} else if ((p->st_other & VT_BTYPE) == VT_BYTE) {
-		    csym.n_type = T_CHAR;
-		    csym.n_sclass = C_EXT;
-		} else {
-		    csym.n_type = T_INT;	// just mark as a label
-		    csym.n_sclass = C_LABEL;
-		}
-
-
-		csym.n_value = p->st_value;
-		csym.n_scnum = 2;
-		csym.n_numaux = 1;
-		fwrite(&csym, 18, 1, f);
-
-		auxfunc.tag = 0;
-		auxfunc.size = 0x20;
-		auxfunc.fileptr = 0;
-		auxfunc.nextsym = 0;
-		auxfunc.dummy = 0;
-		fwrite(&auxfunc, 18, 1, f);
-		n++;
-		n++;
-
-	    }
-
-	    p++;
-	}
-    }
-
-    if (s1->do_debug) {
-	// write string table
-
-	// first write the size
-	i = pCoff_str_table - Coff_str_table;
-	fwrite(&i, 4, 1, f);
-
-	// then write the strings
-	fwrite(Coff_str_table, i, 1, f);
-
-	tcc_free(Coff_str_table);
-    }
-
-    return 0;
-}
-
-
-
-// group the symbols in order of filename, func1, func2, etc
-// finally global symbols
-
-void SortSymbolTable(void)
-{
-    int i, j, k, n = 0;
-    Elf32_Sym *p, *p2, *NewTable;
-    char *name, *name2;
-
-    NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));
-
-    p = (Elf32_Sym *) symtab_section->data;
-
-
-    // find a file symbol, copy it over
-    // then scan the whole symbol list and copy any function
-    // symbols that match the file association
-
-    for (i = 0; i < nb_syms; i++) {
-	if (p->st_info == 4) {
-	    name = (char *) symtab_section->link->data + p->st_name;
-
-	    // this is a file symbol, copy it over
-
-	    NewTable[n++] = *p;
-
-	    p2 = (Elf32_Sym *) symtab_section->data;
-
-	    for (j = 0; j < nb_syms; j++) {
-		if (p2->st_info == 0x12) {
-		    // this is a func symbol
-
-		    name2 =
-			(char *) symtab_section->link->data + p2->st_name;
-
-		    // find the function data index
-
-		    for (k = 0; k < nFuncs; k++) {
-			if (strcmp(name2, Func[k]) == 0)
-			    break;
-		    }
-
-		    if (k >= nFuncs) {
-			char s[256];
-
-			sprintf(s,
-				"debug (sort) info can't find function: %s",
-				name2);
-
-			error(s);
-		    }
-
-		    if (strcmp(AssociatedFile[k], name) == 0) {
-			// yes they match copy it over
-
-			NewTable[n++] = *p2;
-		    }
-		}
-		p2++;
-	    }
-	}
-	p++;
-    }
-
-    // now all the filename and func symbols should have been copied over
-    // copy all the rest over (all except file and funcs)
-
-    p = (Elf32_Sym *) symtab_section->data;
-    for (i = 0; i < nb_syms; i++) {
-	if (p->st_info != 4 && p->st_info != 0x12) {
-	    NewTable[n++] = *p;
-	}
-	p++;
-    }
-
-    if (n != nb_syms)
-	error("Internal Compiler error, debug info");
-
-    // copy it all back
-
-    p = (Elf32_Sym *) symtab_section->data;
-    for (i = 0; i < nb_syms; i++) {
-	*p++ = NewTable[i];
-    }
-
-    tcc_free(NewTable);
-}
-
-
-int FindCoffSymbolIndex(const char *func_name)
-{
-    int i, n = 0;
-    Elf32_Sym *p;
-    char *name;
-
-    p = (Elf32_Sym *) symtab_section->data;
-
-    for (i = 0; i < nb_syms; i++) {
-
-	name = (char *) symtab_section->link->data + p->st_name;
-
-	if (p->st_info == 4) {
-	    // put a filename symbol
-	    n++;
-	} else if (p->st_info == 0x12) {
-
-	    if (strcmp(func_name, name) == 0)
-		return n;
-
-	    n += 6;
-
-	    // put a Function Name
-
-	    // now put aux info
-
-	    // put a .bf
-
-	    // now put aux info
-
-	    // put a .ef
-
-	    // now put aux info
-
-	} else {
-	    n += 2;
-	}
-
-	p++;
-    }
-
-    return n;			// total number of symbols
-}
-
-BOOL OutputTheSection(Section * sect)
-{
-    const char *s = sect->name;
-
-    if (!strcmp(s, ".text"))
-	return true;
-    else if (!strcmp(s, ".data"))
-	return true;
-    else
-	return 0;
-}
-
-short int GetCoffFlags(const char *s)
-{
-    if (!strcmp(s, ".text"))
-	return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400;
-    else if (!strcmp(s, ".data"))
-	return STYP_DATA;
-    else if (!strcmp(s, ".bss"))
-	return STYP_BSS;
-    else if (!strcmp(s, ".stack"))
-	return STYP_BSS | STYP_ALIGN | 0x200;
-    else if (!strcmp(s, ".cinit"))
-	return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200;
-    else
-	return 0;
-}
-
-Section *FindSection(TCCState * s1, const char *sname)
-{
-    Section *s;
-    int i;
-
-    for (i = 1; i < s1->nb_sections; i++) {
-	s = s1->sections[i];
-
-	if (!strcmp(sname, s->name))
-	    return s;
-    }
-
-    error("could not find section %s", sname);
-    return 0;
-}
-
-int tcc_load_coff(TCCState * s1, int fd)
-{
-// tktk TokenSym *ts;
-
-    FILE *f;
-    unsigned int str_size;
-    char *Coff_str_table, *name;
-    int i, k;
-    struct syment csym;
-    char name2[9];
-    FILHDR file_hdr;		/* FILE HEADER STRUCTURE              */
-
-    f = fdopen(fd, "rb");
-    if (!f) {
-	error("Unable to open .out file for input");
-    }
-
-    if (fread(&file_hdr, FILHSZ, 1, f) != 1)
-	error("error reading .out file for input");
-
-    if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
-	error("error reading .out file for input");
-
-    // first read the string table
-
-    if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))
-	error("error reading .out file for input");
-
-    if (fread(&str_size, sizeof(int), 1, f) != 1)
-	error("error reading .out file for input");
-
-
-    Coff_str_table = (char *) tcc_malloc(str_size);
-
-    if (fread(Coff_str_table, str_size - 4, 1, f) != 1)
-	error("error reading .out file for input");
-
-    // read/process all the symbols
-
-    // seek back to symbols
-
-    if (fseek(f, file_hdr.f_symptr, SEEK_SET))
-	error("error reading .out file for input");
-
-    for (i = 0; i < file_hdr.f_nsyms; i++) {
-	if (fread(&csym, SYMESZ, 1, f) != 1)
-	    error("error reading .out file for input");
-
-	if (csym._n._n_n._n_zeroes == 0) {
-	    name = Coff_str_table + csym._n._n_n._n_offset - 4;
-	} else {
-	    name = csym._n._n_name;
-
-	    if (name[7] != 0) {
-		for (k = 0; k < 8; k++)
-		    name2[k] = name[k];
-
-		name2[8] = 0;
-
-		name = name2;
-	    }
-	}
-//              if (strcmp("_DAC_Buffer",name)==0)  // tktk
-//                      name[0]=0;
-
-	if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) ||	// structures
-	    (csym.n_type == 0x18 && csym.n_sclass == 0x2) ||	// pointer to structure
-	    (csym.n_type == 0x7 && csym.n_sclass == 0x2) ||	// doubles
-	    (csym.n_type == 0x6 && csym.n_sclass == 0x2))	// floats
-	{
-	    // strip off any leading underscore (except for other main routine)
-
-	    if (name[0] == '_' && strcmp(name, "_main") != 0)
-		name++;
-
-	    tcc_add_symbol(s1, name, (void*)csym.n_value);
-	}
-	// skip any aux records
-
-	if (csym.n_numaux == 1) {
-	    if (fread(&csym, SYMESZ, 1, f) != 1)
-		error("error reading .out file for input");
-	    i++;
-	}
-    }
-
-    return 0;
-}

+ 0 - 2732
src/modules/native/tcc/libtcc/tccelf.c

@@ -1,2732 +0,0 @@
-/*
- *  ELF file handling for TCC
- * 
- *  Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifdef TCC_TARGET_X86_64
-#define ElfW_Rel ElfW(Rela)
-#define SHT_RELX SHT_RELA
-#define REL_SECTION_FMT ".rela%s"
-/* x86-64 requires PLT for DLLs */
-#define TCC_OUTPUT_DLL_WITH_PLT
-#else
-#define ElfW_Rel ElfW(Rel)
-#define SHT_RELX SHT_REL
-#define REL_SECTION_FMT ".rel%s"
-#endif
-
-/* XXX: DLL with PLT would only work with x86-64 for now */
-//#define TCC_OUTPUT_DLL_WITH_PLT
-
-static int put_elf_str(Section *s, const char *sym)
-{
-    int offset, len;
-    char *ptr;
-
-    len = strlen(sym) + 1;
-    offset = s->data_offset;
-    ptr = section_ptr_add(s, len);
-    memcpy(ptr, sym, len);
-    return offset;
-}
-
-/* elf symbol hashing function */
-static unsigned long elf_hash(const unsigned char *name)
-{
-    unsigned long h = 0, g;
-    
-    while (*name) {
-        h = (h << 4) + *name++;
-        g = h & 0xf0000000;
-        if (g)
-            h ^= g >> 24;
-        h &= ~g;
-    }
-    return h;
-}
-
-/* rebuild hash table of section s */
-/* NOTE: we do factorize the hash table code to go faster */
-static void rebuild_hash(Section *s, unsigned int nb_buckets)
-{
-    ElfW(Sym) *sym;
-    int *ptr, *hash, nb_syms, sym_index, h;
-    char *strtab;
-
-    strtab = s->link->data;
-    nb_syms = s->data_offset / sizeof(ElfW(Sym));
-
-    s->hash->data_offset = 0;
-    ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
-    ptr[0] = nb_buckets;
-    ptr[1] = nb_syms;
-    ptr += 2;
-    hash = ptr;
-    memset(hash, 0, (nb_buckets + 1) * sizeof(int));
-    ptr += nb_buckets + 1;
-
-    sym = (ElfW(Sym) *)s->data + 1;
-    for(sym_index = 1; sym_index < nb_syms; sym_index++) {
-        if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
-            h = elf_hash(strtab + sym->st_name) % nb_buckets;
-            *ptr = hash[h];
-            hash[h] = sym_index;
-        } else {
-            *ptr = 0;
-        }
-        ptr++;
-        sym++;
-    }
-}
-
-/* return the symbol number */
-static int put_elf_sym(Section *s, 
-                       unsigned long value, unsigned long size,
-                       int info, int other, int shndx, const char *name)
-{
-    int name_offset, sym_index;
-    int nbuckets, h;
-    ElfW(Sym) *sym;
-    Section *hs;
-    
-    sym = section_ptr_add(s, sizeof(ElfW(Sym)));
-    if (name)
-        name_offset = put_elf_str(s->link, name);
-    else
-        name_offset = 0;
-    /* XXX: endianness */
-    sym->st_name = name_offset;
-    sym->st_value = value;
-    sym->st_size = size;
-    sym->st_info = info;
-    sym->st_other = other;
-    sym->st_shndx = shndx;
-    sym_index = sym - (ElfW(Sym) *)s->data;
-    hs = s->hash;
-    if (hs) {
-        int *ptr, *base;
-        ptr = section_ptr_add(hs, sizeof(int));
-        base = (int *)hs->data;
-        /* only add global or weak symbols */
-        if (ELFW(ST_BIND)(info) != STB_LOCAL) {
-            /* add another hashing entry */
-            nbuckets = base[0];
-            h = elf_hash(name) % nbuckets;
-            *ptr = base[2 + h];
-            base[2 + h] = sym_index;
-            base[1]++;
-            /* we resize the hash table */
-            hs->nb_hashed_syms++;
-            if (hs->nb_hashed_syms > 2 * nbuckets) {
-                rebuild_hash(s, 2 * nbuckets);
-            }
-        } else {
-            *ptr = 0;
-            base[1]++;
-        }
-    }
-    return sym_index;
-}
-
-/* find global ELF symbol 'name' and return its index. Return 0 if not
-   found. */
-static int find_elf_sym(Section *s, const char *name)
-{
-    ElfW(Sym) *sym;
-    Section *hs;
-    int nbuckets, sym_index, h;
-    const char *name1;
-    
-    hs = s->hash;
-    if (!hs)
-        return 0;
-    nbuckets = ((int *)hs->data)[0];
-    h = elf_hash(name) % nbuckets;
-    sym_index = ((int *)hs->data)[2 + h];
-    while (sym_index != 0) {
-        sym = &((ElfW(Sym) *)s->data)[sym_index];
-        name1 = s->link->data + sym->st_name;
-        if (!strcmp(name, name1))
-            return sym_index;
-        sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
-    }
-    return 0;
-}
-
-/* return elf symbol value or error */
-void *tcc_get_symbol(TCCState *s, const char *name)
-{
-    int sym_index;
-    ElfW(Sym) *sym;
-    sym_index = find_elf_sym(symtab_section, name);
-    if (!sym_index)
-        return NULL;
-    sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
-    return (void*)(long)sym->st_value;
-}
-
-void *tcc_get_symbol_err(TCCState *s, const char *name)
-{
-    void *sym;
-    sym = tcc_get_symbol(s, name);
-    if (!sym)
-        error("%s not defined", name);
-    return sym;
-}
-
-/* add an elf symbol : check if it is already defined and patch
-   it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
-static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
-                       int info, int other, int sh_num, const char *name)
-{
-    ElfW(Sym) *esym;
-    int sym_bind, sym_index, sym_type, esym_bind;
-    unsigned char sym_vis, esym_vis, new_vis;
-
-    sym_bind = ELFW(ST_BIND)(info);
-    sym_type = ELFW(ST_TYPE)(info);
-    sym_vis = ELFW(ST_VISIBILITY)(other);
-        
-    if (sym_bind != STB_LOCAL) {
-        /* we search global or weak symbols */
-        sym_index = find_elf_sym(s, name);
-        if (!sym_index)
-            goto do_def;
-        esym = &((ElfW(Sym) *)s->data)[sym_index];
-        if (esym->st_shndx != SHN_UNDEF) {
-            esym_bind = ELFW(ST_BIND)(esym->st_info);
-            /* propagate the most constraining visibility */
-            /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
-            esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
-            if (esym_vis == STV_DEFAULT) {
-                new_vis = sym_vis;
-            } else if (sym_vis == STV_DEFAULT) {
-                new_vis = esym_vis;
-            } else {
-                new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
-            }
-            esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
-                             | new_vis;
-            other = esym->st_other; /* in case we have to patch esym */
-            if (sh_num == SHN_UNDEF) {
-                /* ignore adding of undefined symbol if the
-                   corresponding symbol is already defined */
-            } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
-                /* global overrides weak, so patch */
-                goto do_patch;
-            } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
-                /* weak is ignored if already global */
-            } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
-                /* ignore hidden symbols after */
-            } else if (esym->st_shndx == SHN_COMMON && sh_num < SHN_LORESERVE) {
-                /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
-                   No idea if this is the correct solution ... */
-                goto do_patch;
-            } else if (s == tcc_state->dynsymtab_section) {
-                /* we accept that two DLL define the same symbol */
-            } else {
-#if 1
-                printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
-                       sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
-#endif
-                error_noabort("'%s' defined twice", name);
-            }
-        } else {
-        do_patch:
-            esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
-            esym->st_shndx = sh_num;
-            esym->st_value = value;
-            esym->st_size = size;
-            esym->st_other = other;
-        }
-    } else {
-    do_def:
-        sym_index = put_elf_sym(s, value, size, 
-                                ELFW(ST_INFO)(sym_bind, sym_type), other, 
-                                sh_num, name);
-    }
-    return sym_index;
-}
-
-/* put relocation */
-static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
-                          int type, int symbol)
-{
-    char buf[256];
-    Section *sr;
-    ElfW_Rel *rel;
-
-    sr = s->reloc;
-    if (!sr) {
-        /* if no relocation section, create it */
-        snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
-        /* if the symtab is allocated, then we consider the relocation
-           are also */
-        sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
-        sr->sh_entsize = sizeof(ElfW_Rel);
-        sr->link = symtab;
-        sr->sh_info = s->sh_num;
-        s->reloc = sr;
-    }
-    rel = section_ptr_add(sr, sizeof(ElfW_Rel));
-    rel->r_offset = offset;
-    rel->r_info = ELFW(R_INFO)(symbol, type);
-#ifdef TCC_TARGET_X86_64
-    rel->r_addend = 0;
-#endif
-}
-
-/* put stab debug information */
-
-typedef struct {
-    unsigned int n_strx;         /* index into string table of name */
-    unsigned char n_type;         /* type of symbol */
-    unsigned char n_other;        /* misc info (usually empty) */
-    unsigned short n_desc;        /* description field */
-    unsigned int n_value;        /* value of symbol */
-} Stab_Sym;
-
-static void put_stabs(const char *str, int type, int other, int desc, 
-                      unsigned long value)
-{
-    Stab_Sym *sym;
-
-    sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
-    if (str) {
-        sym->n_strx = put_elf_str(stabstr_section, str);
-    } else {
-        sym->n_strx = 0;
-    }
-    sym->n_type = type;
-    sym->n_other = other;
-    sym->n_desc = desc;
-    sym->n_value = value;
-}
-
-static void put_stabs_r(const char *str, int type, int other, int desc, 
-                        unsigned long value, Section *sec, int sym_index)
-{
-    put_stabs(str, type, other, desc, value);
-    put_elf_reloc(symtab_section, stab_section, 
-                  stab_section->data_offset - sizeof(unsigned int),
-                  R_DATA_32, sym_index);
-}
-
-static void put_stabn(int type, int other, int desc, int value)
-{
-    put_stabs(NULL, type, other, desc, value);
-}
-
-static void put_stabd(int type, int other, int desc)
-{
-    put_stabs(NULL, type, other, desc, 0);
-}
-
-/* In an ELF file symbol table, the local symbols must appear below
-   the global and weak ones. Since TCC cannot sort it while generating
-   the code, we must do it after. All the relocation tables are also
-   modified to take into account the symbol table sorting */
-static void sort_syms(TCCState *s1, Section *s)
-{
-    int *old_to_new_syms;
-    ElfW(Sym) *new_syms;
-    int nb_syms, i;
-    ElfW(Sym) *p, *q;
-    ElfW_Rel *rel, *rel_end;
-    Section *sr;
-    int type, sym_index;
-
-    nb_syms = s->data_offset / sizeof(ElfW(Sym));
-    new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
-    old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
-
-    /* first pass for local symbols */
-    p = (ElfW(Sym) *)s->data;
-    q = new_syms;
-    for(i = 0; i < nb_syms; i++) {
-        if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
-            old_to_new_syms[i] = q - new_syms;
-            *q++ = *p;
-        }
-        p++;
-    }
-    /* save the number of local symbols in section header */
-    s->sh_info = q - new_syms;
-
-    /* then second pass for non local symbols */
-    p = (ElfW(Sym) *)s->data;
-    for(i = 0; i < nb_syms; i++) {
-        if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
-            old_to_new_syms[i] = q - new_syms;
-            *q++ = *p;
-        }
-        p++;
-    }
-    
-    /* we copy the new symbols to the old */
-    memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
-    tcc_free(new_syms);
-
-    /* now we modify all the relocations */
-    for(i = 1; i < s1->nb_sections; i++) {
-        sr = s1->sections[i];
-        if (sr->sh_type == SHT_RELX && sr->link == s) {
-            rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
-            for(rel = (ElfW_Rel *)sr->data;
-                rel < rel_end;
-                rel++) {
-                sym_index = ELFW(R_SYM)(rel->r_info);
-                type = ELFW(R_TYPE)(rel->r_info);
-                sym_index = old_to_new_syms[sym_index];
-                rel->r_info = ELFW(R_INFO)(sym_index, type);
-            }
-        }
-    }
-    
-    tcc_free(old_to_new_syms);
-}
-
-/* relocate common symbols in the .bss section */
-static void relocate_common_syms(void)
-{
-    ElfW(Sym) *sym, *sym_end;
-    unsigned long offset, align;
-    
-    sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
-    for(sym = (ElfW(Sym) *)symtab_section->data + 1; 
-        sym < sym_end;
-        sym++) {
-        if (sym->st_shndx == SHN_COMMON) {
-            /* align symbol */
-            align = sym->st_value;
-            offset = bss_section->data_offset;
-            offset = (offset + align - 1) & -align;
-            sym->st_value = offset;
-            sym->st_shndx = bss_section->sh_num;
-            offset += sym->st_size;
-            bss_section->data_offset = offset;
-        }
-    }
-}
-
-/* relocate symbol table, resolve undefined symbols if do_resolve is
-   true and output error if undefined symbol. */
-static void relocate_syms(TCCState *s1, int do_resolve)
-{
-    ElfW(Sym) *sym, *esym, *sym_end;
-    int sym_bind, sh_num, sym_index;
-    const char *name;
-    unsigned long addr;
-
-    sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
-    for(sym = (ElfW(Sym) *)symtab_section->data + 1; 
-        sym < sym_end;
-        sym++) {
-        sh_num = sym->st_shndx;
-        if (sh_num == SHN_UNDEF) {
-            name = strtab_section->data + sym->st_name;
-            if (do_resolve) {
-                name = symtab_section->link->data + sym->st_name;
-                addr = (unsigned long)resolve_sym(s1, name, ELFW(ST_TYPE)(sym->st_info));
-                if (addr) {
-                    sym->st_value = addr;
-                    goto found;
-                }
-            } else if (s1->dynsym) {
-                /* if dynamic symbol exist, then use it */
-                sym_index = find_elf_sym(s1->dynsym, name);
-                if (sym_index) {
-                    esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
-                    sym->st_value = esym->st_value;
-                    goto found;
-                }
-            }
-            /* XXX: _fp_hw seems to be part of the ABI, so we ignore
-               it */
-            if (!strcmp(name, "_fp_hw"))
-                goto found;
-            /* only weak symbols are accepted to be undefined. Their
-               value is zero */
-            sym_bind = ELFW(ST_BIND)(sym->st_info);
-            if (sym_bind == STB_WEAK) {
-                sym->st_value = 0;
-            } else {
-                error_noabort("undefined symbol '%s'", name);
-            }
-        } else if (sh_num < SHN_LORESERVE) {
-            /* add section base */
-            sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
-        }
-    found: ;
-    }
-}
-
-#ifdef TCC_TARGET_X86_64
-#define JMP_TABLE_ENTRY_SIZE 14
-static unsigned long add_jmp_table(TCCState *s1, unsigned long val)
-{
-    char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
-    s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
-    /* jmp *0x0(%rip) */
-    p[0] = 0xff;
-    p[1] = 0x25;
-    *(int *)(p + 2) = 0;
-    *(unsigned long *)(p + 6) = val;
-    return (unsigned long)p;
-}
-
-static unsigned long add_got_table(TCCState *s1, unsigned long val)
-{
-    unsigned long *p =(unsigned long *)(s1->runtime_plt_and_got +
-                                        s1->runtime_plt_and_got_offset);
-    s1->runtime_plt_and_got_offset += sizeof(void *);
-    *p = val;
-    return (unsigned long)p;
-}
-#endif
-
-/* relocate a given section (CPU dependent) */
-static void relocate_section(TCCState *s1, Section *s)
-{
-    Section *sr;
-    ElfW_Rel *rel, *rel_end, *qrel;
-    ElfW(Sym) *sym;
-    int type, sym_index;
-    unsigned char *ptr;
-    unsigned long val, addr;
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
-    int esym_index;
-#endif
-
-    sr = s->reloc;
-    rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
-    qrel = (ElfW_Rel *)sr->data;
-    for(rel = qrel;
-        rel < rel_end;
-        rel++) {
-        ptr = s->data + rel->r_offset;
-
-        sym_index = ELFW(R_SYM)(rel->r_info);
-        sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
-        val = sym->st_value;
-#ifdef TCC_TARGET_X86_64
-        /* XXX: not tested */
-        val += rel->r_addend;
-#endif
-        type = ELFW(R_TYPE)(rel->r_info);
-        addr = s->sh_addr + rel->r_offset;
-
-        /* CPU specific */
-        switch(type) {
-#if defined(TCC_TARGET_I386)
-        case R_386_32:
-            if (s1->output_type == TCC_OUTPUT_DLL) {
-                esym_index = s1->symtab_to_dynsym[sym_index];
-                qrel->r_offset = rel->r_offset;
-                if (esym_index) {
-                    qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
-                    qrel++;
-                    break;
-                } else {
-                    qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
-                    qrel++;
-                }
-            }
-            *(int *)ptr += val;
-            break;
-        case R_386_PC32:
-            if (s1->output_type == TCC_OUTPUT_DLL) {
-                /* DLL relocation */
-                esym_index = s1->symtab_to_dynsym[sym_index];
-                if (esym_index) {
-                    qrel->r_offset = rel->r_offset;
-                    qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
-                    qrel++;
-                    break;
-                }
-            }
-            *(int *)ptr += val - addr;
-            break;
-        case R_386_PLT32:
-            *(int *)ptr += val - addr;
-            break;
-        case R_386_GLOB_DAT:
-        case R_386_JMP_SLOT:
-            *(int *)ptr = val;
-            break;
-        case R_386_GOTPC:
-            *(int *)ptr += s1->got->sh_addr - addr;
-            break;
-        case R_386_GOTOFF:
-            *(int *)ptr += val - s1->got->sh_addr;
-            break;
-        case R_386_GOT32:
-            /* we load the got offset */
-            *(int *)ptr += s1->got_offsets[sym_index];
-            break;
-#elif defined(TCC_TARGET_ARM)
-        case R_ARM_PC24:
-        case R_ARM_CALL:
-        case R_ARM_JUMP24:
-        case R_ARM_PLT32:
-            {
-                int x;
-                x = (*(int *)ptr)&0xffffff;
-                (*(int *)ptr) &= 0xff000000;
-                if (x & 0x800000)
-                    x -= 0x1000000;
-                x *= 4;
-                x += val - addr;
-                if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
-                    error("can't relocate value at %x",addr);
-                x >>= 2;
-                x &= 0xffffff;
-                (*(int *)ptr) |= x;
-            }
-            break;
-        case R_ARM_PREL31:
-            {
-                int x;
-                x = (*(int *)ptr) & 0x7fffffff;
-                (*(int *)ptr) &= 0x80000000;
-                x = (x * 2) / 2;
-                x += val - addr;
-                if((x^(x>>1))&0x40000000)
-                    error("can't relocate value at %x",addr);
-                (*(int *)ptr) |= x & 0x7fffffff;
-            }
-        case R_ARM_ABS32:
-            *(int *)ptr += val;
-            break;
-        case R_ARM_BASE_PREL:
-            *(int *)ptr += s1->got->sh_addr - addr;
-            break;
-        case R_ARM_GOTOFF32:
-            *(int *)ptr += val - s1->got->sh_addr;
-            break;
-        case R_ARM_GOT_BREL:
-            /* we load the got offset */
-            *(int *)ptr += s1->got_offsets[sym_index];
-            break;
-        case R_ARM_COPY:
-            break;
-        default:
-            fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
-                    type,addr,(unsigned int )ptr,val);
-            break;
-#elif defined(TCC_TARGET_C67)
-        case R_C60_32:
-            *(int *)ptr += val;
-            break;
-        case R_C60LO16:
-            {
-                uint32_t orig;
-                
-                /* put the low 16 bits of the absolute address */
-                // add to what is already there
-                
-                orig  =   ((*(int *)(ptr  )) >> 7) & 0xffff;
-                orig |=  (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
-                
-                //patch both at once - assumes always in pairs Low - High
-                
-                *(int *) ptr    = (*(int *) ptr    & (~(0xffff << 7)) ) |  (((val+orig)      & 0xffff) << 7);
-                *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
-            }
-            break;
-        case R_C60HI16:
-            break;
-        default:
-            fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
-                    type,addr,(unsigned int )ptr,val);
-            break;
-#elif defined(TCC_TARGET_X86_64)
-        case R_X86_64_64:
-            if (s1->output_type == TCC_OUTPUT_DLL) {
-                qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
-                qrel->r_addend = *(long long *)ptr + val;
-                qrel++;
-            }
-            *(long long *)ptr += val;
-            break;
-        case R_X86_64_32:
-        case R_X86_64_32S:
-            if (s1->output_type == TCC_OUTPUT_DLL) {
-                /* XXX: this logic may depend on TCC's codegen
-                   now TCC uses R_X86_64_32 even for a 64bit pointer */
-                qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
-                qrel->r_addend = *(int *)ptr + val;
-                qrel++;
-            }
-            *(int *)ptr += val;
-            break;
-        case R_X86_64_PC32: {
-            if (s1->output_type == TCC_OUTPUT_DLL) {
-                /* DLL relocation */
-                esym_index = s1->symtab_to_dynsym[sym_index];
-                if (esym_index) {
-                    qrel->r_offset = rel->r_offset;
-                    qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
-                    qrel->r_addend = *(int *)ptr;
-                    qrel++;
-                    break;
-                }
-            }
-            long diff = val - addr;
-            if (diff <= -2147483647 || diff > 2147483647) {
-                /* XXX: naive support for over 32bit jump */
-                if (s1->output_type == TCC_OUTPUT_MEMORY) {
-                    val = add_jmp_table(s1, val);
-                    diff = val - addr;
-                }
-                if (diff <= -2147483647 || diff > 2147483647) {
-                    error("internal error: relocation failed");
-                }
-            }
-            *(int *)ptr += diff;
-        }
-            break;
-        case R_X86_64_PLT32:
-            *(int *)ptr += val - addr;
-            break;
-        case R_X86_64_GLOB_DAT:
-        case R_X86_64_JUMP_SLOT:
-            *(int *)ptr = val;
-            break;
-        case R_X86_64_GOTPCREL:
-            if (s1->output_type == TCC_OUTPUT_MEMORY) {
-                val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
-                *(int *)ptr += val - addr;
-                break;
-            }
-            *(int *)ptr += (s1->got->sh_addr - addr +
-                            s1->got_offsets[sym_index] - 4);
-            break;
-        case R_X86_64_GOTTPOFF:
-            *(int *)ptr += val - s1->got->sh_addr;
-            break;
-        case R_X86_64_GOT32:
-            /* we load the got offset */
-            *(int *)ptr += s1->got_offsets[sym_index];
-            break;
-#else
-#error unsupported processor
-#endif
-        }
-    }
-    /* if the relocation is allocated, we change its symbol table */
-    if (sr->sh_flags & SHF_ALLOC)
-        sr->link = s1->dynsym;
-}
-
-/* relocate relocation table in 'sr' */
-static void relocate_rel(TCCState *s1, Section *sr)
-{
-    Section *s;
-    ElfW_Rel *rel, *rel_end;
-    
-    s = s1->sections[sr->sh_info];
-    rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
-    for(rel = (ElfW_Rel *)sr->data;
-        rel < rel_end;
-        rel++) {
-        rel->r_offset += s->sh_addr;
-    }
-}
-
-/* count the number of dynamic relocations so that we can reserve
-   their space */
-static int prepare_dynamic_rel(TCCState *s1, Section *sr)
-{
-    ElfW_Rel *rel, *rel_end;
-    int sym_index, esym_index, type, count;
-
-    count = 0;
-    rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
-    for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
-        sym_index = ELFW(R_SYM)(rel->r_info);
-        type = ELFW(R_TYPE)(rel->r_info);
-        switch(type) {
-#if defined(TCC_TARGET_I386)
-        case R_386_32:
-#elif defined(TCC_TARGET_X86_64)
-        case R_X86_64_32:
-        case R_X86_64_32S:
-        case R_X86_64_64:
-#endif
-            count++;
-            break;
-#if defined(TCC_TARGET_I386)
-        case R_386_PC32:
-#elif defined(TCC_TARGET_X86_64)
-        case R_X86_64_PC32:
-#endif
-            esym_index = s1->symtab_to_dynsym[sym_index];
-            if (esym_index)
-                count++;
-            break;
-        default:
-            break;
-        }
-    }
-    if (count) {
-        /* allocate the section */
-        sr->sh_flags |= SHF_ALLOC;
-        sr->sh_size = count * sizeof(ElfW_Rel);
-    }
-    return count;
-}
-
-static void put_got_offset(TCCState *s1, int index, unsigned long val)
-{
-    int n;
-    unsigned long *tab;
-
-    if (index >= s1->nb_got_offsets) {
-        /* find immediately bigger power of 2 and reallocate array */
-        n = 1;
-        while (index >= n)
-            n *= 2;
-        tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
-        if (!tab)
-            error("memory full");
-        s1->got_offsets = tab;
-        memset(s1->got_offsets + s1->nb_got_offsets, 0,
-               (n - s1->nb_got_offsets) * sizeof(unsigned long));
-        s1->nb_got_offsets = n;
-    }
-    s1->got_offsets[index] = val;
-}
-
-/* XXX: suppress that */
-static void put32(unsigned char *p, uint32_t val)
-{
-    p[0] = val;
-    p[1] = val >> 8;
-    p[2] = val >> 16;
-    p[3] = val >> 24;
-}
-
-#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
-    defined(TCC_TARGET_X86_64)
-static uint32_t get32(unsigned char *p)
-{
-    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-}
-#endif
-
-static void build_got(TCCState *s1)
-{
-    unsigned char *ptr;
-
-    /* if no got, then create it */
-    s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
-    s1->got->sh_entsize = 4;
-    add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT), 
-                0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
-    ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
-#if PTR_SIZE == 4
-    /* keep space for _DYNAMIC pointer, if present */
-    put32(ptr, 0);
-    /* two dummy got entries */
-    put32(ptr + 4, 0);
-    put32(ptr + 8, 0);
-#else
-    /* keep space for _DYNAMIC pointer, if present */
-    put32(ptr, 0);
-    put32(ptr + 4, 0);
-    /* two dummy got entries */
-    put32(ptr + 8, 0);
-    put32(ptr + 12, 0);
-    put32(ptr + 16, 0);
-    put32(ptr + 20, 0);
-#endif
-}
-
-/* put a got entry corresponding to a symbol in symtab_section. 'size'
-   and 'info' can be modifed if more precise info comes from the DLL */
-static void put_got_entry(TCCState *s1,
-                          int reloc_type, unsigned long size, int info, 
-                          int sym_index)
-{
-    int index;
-    const char *name;
-    ElfW(Sym) *sym;
-    unsigned long offset;
-    int *ptr;
-
-    if (!s1->got)
-        build_got(s1);
-
-    /* if a got entry already exists for that symbol, no need to add one */
-    if (sym_index < s1->nb_got_offsets &&
-        s1->got_offsets[sym_index] != 0)
-        return;
-    
-    put_got_offset(s1, sym_index, s1->got->data_offset);
-
-    if (s1->dynsym) {
-        sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
-        name = symtab_section->link->data + sym->st_name;
-        offset = sym->st_value;
-#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
-        if (reloc_type ==
-#ifdef TCC_TARGET_X86_64
-            R_X86_64_JUMP_SLOT
-#else
-            R_386_JMP_SLOT
-#endif
-            ) {
-            Section *plt;
-            uint8_t *p;
-            int modrm;
-
-#if defined(TCC_OUTPUT_DLL_WITH_PLT)
-            modrm = 0x25;
-#else
-            /* if we build a DLL, we add a %ebx offset */
-            if (s1->output_type == TCC_OUTPUT_DLL)
-                modrm = 0xa3;
-            else
-                modrm = 0x25;
-#endif
-
-            /* add a PLT entry */
-            plt = s1->plt;
-            if (plt->data_offset == 0) {
-                /* first plt entry */
-                p = section_ptr_add(plt, 16);
-                p[0] = 0xff; /* pushl got + PTR_SIZE */
-                p[1] = modrm + 0x10;
-                put32(p + 2, PTR_SIZE);
-                p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
-                p[7] = modrm;
-                put32(p + 8, PTR_SIZE * 2);
-            }
-
-            p = section_ptr_add(plt, 16);
-            p[0] = 0xff; /* jmp *(got + x) */
-            p[1] = modrm;
-            put32(p + 2, s1->got->data_offset);
-            p[6] = 0x68; /* push $xxx */
-            put32(p + 7, (plt->data_offset - 32) >> 1);
-            p[11] = 0xe9; /* jmp plt_start */
-            put32(p + 12, -(plt->data_offset));
-
-            /* the symbol is modified so that it will be relocated to
-               the PLT */
-#if !defined(TCC_OUTPUT_DLL_WITH_PLT)
-            if (s1->output_type == TCC_OUTPUT_EXE)
-#endif
-                offset = plt->data_offset - 16;
-        }
-#elif defined(TCC_TARGET_ARM)
-        if (reloc_type == R_ARM_JUMP_SLOT) {
-            Section *plt;
-            uint8_t *p;
-            
-            /* if we build a DLL, we add a %ebx offset */
-            if (s1->output_type == TCC_OUTPUT_DLL)
-                error("DLLs unimplemented!");
-
-            /* add a PLT entry */
-            plt = s1->plt;
-            if (plt->data_offset == 0) {
-                /* first plt entry */
-                p = section_ptr_add(plt, 16);
-                put32(p     , 0xe52de004);
-                put32(p +  4, 0xe59fe010);
-                put32(p +  8, 0xe08fe00e);
-                put32(p + 12, 0xe5bef008);
-            }
-
-            p = section_ptr_add(plt, 16);
-            put32(p  , 0xe59fc004);
-            put32(p+4, 0xe08fc00c);
-            put32(p+8, 0xe59cf000);
-            put32(p+12, s1->got->data_offset);
-
-            /* the symbol is modified so that it will be relocated to
-               the PLT */
-            if (s1->output_type == TCC_OUTPUT_EXE)
-                offset = plt->data_offset - 16;
-        }
-#elif defined(TCC_TARGET_C67)
-        error("C67 got not implemented");
-#else
-#error unsupported CPU
-#endif
-        index = put_elf_sym(s1->dynsym, offset, 
-                            size, info, 0, sym->st_shndx, name);
-        /* put a got entry */
-        put_elf_reloc(s1->dynsym, s1->got, 
-                      s1->got->data_offset, 
-                      reloc_type, index);
-    }
-    ptr = section_ptr_add(s1->got, PTR_SIZE);
-    *ptr = 0;
-}
-
-/* build GOT and PLT entries */
-static void build_got_entries(TCCState *s1)
-{
-    Section *s, *symtab;
-    ElfW_Rel *rel, *rel_end;
-    ElfW(Sym) *sym;
-    int i, type, reloc_type, sym_index;
-
-    for(i = 1; i < s1->nb_sections; i++) {
-        s = s1->sections[i];
-        if (s->sh_type != SHT_RELX)
-            continue;
-        /* no need to handle got relocations */
-        if (s->link != symtab_section)
-            continue;
-        symtab = s->link;
-        rel_end = (ElfW_Rel *)(s->data + s->data_offset);
-        for(rel = (ElfW_Rel *)s->data;
-            rel < rel_end;
-            rel++) {
-            type = ELFW(R_TYPE)(rel->r_info);
-            switch(type) {
-#if defined(TCC_TARGET_I386)
-            case R_386_GOT32:
-            case R_386_GOTOFF:
-            case R_386_GOTPC:
-            case R_386_PLT32:
-                if (!s1->got)
-                    build_got(s1);
-                if (type == R_386_GOT32 || type == R_386_PLT32) {
-                    sym_index = ELFW(R_SYM)(rel->r_info);
-                    sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
-                    /* look at the symbol got offset. If none, then add one */
-                    if (type == R_386_GOT32)
-                        reloc_type = R_386_GLOB_DAT;
-                    else
-                        reloc_type = R_386_JMP_SLOT;
-                    put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 
-                                  sym_index);
-                }
-                break;
-#elif defined(TCC_TARGET_ARM)
-            case R_ARM_GOT_BREL:
-            case R_ARM_GOTOFF32:
-            case R_ARM_BASE_PREL:
-            case R_ARM_PLT32:
-                if (!s1->got)
-                    build_got(s1);
-                if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
-                    sym_index = ELFW(R_SYM)(rel->r_info);
-                    sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
-                    /* look at the symbol got offset. If none, then add one */
-                    if (type == R_ARM_GOT_BREL)
-                        reloc_type = R_ARM_GLOB_DAT;
-                    else
-                        reloc_type = R_ARM_JUMP_SLOT;
-                    put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 
-                                  sym_index);
-                }
-                break;
-#elif defined(TCC_TARGET_C67)
-            case R_C60_GOT32:
-            case R_C60_GOTOFF:
-            case R_C60_GOTPC:
-            case R_C60_PLT32:
-                if (!s1->got)
-                    build_got(s1);
-                if (type == R_C60_GOT32 || type == R_C60_PLT32) {
-                    sym_index = ELFW(R_SYM)(rel->r_info);
-                    sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
-                    /* look at the symbol got offset. If none, then add one */
-                    if (type == R_C60_GOT32)
-                        reloc_type = R_C60_GLOB_DAT;
-                    else
-                        reloc_type = R_C60_JMP_SLOT;
-                    put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 
-                                  sym_index);
-                }
-                break;
-#elif defined(TCC_TARGET_X86_64)
-            case R_X86_64_GOT32:
-            case R_X86_64_GOTTPOFF:
-            case R_X86_64_GOTPCREL:
-            case R_X86_64_PLT32:
-                if (!s1->got)
-                    build_got(s1);
-                if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
-                    type == R_X86_64_PLT32) {
-                    sym_index = ELFW(R_SYM)(rel->r_info);
-                    sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
-                    /* look at the symbol got offset. If none, then add one */
-                    if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
-                        reloc_type = R_X86_64_GLOB_DAT;
-                    else
-                        reloc_type = R_X86_64_JUMP_SLOT;
-                    put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 
-                                  sym_index);
-                }
-                break;
-#else
-#error unsupported CPU
-#endif
-            default:
-                break;
-            }
-        }
-    }
-}
-
-static Section *new_symtab(TCCState *s1,
-                           const char *symtab_name, int sh_type, int sh_flags,
-                           const char *strtab_name, 
-                           const char *hash_name, int hash_sh_flags)
-{
-    Section *symtab, *strtab, *hash;
-    int *ptr, nb_buckets;
-
-    symtab = new_section(s1, symtab_name, sh_type, sh_flags);
-    symtab->sh_entsize = sizeof(ElfW(Sym));
-    strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
-    put_elf_str(strtab, "");
-    symtab->link = strtab;
-    put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
-    
-    nb_buckets = 1;
-
-    hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
-    hash->sh_entsize = sizeof(int);
-    symtab->hash = hash;
-    hash->link = symtab;
-
-    ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
-    ptr[0] = nb_buckets;
-    ptr[1] = 1;
-    memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
-    return symtab;
-}
-
-/* put dynamic tag */
-static void put_dt(Section *dynamic, int dt, unsigned long val)
-{
-    ElfW(Dyn) *dyn;
-    dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
-    dyn->d_tag = dt;
-    dyn->d_un.d_val = val;
-}
-
-static void add_init_array_defines(TCCState *s1, const char *section_name)
-{
-    Section *s;
-    long end_offset;
-    char sym_start[1024];
-    char sym_end[1024];
-    
-    snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
-    snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
-
-    s = find_section(s1, section_name);
-    if (!s) {
-        end_offset = 0;
-        s = data_section;
-    } else {
-        end_offset = s->data_offset;
-    }
-
-    add_elf_sym(symtab_section, 
-                0, 0,
-                ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
-                s->sh_num, sym_start);
-    add_elf_sym(symtab_section, 
-                end_offset, 0,
-                ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
-                s->sh_num, sym_end);
-}
-
-/* add tcc runtime libraries */
-static void tcc_add_runtime(TCCState *s1)
-{
-#if defined(CONFIG_TCC_BCHECK) || !defined(CONFIG_USE_LIBGCC)
-    char buf[1024];
-#endif
-
-#ifdef CONFIG_TCC_BCHECK
-    if (s1->do_bounds_check) {
-        unsigned long *ptr;
-        Section *init_section;
-        unsigned char *pinit;
-        int sym_index;
-
-        /* XXX: add an object file to do that */
-        ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
-        *ptr = 0;
-        add_elf_sym(symtab_section, 0, 0, 
-                    ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
-                    bounds_section->sh_num, "__bounds_start");
-        /* add bound check code */
-        snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
-        tcc_add_file(s1, buf);
-#ifdef TCC_TARGET_I386
-        if (s1->output_type != TCC_OUTPUT_MEMORY) {
-            /* add 'call __bound_init()' in .init section */
-            init_section = find_section(s1, ".init");
-            pinit = section_ptr_add(init_section, 5);
-            pinit[0] = 0xe8;
-            put32(pinit + 1, -4);
-            sym_index = find_elf_sym(symtab_section, "__bound_init");
-            put_elf_reloc(symtab_section, init_section, 
-                          init_section->data_offset - 4, R_386_PC32, sym_index);
-        }
-#endif
-    }
-#endif
-    /* add libc */
-    if (!s1->nostdlib) {
-        tcc_add_library(s1, "c");
-
-#ifdef CONFIG_USE_LIBGCC
-        tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
-#else
-        snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
-        tcc_add_file(s1, buf);
-#endif
-    }
-    /* add crt end if not memory output */
-    if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
-        tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
-    }
-}
-
-/* add various standard linker symbols (must be done after the
-   sections are filled (for example after allocating common
-   symbols)) */
-static void tcc_add_linker_symbols(TCCState *s1)
-{
-    char buf[1024];
-    int i;
-    Section *s;
-
-    add_elf_sym(symtab_section, 
-                text_section->data_offset, 0,
-                ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
-                text_section->sh_num, "_etext");
-    add_elf_sym(symtab_section, 
-                data_section->data_offset, 0,
-                ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
-                data_section->sh_num, "_edata");
-    add_elf_sym(symtab_section, 
-                bss_section->data_offset, 0,
-                ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
-                bss_section->sh_num, "_end");
-    /* horrible new standard ldscript defines */
-    add_init_array_defines(s1, ".preinit_array");
-    add_init_array_defines(s1, ".init_array");
-    add_init_array_defines(s1, ".fini_array");
-    
-    /* add start and stop symbols for sections whose name can be
-       expressed in C */
-    for(i = 1; i < s1->nb_sections; i++) {
-        s = s1->sections[i];
-        if (s->sh_type == SHT_PROGBITS &&
-            (s->sh_flags & SHF_ALLOC)) {
-            const char *p;
-            int ch;
-
-            /* check if section name can be expressed in C */
-            p = s->name;
-            for(;;) {
-                ch = *p;
-                if (!ch)
-                    break;
-                if (!isid(ch) && !isnum(ch))
-                    goto next_sec;
-                p++;
-            }
-            snprintf(buf, sizeof(buf), "__start_%s", s->name);
-            add_elf_sym(symtab_section, 
-                        0, 0,
-                        ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
-                        s->sh_num, buf);
-            snprintf(buf, sizeof(buf), "__stop_%s", s->name);
-            add_elf_sym(symtab_section,
-                        s->data_offset, 0,
-                        ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
-                        s->sh_num, buf);
-        }
-    next_sec: ;
-    }
-}
-
-/* name of ELF interpreter */
-#if defined __FreeBSD__
-static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
-#elif defined TCC_ARM_EABI
-static char elf_interp[] = "/lib/ld-linux.so.3";
-#elif defined(TCC_TARGET_X86_64)
-static char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
-#elif defined(TCC_UCLIBC)
-static char elf_interp[] = "/lib/ld-uClibc.so.0";
-#else
-static char elf_interp[] = "/lib/ld-linux.so.2";
-#endif
-
-static void tcc_output_binary(TCCState *s1, FILE *f,
-                              const int *section_order)
-{
-    Section *s;
-    int i, offset, size;
-
-    offset = 0;
-    for(i=1;i<s1->nb_sections;i++) {
-        s = s1->sections[section_order[i]];
-        if (s->sh_type != SHT_NOBITS &&
-            (s->sh_flags & SHF_ALLOC)) {
-            while (offset < s->sh_offset) {
-                fputc(0, f);
-                offset++;
-            }
-            size = s->sh_size;
-            fwrite(s->data, 1, size, f);
-            offset += size;
-        }
-    }
-}
-
-/* output an ELF file */
-/* XXX: suppress unneeded sections */
-int elf_output_file(TCCState *s1, const char *filename)
-{
-    ElfW(Ehdr) ehdr;
-    FILE *f;
-    int fd, mode, ret;
-    int *section_order;
-    int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
-    unsigned long addr;
-    Section *strsec, *s;
-    ElfW(Shdr) shdr, *sh;
-    ElfW(Phdr) *phdr, *ph;
-    Section *interp, *dynamic, *dynstr;
-    unsigned long saved_dynamic_data_offset;
-    ElfW(Sym) *sym;
-    int type, file_type;
-    unsigned long rel_addr, rel_size;
-    
-    file_type = s1->output_type;
-    s1->nb_errors = 0;
-
-    if (file_type != TCC_OUTPUT_OBJ) {
-        tcc_add_runtime(s1);
-    }
-
-    phdr = NULL;
-    section_order = NULL;
-    interp = NULL;
-    dynamic = NULL;
-    dynstr = NULL; /* avoid warning */
-    saved_dynamic_data_offset = 0; /* avoid warning */
-    
-    if (file_type != TCC_OUTPUT_OBJ) {
-        relocate_common_syms();
-
-        tcc_add_linker_symbols(s1);
-
-        if (!s1->static_link) {
-            const char *name;
-            int sym_index, index;
-            ElfW(Sym) *esym, *sym_end;
-            
-            if (file_type == TCC_OUTPUT_EXE) {
-                char *ptr;
-                /* add interpreter section only if executable */
-                interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
-                interp->sh_addralign = 1;
-                ptr = section_ptr_add(interp, sizeof(elf_interp));
-                strcpy(ptr, elf_interp);
-            }
-        
-            /* add dynamic symbol table */
-            s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
-                                    ".dynstr", 
-                                    ".hash", SHF_ALLOC);
-            dynstr = s1->dynsym->link;
-            
-            /* add dynamic section */
-            dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, 
-                                  SHF_ALLOC | SHF_WRITE);
-            dynamic->link = dynstr;
-            dynamic->sh_entsize = sizeof(ElfW(Dyn));
-        
-            /* add PLT */
-            s1->plt = new_section(s1, ".plt", SHT_PROGBITS, 
-                                  SHF_ALLOC | SHF_EXECINSTR);
-            s1->plt->sh_entsize = 4;
-
-            build_got(s1);
-
-            /* scan for undefined symbols and see if they are in the
-               dynamic symbols. If a symbol STT_FUNC is found, then we
-               add it in the PLT. If a symbol STT_OBJECT is found, we
-               add it in the .bss section with a suitable relocation */
-            sym_end = (ElfW(Sym) *)(symtab_section->data + 
-                                    symtab_section->data_offset);
-            if (file_type == TCC_OUTPUT_EXE) {
-                for(sym = (ElfW(Sym) *)symtab_section->data + 1; 
-                    sym < sym_end;
-                    sym++) {
-                    if (sym->st_shndx == SHN_UNDEF) {
-                        name = symtab_section->link->data + sym->st_name;
-                        sym_index = find_elf_sym(s1->dynsymtab_section, name);
-                        if (sym_index) {
-                            esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
-                            type = ELFW(ST_TYPE)(esym->st_info);
-                            if (type == STT_FUNC) {
-                                put_got_entry(s1, R_JMP_SLOT, esym->st_size, 
-                                              esym->st_info, 
-                                              sym - (ElfW(Sym) *)symtab_section->data);
-                            } else if (type == STT_OBJECT) {
-                                unsigned long offset;
-                                offset = bss_section->data_offset;
-                                /* XXX: which alignment ? */
-                                offset = (offset + 16 - 1) & -16;
-                                index = put_elf_sym(s1->dynsym, offset, esym->st_size, 
-                                                    esym->st_info, 0, 
-                                                    bss_section->sh_num, name);
-                                put_elf_reloc(s1->dynsym, bss_section, 
-                                              offset, R_COPY, index);
-                                offset += esym->st_size;
-                                bss_section->data_offset = offset;
-                            }
-                        } else {
-                                /* STB_WEAK undefined symbols are accepted */
-                                /* XXX: _fp_hw seems to be part of the ABI, so we ignore
-                                   it */
-                            if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
-                                !strcmp(name, "_fp_hw")) {
-                            } else {
-                                error_noabort("undefined symbol '%s'", name);
-                            }
-                        }
-                    } else if (s1->rdynamic && 
-                               ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
-                        /* if -rdynamic option, then export all non
-                           local symbols */
-                        name = symtab_section->link->data + sym->st_name;
-                        put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, 
-                                    sym->st_info, 0, 
-                                    sym->st_shndx, name);
-                    }
-                }
-            
-                if (s1->nb_errors)
-                    goto fail;
-
-                /* now look at unresolved dynamic symbols and export
-                   corresponding symbol */
-                sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data + 
-                                        s1->dynsymtab_section->data_offset);
-                for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1; 
-                    esym < sym_end;
-                    esym++) {
-                    if (esym->st_shndx == SHN_UNDEF) {
-                        name = s1->dynsymtab_section->link->data + esym->st_name;
-                        sym_index = find_elf_sym(symtab_section, name);
-                        if (sym_index) {
-                            /* XXX: avoid adding a symbol if already
-                               present because of -rdynamic ? */
-                            sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
-                            put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, 
-                                        sym->st_info, 0, 
-                                        sym->st_shndx, name);
-                        } else {
-                            if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
-                                /* weak symbols can stay undefined */
-                            } else {
-                                warning("undefined dynamic symbol '%s'", name);
-                            }
-                        }
-                    }
-                }
-            } else {
-                int nb_syms;
-                /* shared library case : we simply export all the global symbols */
-                nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
-                s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
-                for(sym = (ElfW(Sym) *)symtab_section->data + 1; 
-                    sym < sym_end;
-                    sym++) {
-                    if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
-#if defined(TCC_OUTPUT_DLL_WITH_PLT)
-                        if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
-                            sym->st_shndx == SHN_UNDEF) {
-                            put_got_entry(s1, R_JMP_SLOT, sym->st_size, 
-                                          sym->st_info, 
-                                          sym - (ElfW(Sym) *)symtab_section->data);
-                        }
-                        else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
-                            put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size, 
-                                          sym->st_info, 
-                                          sym - (ElfW(Sym) *)symtab_section->data);
-                        }
-                        else
-#endif
-                        {
-                            name = symtab_section->link->data + sym->st_name;
-                            index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, 
-                                                sym->st_info, 0, 
-                                                sym->st_shndx, name);
-                            s1->symtab_to_dynsym[sym - 
-                                                 (ElfW(Sym) *)symtab_section->data] = 
-                                index;
-                        }
-                    }
-                }
-            }
-
-            build_got_entries(s1);
-        
-            /* add a list of needed dlls */
-            for(i = 0; i < s1->nb_loaded_dlls; i++) {
-                DLLReference *dllref = s1->loaded_dlls[i];
-                if (dllref->level == 0)
-                    put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
-            }
-            /* XXX: currently, since we do not handle PIC code, we
-               must relocate the readonly segments */
-            if (file_type == TCC_OUTPUT_DLL) {
-                if (s1->soname)
-                    put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
-                put_dt(dynamic, DT_TEXTREL, 0);
-            }
-
-            /* add necessary space for other entries */
-            saved_dynamic_data_offset = dynamic->data_offset;
-            dynamic->data_offset += sizeof(ElfW(Dyn)) * 9;
-        } else {
-            /* still need to build got entries in case of static link */
-            build_got_entries(s1);
-        }
-    }
-
-    memset(&ehdr, 0, sizeof(ehdr));
-
-    /* we add a section for symbols */
-    strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
-    put_elf_str(strsec, "");
-    
-    /* compute number of sections */
-    shnum = s1->nb_sections;
-
-    /* this array is used to reorder sections in the output file */
-    section_order = tcc_malloc(sizeof(int) * shnum);
-    section_order[0] = 0;
-    sh_order_index = 1;
-    
-    /* compute number of program headers */
-    switch(file_type) {
-    default:
-    case TCC_OUTPUT_OBJ:
-        phnum = 0;
-        break;
-    case TCC_OUTPUT_EXE:
-        if (!s1->static_link)
-            phnum = 4;
-        else
-            phnum = 2;
-        break;
-    case TCC_OUTPUT_DLL:
-        phnum = 3;
-        break;
-    }
-
-    /* allocate strings for section names and decide if an unallocated
-       section should be output */
-    /* NOTE: the strsec section comes last, so its size is also
-       correct ! */
-    for(i = 1; i < s1->nb_sections; i++) {
-        s = s1->sections[i];
-        s->sh_name = put_elf_str(strsec, s->name);
-#if 0 //gr       
-        printf("section: f=%08x t=%08x i=%08x %s %s\n", 
-               s->sh_flags, 
-               s->sh_type, 
-               s->sh_info, 
-               s->name, 
-               s->reloc ? s->reloc->name : "n"
-               ); 
-#endif
-        /* when generating a DLL, we include relocations but we may
-           patch them */
-        if (file_type == TCC_OUTPUT_DLL && 
-            s->sh_type == SHT_RELX && 
-            !(s->sh_flags & SHF_ALLOC)) {
-            /* //gr: avoid bogus relocs for empty (debug) sections */
-            if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
-                prepare_dynamic_rel(s1, s);
-            else if (s1->do_debug)
-                s->sh_size = s->data_offset;
-        } else if (s1->do_debug ||
-            file_type == TCC_OUTPUT_OBJ || 
-            (s->sh_flags & SHF_ALLOC) ||
-            i == (s1->nb_sections - 1)) {
-            /* we output all sections if debug or object file */
-            s->sh_size = s->data_offset;
-        }
-    }
-
-    /* allocate program segment headers */
-    phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
-        
-    if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
-        file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
-    } else {
-        file_offset = 0;
-    }
-    if (phnum > 0) {
-        /* compute section to program header mapping */
-        if (s1->has_text_addr) { 
-            int a_offset, p_offset;
-            addr = s1->text_addr;
-            /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
-               ELF_PAGE_SIZE */
-            a_offset = addr & (ELF_PAGE_SIZE - 1);
-            p_offset = file_offset & (ELF_PAGE_SIZE - 1);
-            if (a_offset < p_offset) 
-                a_offset += ELF_PAGE_SIZE;
-            file_offset += (a_offset - p_offset);
-        } else {
-            if (file_type == TCC_OUTPUT_DLL)
-                addr = 0;
-            else
-                addr = ELF_START_ADDR;
-            /* compute address after headers */
-            addr += (file_offset & (ELF_PAGE_SIZE - 1));
-        }
-        
-        /* dynamic relocation table information, for .dynamic section */
-        rel_size = 0;
-        rel_addr = 0;
-
-        /* leave one program header for the program interpreter */
-        ph = &phdr[0];
-        if (interp)
-            ph++;
-
-        for(j = 0; j < 2; j++) {
-            ph->p_type = PT_LOAD;
-            if (j == 0)
-                ph->p_flags = PF_R | PF_X;
-            else
-                ph->p_flags = PF_R | PF_W;
-            ph->p_align = ELF_PAGE_SIZE;
-            
-            /* we do the following ordering: interp, symbol tables,
-               relocations, progbits, nobits */
-            /* XXX: do faster and simpler sorting */
-            for(k = 0; k < 5; k++) {
-                for(i = 1; i < s1->nb_sections; i++) {
-                    s = s1->sections[i];
-                    /* compute if section should be included */
-                    if (j == 0) {
-                        if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != 
-                            SHF_ALLOC)
-                            continue;
-                    } else {
-                        if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != 
-                            (SHF_ALLOC | SHF_WRITE))
-                            continue;
-                    }
-                    if (s == interp) {
-                        if (k != 0)
-                            continue;
-                    } else if (s->sh_type == SHT_DYNSYM ||
-                               s->sh_type == SHT_STRTAB ||
-                               s->sh_type == SHT_HASH) {
-                        if (k != 1)
-                            continue;
-                    } else if (s->sh_type == SHT_RELX) {
-                        if (k != 2)
-                            continue;
-                    } else if (s->sh_type == SHT_NOBITS) {
-                        if (k != 4)
-                            continue;
-                    } else {
-                        if (k != 3)
-                            continue;
-                    }
-                    section_order[sh_order_index++] = i;
-
-                    /* section matches: we align it and add its size */
-                    tmp = addr;
-                    addr = (addr + s->sh_addralign - 1) & 
-                        ~(s->sh_addralign - 1);
-                    file_offset += addr - tmp;
-                    s->sh_offset = file_offset;
-                    s->sh_addr = addr;
-                    
-                    /* update program header infos */
-                    if (ph->p_offset == 0) {
-                        ph->p_offset = file_offset;
-                        ph->p_vaddr = addr;
-                        ph->p_paddr = ph->p_vaddr;
-                    }
-                    /* update dynamic relocation infos */
-                    if (s->sh_type == SHT_RELX) {
-                        if (rel_size == 0)
-                            rel_addr = addr;
-                        rel_size += s->sh_size;
-                    }
-                    addr += s->sh_size;
-                    if (s->sh_type != SHT_NOBITS)
-                        file_offset += s->sh_size;
-                }
-            }
-            ph->p_filesz = file_offset - ph->p_offset;
-            ph->p_memsz = addr - ph->p_vaddr;
-            ph++;
-            if (j == 0) {
-                if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
-                    /* if in the middle of a page, we duplicate the page in
-                       memory so that one copy is RX and the other is RW */
-                    if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
-                        addr += ELF_PAGE_SIZE;
-                } else {
-                    addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
-                    file_offset = (file_offset + ELF_PAGE_SIZE - 1) & 
-                        ~(ELF_PAGE_SIZE - 1);
-                }
-            }
-        }
-
-        /* if interpreter, then add corresponing program header */
-        if (interp) {
-            ph = &phdr[0];
-            
-            ph->p_type = PT_INTERP;
-            ph->p_offset = interp->sh_offset;
-            ph->p_vaddr = interp->sh_addr;
-            ph->p_paddr = ph->p_vaddr;
-            ph->p_filesz = interp->sh_size;
-            ph->p_memsz = interp->sh_size;
-            ph->p_flags = PF_R;
-            ph->p_align = interp->sh_addralign;
-        }
-        
-        /* if dynamic section, then add corresponing program header */
-        if (dynamic) {
-            ElfW(Sym) *sym_end;
-
-            ph = &phdr[phnum - 1];
-            
-            ph->p_type = PT_DYNAMIC;
-            ph->p_offset = dynamic->sh_offset;
-            ph->p_vaddr = dynamic->sh_addr;
-            ph->p_paddr = ph->p_vaddr;
-            ph->p_filesz = dynamic->sh_size;
-            ph->p_memsz = dynamic->sh_size;
-            ph->p_flags = PF_R | PF_W;
-            ph->p_align = dynamic->sh_addralign;
-
-            /* put GOT dynamic section address */
-            put32(s1->got->data, dynamic->sh_addr);
-
-            /* relocate the PLT */
-            if (file_type == TCC_OUTPUT_EXE
-#if defined(TCC_OUTPUT_DLL_WITH_PLT)
-                || file_type == TCC_OUTPUT_DLL
-#endif
-                ) {
-                uint8_t *p, *p_end;
-
-                p = s1->plt->data;
-                p_end = p + s1->plt->data_offset;
-                if (p < p_end) {
-#if defined(TCC_TARGET_I386)
-                    put32(p + 2, get32(p + 2) + s1->got->sh_addr);
-                    put32(p + 8, get32(p + 8) + s1->got->sh_addr);
-                    p += 16;
-                    while (p < p_end) {
-                        put32(p + 2, get32(p + 2) + s1->got->sh_addr);
-                        p += 16;
-                    }
-#elif defined(TCC_TARGET_X86_64)
-                    int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
-                    put32(p + 2, get32(p + 2) + x);
-                    put32(p + 8, get32(p + 8) + x - 6);
-                    p += 16;
-                    while (p < p_end) {
-                        put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
-                        p += 16;
-                    }
-#elif defined(TCC_TARGET_ARM)
-                    int x;
-                    x=s1->got->sh_addr - s1->plt->sh_addr - 12;
-                    p +=16;
-                    while (p < p_end) {
-                        put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
-                        p += 16;
-                    }
-#elif defined(TCC_TARGET_C67)
-                    /* XXX: TODO */
-#else
-#error unsupported CPU
-#endif
-                }
-            }
-
-            /* relocate symbols in .dynsym */
-            sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
-            for(sym = (ElfW(Sym) *)s1->dynsym->data + 1; 
-                sym < sym_end;
-                sym++) {
-                if (sym->st_shndx == SHN_UNDEF) {
-                    /* relocate to the PLT if the symbol corresponds
-                       to a PLT entry */
-                    if (sym->st_value)
-                        sym->st_value += s1->plt->sh_addr;
-                } else if (sym->st_shndx < SHN_LORESERVE) {
-                    /* do symbol relocation */
-                    sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
-                }
-            }
-
-            /* put dynamic section entries */
-            dynamic->data_offset = saved_dynamic_data_offset;
-            put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
-            put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
-            put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
-            put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
-            put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
-#ifdef TCC_TARGET_X86_64
-            put_dt(dynamic, DT_RELA, rel_addr);
-            put_dt(dynamic, DT_RELASZ, rel_size);
-            put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
-#else
-            put_dt(dynamic, DT_REL, rel_addr);
-            put_dt(dynamic, DT_RELSZ, rel_size);
-            put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
-#endif
-            if (s1->do_debug)
-                put_dt(dynamic, DT_DEBUG, 0);
-            put_dt(dynamic, DT_NULL, 0);
-        }
-
-        ehdr.e_phentsize = sizeof(ElfW(Phdr));
-        ehdr.e_phnum = phnum;
-        ehdr.e_phoff = sizeof(ElfW(Ehdr));
-    }
-
-    /* all other sections come after */
-    for(i = 1; i < s1->nb_sections; i++) {
-        s = s1->sections[i];
-        if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
-            continue;
-        section_order[sh_order_index++] = i;
-        
-        file_offset = (file_offset + s->sh_addralign - 1) & 
-            ~(s->sh_addralign - 1);
-        s->sh_offset = file_offset;
-        if (s->sh_type != SHT_NOBITS)
-            file_offset += s->sh_size;
-    }
-    
-    /* if building executable or DLL, then relocate each section
-       except the GOT which is already relocated */
-    if (file_type != TCC_OUTPUT_OBJ) {
-        relocate_syms(s1, 0);
-
-        if (s1->nb_errors != 0) {
-        fail:
-            ret = -1;
-            goto the_end;
-        }
-
-        /* relocate sections */
-        /* XXX: ignore sections with allocated relocations ? */
-        for(i = 1; i < s1->nb_sections; i++) {
-            s = s1->sections[i];
-            if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
-                relocate_section(s1, s);
-        }
-
-        /* relocate relocation entries if the relocation tables are
-           allocated in the executable */
-        for(i = 1; i < s1->nb_sections; i++) {
-            s = s1->sections[i];
-            if ((s->sh_flags & SHF_ALLOC) &&
-                s->sh_type == SHT_RELX) {
-                relocate_rel(s1, s);
-            }
-        }
-
-        /* get entry point address */
-        if (file_type == TCC_OUTPUT_EXE)
-            ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start");
-        else
-            ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
-    }
-
-    /* write elf file */
-    if (file_type == TCC_OUTPUT_OBJ)
-        mode = 0666;
-    else
-        mode = 0777;
-    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode); 
-    if (fd < 0) {
-        error_noabort("could not write '%s'", filename);
-        goto fail;
-    }
-    f = fdopen(fd, "wb");
-    if (s1->verbose)
-        printf("<- %s\n", filename);
-
-#ifdef TCC_TARGET_COFF
-    if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
-        tcc_output_coff(s1, f);
-    } else
-#endif
-    if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
-        sort_syms(s1, symtab_section);
-        
-        /* align to 4 */
-        file_offset = (file_offset + 3) & -4;
-    
-        /* fill header */
-        ehdr.e_ident[0] = ELFMAG0;
-        ehdr.e_ident[1] = ELFMAG1;
-        ehdr.e_ident[2] = ELFMAG2;
-        ehdr.e_ident[3] = ELFMAG3;
-        ehdr.e_ident[4] = TCC_ELFCLASS;
-        ehdr.e_ident[5] = ELFDATA2LSB;
-        ehdr.e_ident[6] = EV_CURRENT;
-#ifdef __FreeBSD__
-        ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
-#endif
-#ifdef TCC_TARGET_ARM
-#ifdef TCC_ARM_EABI
-        ehdr.e_ident[EI_OSABI] = 0;
-        ehdr.e_flags = 4 << 24;
-#else
-        ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
-#endif
-#endif
-        switch(file_type) {
-        default:
-        case TCC_OUTPUT_EXE:
-            ehdr.e_type = ET_EXEC;
-            break;
-        case TCC_OUTPUT_DLL:
-            ehdr.e_type = ET_DYN;
-            break;
-        case TCC_OUTPUT_OBJ:
-            ehdr.e_type = ET_REL;
-            break;
-        }
-        ehdr.e_machine = EM_TCC_TARGET;
-        ehdr.e_version = EV_CURRENT;
-        ehdr.e_shoff = file_offset;
-        ehdr.e_ehsize = sizeof(ElfW(Ehdr));
-        ehdr.e_shentsize = sizeof(ElfW(Shdr));
-        ehdr.e_shnum = shnum;
-        ehdr.e_shstrndx = shnum - 1;
-        
-        fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
-        fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
-        offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
-
-        for(i=1;i<s1->nb_sections;i++) {
-            s = s1->sections[section_order[i]];
-            if (s->sh_type != SHT_NOBITS) {
-                while (offset < s->sh_offset) {
-                    fputc(0, f);
-                    offset++;
-                }
-                size = s->sh_size;
-                fwrite(s->data, 1, size, f);
-                offset += size;
-            }
-        }
-
-        /* output section headers */
-        while (offset < ehdr.e_shoff) {
-            fputc(0, f);
-            offset++;
-        }
-    
-        for(i=0;i<s1->nb_sections;i++) {
-            sh = &shdr;
-            memset(sh, 0, sizeof(ElfW(Shdr)));
-            s = s1->sections[i];
-            if (s) {
-                sh->sh_name = s->sh_name;
-                sh->sh_type = s->sh_type;
-                sh->sh_flags = s->sh_flags;
-                sh->sh_entsize = s->sh_entsize;
-                sh->sh_info = s->sh_info;
-                if (s->link)
-                    sh->sh_link = s->link->sh_num;
-                sh->sh_addralign = s->sh_addralign;
-                sh->sh_addr = s->sh_addr;
-                sh->sh_offset = s->sh_offset;
-                sh->sh_size = s->sh_size;
-            }
-            fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
-        }
-    } else {
-        tcc_output_binary(s1, f, section_order);
-    }
-    fclose(f);
-
-    ret = 0;
- the_end:
-    tcc_free(s1->symtab_to_dynsym);
-    tcc_free(section_order);
-    tcc_free(phdr);
-    tcc_free(s1->got_offsets);
-    return ret;
-}
-
-int tcc_output_file(TCCState *s, const char *filename)
-{
-    int ret;
-#ifdef TCC_TARGET_PE
-    if (s->output_type != TCC_OUTPUT_OBJ) {
-        ret = pe_output_file(s, filename);
-    } else
-#endif
-    {
-        ret = elf_output_file(s, filename);
-    }
-    return ret;
-}
-
-static void *load_data(int fd, unsigned long file_offset, unsigned long size)
-{
-    void *data;
-
-    data = tcc_malloc(size);
-    lseek(fd, file_offset, SEEK_SET);
-    read(fd, data, size);
-    return data;
-}
-
-typedef struct SectionMergeInfo {
-    Section *s;            /* corresponding existing section */
-    unsigned long offset;  /* offset of the new section in the existing section */
-    uint8_t new_section;       /* true if section 's' was added */
-    uint8_t link_once;         /* true if link once section */
-} SectionMergeInfo;
-
-/* load an object file and merge it with current files */
-/* XXX: handle correctly stab (debug) info */
-static int tcc_load_object_file(TCCState *s1, 
-                                int fd, unsigned long file_offset)
-{ 
-    ElfW(Ehdr) ehdr;
-    ElfW(Shdr) *shdr, *sh;
-    int size, i, j, offset, offseti, nb_syms, sym_index, ret;
-    unsigned char *strsec, *strtab;
-    int *old_to_new_syms;
-    char *sh_name, *name;
-    SectionMergeInfo *sm_table, *sm;
-    ElfW(Sym) *sym, *symtab;
-    ElfW_Rel *rel, *rel_end;
-    Section *s;
-
-    int stab_index;
-    int stabstr_index;
-
-    stab_index = stabstr_index = 0;
-
-    if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
-        goto fail1;
-    if (ehdr.e_ident[0] != ELFMAG0 ||
-        ehdr.e_ident[1] != ELFMAG1 ||
-        ehdr.e_ident[2] != ELFMAG2 ||
-        ehdr.e_ident[3] != ELFMAG3)
-        goto fail1;
-    /* test if object file */
-    if (ehdr.e_type != ET_REL)
-        goto fail1;
-    /* test CPU specific stuff */
-    if (ehdr.e_ident[5] != ELFDATA2LSB ||
-        ehdr.e_machine != EM_TCC_TARGET) {
-    fail1:
-        error_noabort("invalid object file");
-        return -1;
-    }
-    /* read sections */
-    shdr = load_data(fd, file_offset + ehdr.e_shoff, 
-                     sizeof(ElfW(Shdr)) * ehdr.e_shnum);
-    sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
-    
-    /* load section names */
-    sh = &shdr[ehdr.e_shstrndx];
-    strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
-
-    /* load symtab and strtab */
-    old_to_new_syms = NULL;
-    symtab = NULL;
-    strtab = NULL;
-    nb_syms = 0;
-    for(i = 1; i < ehdr.e_shnum; i++) {
-        sh = &shdr[i];
-        if (sh->sh_type == SHT_SYMTAB) {
-            if (symtab) {
-                error_noabort("object must contain only one symtab");
-            fail:
-                ret = -1;
-                goto the_end;
-            }
-            nb_syms = sh->sh_size / sizeof(ElfW(Sym));
-            symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
-            sm_table[i].s = symtab_section;
-
-            /* now load strtab */
-            sh = &shdr[sh->sh_link];
-            strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
-        }
-    }
-        
-    /* now examine each section and try to merge its content with the
-       ones in memory */
-    for(i = 1; i < ehdr.e_shnum; i++) {
-        /* no need to examine section name strtab */
-        if (i == ehdr.e_shstrndx)
-            continue;
-        sh = &shdr[i];
-        sh_name = strsec + sh->sh_name;
-        /* ignore sections types we do not handle */
-        if (sh->sh_type != SHT_PROGBITS &&
-            sh->sh_type != SHT_RELX && 
-#ifdef TCC_ARM_EABI
-            sh->sh_type != SHT_ARM_EXIDX &&
-#endif
-            sh->sh_type != SHT_NOBITS && 
-            strcmp(sh_name, ".stabstr")
-            )
-            continue;
-        if (sh->sh_addralign < 1)
-            sh->sh_addralign = 1;
-        /* find corresponding section, if any */
-        for(j = 1; j < s1->nb_sections;j++) {
-            s = s1->sections[j];
-            if (!strcmp(s->name, sh_name)) {
-                if (!strncmp(sh_name, ".gnu.linkonce", 
-                             sizeof(".gnu.linkonce") - 1)) {
-                    /* if a 'linkonce' section is already present, we
-                       do not add it again. It is a little tricky as
-                       symbols can still be defined in
-                       it. */
-                    sm_table[i].link_once = 1;
-                    goto next;
-                } else {
-                    goto found;
-                }
-            }
-        }
-        /* not found: create new section */
-        s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
-        /* take as much info as possible from the section. sh_link and
-           sh_info will be updated later */
-        s->sh_addralign = sh->sh_addralign;
-        s->sh_entsize = sh->sh_entsize;
-        sm_table[i].new_section = 1;
-    found:
-        if (sh->sh_type != s->sh_type) {
-            error_noabort("invalid section type");
-            goto fail;
-        }
-
-        /* align start of section */
-        offset = s->data_offset;
-
-        if (0 == strcmp(sh_name, ".stab")) {
-            stab_index = i;
-            goto no_align;
-        }
-        if (0 == strcmp(sh_name, ".stabstr")) {
-            stabstr_index = i;
-            goto no_align;
-        }
-
-        size = sh->sh_addralign - 1;
-        offset = (offset + size) & ~size;
-        if (sh->sh_addralign > s->sh_addralign)
-            s->sh_addralign = sh->sh_addralign;
-        s->data_offset = offset;
-    no_align:
-        sm_table[i].offset = offset;
-        sm_table[i].s = s;
-        /* concatenate sections */
-        size = sh->sh_size;
-        if (sh->sh_type != SHT_NOBITS) {
-            unsigned char *ptr;
-            lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
-            ptr = section_ptr_add(s, size);
-            read(fd, ptr, size);
-        } else {
-            s->data_offset += size;
-        }
-    next: ;
-    }
-
-    /* //gr relocate stab strings */
-    if (stab_index && stabstr_index) {
-        Stab_Sym *a, *b;
-        unsigned o;
-        s = sm_table[stab_index].s;
-        a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
-        b = (Stab_Sym *)(s->data + s->data_offset);
-        o = sm_table[stabstr_index].offset;
-        while (a < b) 
-            a->n_strx += o, a++;
-    }
-
-    /* second short pass to update sh_link and sh_info fields of new
-       sections */
-    for(i = 1; i < ehdr.e_shnum; i++) {
-        s = sm_table[i].s;
-        if (!s || !sm_table[i].new_section)
-            continue;
-        sh = &shdr[i];
-        if (sh->sh_link > 0)
-            s->link = sm_table[sh->sh_link].s;
-        if (sh->sh_type == SHT_RELX) {
-            s->sh_info = sm_table[sh->sh_info].s->sh_num;
-            /* update backward link */
-            s1->sections[s->sh_info]->reloc = s;
-        }
-    }
-    sm = sm_table;
-
-    /* resolve symbols */
-    old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
-
-    sym = symtab + 1;
-    for(i = 1; i < nb_syms; i++, sym++) {
-        if (sym->st_shndx != SHN_UNDEF &&
-            sym->st_shndx < SHN_LORESERVE) {
-            sm = &sm_table[sym->st_shndx];
-            if (sm->link_once) {
-                /* if a symbol is in a link once section, we use the
-                   already defined symbol. It is very important to get
-                   correct relocations */
-                if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
-                    name = strtab + sym->st_name;
-                    sym_index = find_elf_sym(symtab_section, name);
-                    if (sym_index)
-                        old_to_new_syms[i] = sym_index;
-                }
-                continue;
-            }
-            /* if no corresponding section added, no need to add symbol */
-            if (!sm->s)
-                continue;
-            /* convert section number */
-            sym->st_shndx = sm->s->sh_num;
-            /* offset value */
-            sym->st_value += sm->offset;
-        }
-        /* add symbol */
-        name = strtab + sym->st_name;
-        sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size, 
-                                sym->st_info, sym->st_other, 
-                                sym->st_shndx, name);
-        old_to_new_syms[i] = sym_index;
-    }
-
-    /* third pass to patch relocation entries */
-    for(i = 1; i < ehdr.e_shnum; i++) {
-        s = sm_table[i].s;
-        if (!s)
-            continue;
-        sh = &shdr[i];
-        offset = sm_table[i].offset;
-        switch(s->sh_type) {
-        case SHT_RELX:
-            /* take relocation offset information */
-            offseti = sm_table[sh->sh_info].offset;
-            rel_end = (ElfW_Rel *)(s->data + s->data_offset);
-            for(rel = (ElfW_Rel *)(s->data + offset);
-                rel < rel_end;
-                rel++) {
-                int type;
-                unsigned sym_index;
-                /* convert symbol index */
-                type = ELFW(R_TYPE)(rel->r_info);
-                sym_index = ELFW(R_SYM)(rel->r_info);
-                /* NOTE: only one symtab assumed */
-                if (sym_index >= nb_syms)
-                    goto invalid_reloc;
-                sym_index = old_to_new_syms[sym_index];
-                /* ignore link_once in rel section. */
-                if (!sym_index && !sm->link_once) {
-                invalid_reloc:
-                    error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
-                        i, strsec + sh->sh_name, rel->r_offset);
-                    goto fail;
-                }
-                rel->r_info = ELFW(R_INFO)(sym_index, type);
-                /* offset the relocation offset */
-                rel->r_offset += offseti;
-            }
-            break;
-        default:
-            break;
-        }
-    }
-    
-    ret = 0;
- the_end:
-    tcc_free(symtab);
-    tcc_free(strtab);
-    tcc_free(old_to_new_syms);
-    tcc_free(sm_table);
-    tcc_free(strsec);
-    tcc_free(shdr);
-    return ret;
-}
-
-#define ARMAG  "!<arch>\012"    /* For COFF and a.out archives */
-
-typedef struct ArchiveHeader {
-    char ar_name[16];           /* name of this member */
-    char ar_date[12];           /* file mtime */
-    char ar_uid[6];             /* owner uid; printed as decimal */
-    char ar_gid[6];             /* owner gid; printed as decimal */
-    char ar_mode[8];            /* file mode, printed as octal   */
-    char ar_size[10];           /* file size, printed as decimal */
-    char ar_fmag[2];            /* should contain ARFMAG */
-} ArchiveHeader;
-
-static int get_be32(const uint8_t *b)
-{
-    return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
-}
-
-/* load only the objects which resolve undefined symbols */
-static int tcc_load_alacarte(TCCState *s1, int fd, int size)
-{
-    int i, bound, nsyms, sym_index, off, ret;
-    uint8_t *data;
-    const char *ar_names, *p;
-    const uint8_t *ar_index;
-    ElfW(Sym) *sym;
-
-    data = tcc_malloc(size);
-    if (read(fd, data, size) != size)
-        goto fail;
-    nsyms = get_be32(data);
-    ar_index = data + 4;
-    ar_names = ar_index + nsyms * 4;
-
-    do {
-        bound = 0;
-        for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
-            sym_index = find_elf_sym(symtab_section, p);
-            if(sym_index) {
-                sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
-                if(sym->st_shndx == SHN_UNDEF) {
-                    off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
-#if 0
-                    printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
-#endif
-                    ++bound;
-                    lseek(fd, off, SEEK_SET);
-                    if(tcc_load_object_file(s1, fd, off) < 0) {
-                    fail:
-                        ret = -1;
-                        goto the_end;
-                    }
-                }
-            }
-        }
-    } while(bound);
-    ret = 0;
- the_end:
-    tcc_free(data);
-    return ret;
-}
-
-/* load a '.a' file */
-static int tcc_load_archive(TCCState *s1, int fd)
-{
-    ArchiveHeader hdr;
-    char ar_size[11];
-    char ar_name[17];
-    char magic[8];
-    int size, len, i;
-    unsigned long file_offset;
-
-    /* skip magic which was already checked */
-    read(fd, magic, sizeof(magic));
-    
-    for(;;) {
-        len = read(fd, &hdr, sizeof(hdr));
-        if (len == 0)
-            break;
-        if (len != sizeof(hdr)) {
-            error_noabort("invalid archive");
-            return -1;
-        }
-        memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
-        ar_size[sizeof(hdr.ar_size)] = '\0';
-        size = strtol(ar_size, NULL, 0);
-        memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
-        for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
-            if (ar_name[i] != ' ')
-                break;
-        }
-        ar_name[i + 1] = '\0';
-        //        printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
-        file_offset = lseek(fd, 0, SEEK_CUR);
-        /* align to even */
-        size = (size + 1) & ~1;
-        if (!strcmp(ar_name, "/")) {
-            /* coff symbol table : we handle it */
-            if(s1->alacarte_link)
-                return tcc_load_alacarte(s1, fd, size);
-        } else if (!strcmp(ar_name, "//") ||
-                   !strcmp(ar_name, "__.SYMDEF") ||
-                   !strcmp(ar_name, "__.SYMDEF/") ||
-                   !strcmp(ar_name, "ARFILENAMES/")) {
-            /* skip symbol table or archive names */
-        } else {
-            if (tcc_load_object_file(s1, fd, file_offset) < 0)
-                return -1;
-        }
-        lseek(fd, file_offset + size, SEEK_SET);
-    }
-    return 0;
-}
-
-/* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
-   is referenced by the user (so it should be added as DT_NEEDED in
-   the generated ELF file) */
-static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
-{ 
-    ElfW(Ehdr) ehdr;
-    ElfW(Shdr) *shdr, *sh, *sh1;
-    int i, j, nb_syms, nb_dts, sym_bind, ret;
-    ElfW(Sym) *sym, *dynsym;
-    ElfW(Dyn) *dt, *dynamic;
-    unsigned char *dynstr;
-    const char *name, *soname;
-    DLLReference *dllref;
-    
-    read(fd, &ehdr, sizeof(ehdr));
-
-    /* test CPU specific stuff */
-    if (ehdr.e_ident[5] != ELFDATA2LSB ||
-        ehdr.e_machine != EM_TCC_TARGET) {
-        error_noabort("bad architecture");
-        return -1;
-    }
-
-    /* read sections */
-    shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
-
-    /* load dynamic section and dynamic symbols */
-    nb_syms = 0;
-    nb_dts = 0;
-    dynamic = NULL;
-    dynsym = NULL; /* avoid warning */
-    dynstr = NULL; /* avoid warning */
-    for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
-        switch(sh->sh_type) {
-        case SHT_DYNAMIC:
-            nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
-            dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
-            break;
-        case SHT_DYNSYM:
-            nb_syms = sh->sh_size / sizeof(ElfW(Sym));
-            dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
-            sh1 = &shdr[sh->sh_link];
-            dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
-            break;
-        default:
-            break;
-        }
-    }
-    
-    /* compute the real library name */
-    soname = tcc_basename(filename);
-        
-    for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
-        if (dt->d_tag == DT_SONAME) {
-            soname = dynstr + dt->d_un.d_val;
-        }
-    }
-
-    /* if the dll is already loaded, do not load it */
-    for(i = 0; i < s1->nb_loaded_dlls; i++) {
-        dllref = s1->loaded_dlls[i];
-        if (!strcmp(soname, dllref->name)) {
-            /* but update level if needed */
-            if (level < dllref->level)
-                dllref->level = level;
-            ret = 0;
-            goto the_end;
-        }
-    }
-    
-    //    printf("loading dll '%s'\n", soname);
-
-    /* add the dll and its level */
-    dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
-    dllref->level = level;
-    strcpy(dllref->name, soname);
-    dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
-
-    /* add dynamic symbols in dynsym_section */
-    for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
-        sym_bind = ELFW(ST_BIND)(sym->st_info);
-        if (sym_bind == STB_LOCAL)
-            continue;
-        name = dynstr + sym->st_name;
-        add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
-                    sym->st_info, sym->st_other, sym->st_shndx, name);
-    }
-
-    /* load all referenced DLLs */
-    for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
-        switch(dt->d_tag) {
-        case DT_NEEDED:
-            name = dynstr + dt->d_un.d_val;
-            for(j = 0; j < s1->nb_loaded_dlls; j++) {
-                dllref = s1->loaded_dlls[j];
-                if (!strcmp(name, dllref->name))
-                    goto already_loaded;
-            }
-            if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
-                error_noabort("referenced dll '%s' not found", name);
-                ret = -1;
-                goto the_end;
-            }
-        already_loaded:
-            break;
-        }
-    }
-    ret = 0;
- the_end:
-    tcc_free(dynstr);
-    tcc_free(dynsym);
-    tcc_free(dynamic);
-    tcc_free(shdr);
-    return ret;
-}
-
-#define LD_TOK_NAME 256
-#define LD_TOK_EOF  (-1)
-
-/* return next ld script token */
-static int ld_next(TCCState *s1, char *name, int name_size)
-{
-    int c;
-    char *q;
-
- redo:
-    switch(ch) {
-    case ' ':
-    case '\t':
-    case '\f':
-    case '\v':
-    case '\r':
-    case '\n':
-        inp();
-        goto redo;
-    case '/':
-        minp();
-        if (ch == '*') {
-            file->buf_ptr = parse_comment(file->buf_ptr);
-            ch = file->buf_ptr[0];
-            goto redo;
-        } else {
-            q = name;
-            *q++ = '/';
-            goto parse_name;
-        }
-        break;
-    /* case 'a' ... 'z': */
-    case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-    /* case 'A' ... 'z': */
-    case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-    case '_':
-    case '\\':
-    case '.':
-    case '$':
-    case '~':
-        q = name;
-    parse_name:
-        for(;;) {
-            if (!((ch >= 'a' && ch <= 'z') ||
-                  (ch >= 'A' && ch <= 'Z') ||
-                  (ch >= '0' && ch <= '9') ||
-                  strchr("/.-_+=$:\\,~", ch)))
-                break;
-            if ((q - name) < name_size - 1) {
-                *q++ = ch;
-            }
-            minp();
-        }
-        *q = '\0';
-        c = LD_TOK_NAME;
-        break;
-    case CH_EOF:
-        c = LD_TOK_EOF;
-        break;
-    default:
-        c = ch;
-        inp();
-        break;
-    }
-#if 0
-    printf("tok=%c %d\n", c, c);
-    if (c == LD_TOK_NAME)
-        printf("  name=%s\n", name);
-#endif
-    return c;
-}
-
-static int ld_add_file_list(TCCState *s1, int as_needed)
-{
-    char filename[1024];
-    int t, ret;
-
-    t = ld_next(s1, filename, sizeof(filename));
-    if (t != '(')
-        expect("(");
-    t = ld_next(s1, filename, sizeof(filename));
-    for(;;) {
-        if (t == LD_TOK_EOF) {
-            error_noabort("unexpected end of file");
-            return -1;
-        } else if (t == ')') {
-            break;
-        } else if (t != LD_TOK_NAME) {
-            error_noabort("filename expected");
-            return -1;
-        } 
-        if (!strcmp(filename, "AS_NEEDED")) {
-            ret = ld_add_file_list(s1, 1);
-            if (ret)
-                return ret;
-        } else {
-            /* TODO: Implement AS_NEEDED support. Ignore it for now */
-            if (!as_needed)
-                tcc_add_file(s1, filename);
-        }
-        t = ld_next(s1, filename, sizeof(filename));
-        if (t == ',') {
-            t = ld_next(s1, filename, sizeof(filename));
-        }
-    }
-    return 0;
-}
-
-/* interpret a subset of GNU ldscripts to handle the dummy libc.so
-   files */
-static int tcc_load_ldscript(TCCState *s1)
-{
-    char cmd[64];
-    char filename[1024];
-    int t, ret;
-    
-    ch = file->buf_ptr[0];
-    ch = handle_eob();
-    for(;;) {
-        t = ld_next(s1, cmd, sizeof(cmd));
-        if (t == LD_TOK_EOF)
-            return 0;
-        else if (t != LD_TOK_NAME)
-            return -1;
-        if (!strcmp(cmd, "INPUT") ||
-            !strcmp(cmd, "GROUP")) {
-            ret = ld_add_file_list(s1, 0);
-            if (ret)
-                return ret;
-        } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
-                   !strcmp(cmd, "TARGET")) {
-            /* ignore some commands */
-            t = ld_next(s1, cmd, sizeof(cmd));
-            if (t != '(')
-                expect("(");
-            for(;;) {
-                t = ld_next(s1, filename, sizeof(filename));
-                if (t == LD_TOK_EOF) {
-                    error_noabort("unexpected end of file");
-                    return -1;
-                } else if (t == ')') {
-                    break;
-                }
-            }
-        } else {
-            return -1;
-        }
-    }
-    return 0;
-}

+ 0 - 5122
src/modules/native/tcc/libtcc/tccgen.c

@@ -1,5122 +0,0 @@
-/*
- *  TCC - Tiny C Compiler
- * 
- *  Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-void swap(int *p, int *q)
-{
-    int t;
-    t = *p;
-    *p = *q;
-    *q = t;
-}
-
-void vsetc(CType *type, int r, CValue *vc)
-{
-    int v;
-
-    if (vtop >= vstack + (VSTACK_SIZE - 1))
-        error("memory full");
-    /* cannot let cpu flags if other instruction are generated. Also
-       avoid leaving VT_JMP anywhere except on the top of the stack
-       because it would complicate the code generator. */
-    if (vtop >= vstack) {
-        v = vtop->r & VT_VALMASK;
-        if (v == VT_CMP || (v & ~1) == VT_JMP)
-            gv(RC_INT);
-    }
-    vtop++;
-    vtop->type = *type;
-    vtop->r = r;
-    vtop->r2 = VT_CONST;
-    vtop->c = *vc;
-}
-
-/* push integer constant */
-void vpushi(int v)
-{
-    CValue cval;
-    cval.i = v;
-    vsetc(&int_type, VT_CONST, &cval);
-}
-
-/* push long long constant */
-void vpushll(long long v)
-{
-    CValue cval;
-    CType ctype;
-    ctype.t = VT_LLONG;
-    cval.ull = v;
-    vsetc(&ctype, VT_CONST, &cval);
-}
-
-/* Return a static symbol pointing to a section */
-static Sym *get_sym_ref(CType *type, Section *sec, 
-                        unsigned long offset, unsigned long size)
-{
-    int v;
-    Sym *sym;
-
-    v = anon_sym++;
-    sym = global_identifier_push(v, type->t | VT_STATIC, 0);
-    sym->type.ref = type->ref;
-    sym->r = VT_CONST | VT_SYM;
-    put_extern_sym(sym, sec, offset, size);
-    return sym;
-}
-
-/* push a reference to a section offset by adding a dummy symbol */
-static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
-{
-    CValue cval;
-
-    cval.ul = 0;
-    vsetc(type, VT_CONST | VT_SYM, &cval);
-    vtop->sym = get_sym_ref(type, sec, offset, size);
-}
-
-/* define a new external reference to a symbol 'v' of type 'u' */
-static Sym *external_global_sym(int v, CType *type, int r)
-{
-    Sym *s;
-
-    s = sym_find(v);
-    if (!s) {
-        /* push forward reference */
-        s = global_identifier_push(v, type->t | VT_EXTERN, 0);
-        s->type.ref = type->ref;
-        s->r = r | VT_CONST | VT_SYM;
-    }
-    return s;
-}
-
-/* define a new external reference to a symbol 'v' of type 'u' */
-static Sym *external_sym(int v, CType *type, int r)
-{
-    Sym *s;
-
-    s = sym_find(v);
-    if (!s) {
-        /* push forward reference */
-        s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
-        s->type.t |= VT_EXTERN;
-    } else {
-        if (!is_compatible_types(&s->type, type))
-            error("incompatible types for redefinition of '%s'", 
-                  get_tok_str(v, NULL));
-    }
-    return s;
-}
-
-/* push a reference to global symbol v */
-static void vpush_global_sym(CType *type, int v)
-{
-    Sym *sym;
-    CValue cval;
-
-    sym = external_global_sym(v, type, 0);
-    cval.ul = 0;
-    vsetc(type, VT_CONST | VT_SYM, &cval);
-    vtop->sym = sym;
-}
-
-void vset(CType *type, int r, int v)
-{
-    CValue cval;
-
-    cval.i = v;
-    vsetc(type, r, &cval);
-}
-
-void vseti(int r, int v)
-{
-    CType type;
-    type.t = VT_INT;
-    vset(&type, r, v);
-}
-
-void vswap(void)
-{
-    SValue tmp;
-
-    tmp = vtop[0];
-    vtop[0] = vtop[-1];
-    vtop[-1] = tmp;
-}
-
-void vpushv(SValue *v)
-{
-    if (vtop >= vstack + (VSTACK_SIZE - 1))
-        error("memory full");
-    vtop++;
-    *vtop = *v;
-}
-
-void vdup(void)
-{
-    vpushv(vtop);
-}
-
-/* save r to the memory stack, and mark it as being free */
-void save_reg(int r)
-{
-    int l, saved, size, align;
-    SValue *p, sv;
-    CType *type;
-
-    /* modify all stack values */
-    saved = 0;
-    l = 0;
-    for(p=vstack;p<=vtop;p++) {
-        if ((p->r & VT_VALMASK) == r ||
-            ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
-            /* must save value on stack if not already done */
-            if (!saved) {
-                /* NOTE: must reload 'r' because r might be equal to r2 */
-                r = p->r & VT_VALMASK;
-                /* store register in the stack */
-                type = &p->type;
-                if ((p->r & VT_LVAL) ||
-                    (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
-#ifdef TCC_TARGET_X86_64
-                    type = &char_pointer_type;
-#else
-                    type = &int_type;
-#endif
-                size = type_size(type, &align);
-                loc = (loc - size) & -align;
-                sv.type.t = type->t;
-                sv.r = VT_LOCAL | VT_LVAL;
-                sv.c.ul = loc;
-                store(r, &sv);
-#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
-                /* x86 specific: need to pop fp register ST0 if saved */
-                if (r == TREG_ST0) {
-                    o(0xd9dd); /* fstp %st(1) */
-                }
-#endif
-#ifndef TCC_TARGET_X86_64
-                /* special long long case */
-                if ((type->t & VT_BTYPE) == VT_LLONG) {
-                    sv.c.ul += 4;
-                    store(p->r2, &sv);
-                }
-#endif
-                l = loc;
-                saved = 1;
-            }
-            /* mark that stack entry as being saved on the stack */
-            if (p->r & VT_LVAL) {
-                /* also clear the bounded flag because the
-                   relocation address of the function was stored in
-                   p->c.ul */
-                p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
-            } else {
-                p->r = lvalue_type(p->type.t) | VT_LOCAL;
-            }
-            p->r2 = VT_CONST;
-            p->c.ul = l;
-        }
-    }
-}
-
-/* find a register of class 'rc2' with at most one reference on stack.
- * If none, call get_reg(rc) */
-int get_reg_ex(int rc, int rc2) 
-{
-    int r;
-    SValue *p;
-    
-    for(r=0;r<NB_REGS;r++) {
-        if (reg_classes[r] & rc2) {
-            int n;
-            n=0;
-            for(p = vstack; p <= vtop; p++) {
-                if ((p->r & VT_VALMASK) == r ||
-                    (p->r2 & VT_VALMASK) == r)
-                    n++;
-            }
-            if (n <= 1)
-                return r;
-        }
-    }
-    return get_reg(rc);
-}
-
-/* find a free register of class 'rc'. If none, save one register */
-int get_reg(int rc)
-{
-    int r;
-    SValue *p;
-
-    /* find a free register */
-    for(r=0;r<NB_REGS;r++) {
-        if (reg_classes[r] & rc) {
-            for(p=vstack;p<=vtop;p++) {
-                if ((p->r & VT_VALMASK) == r ||
-                    (p->r2 & VT_VALMASK) == r)
-                    goto notfound;
-            }
-            return r;
-        }
-    notfound: ;
-    }
-    
-    /* no register left : free the first one on the stack (VERY
-       IMPORTANT to start from the bottom to ensure that we don't
-       spill registers used in gen_opi()) */
-    for(p=vstack;p<=vtop;p++) {
-        r = p->r & VT_VALMASK;
-        if (r < VT_CONST && (reg_classes[r] & rc))
-            goto save_found;
-        /* also look at second register (if long long) */
-        r = p->r2 & VT_VALMASK;
-        if (r < VT_CONST && (reg_classes[r] & rc)) {
-        save_found:
-            save_reg(r);
-            return r;
-        }
-    }
-    /* Should never comes here */
-    return -1;
-}
-
-/* save registers up to (vtop - n) stack entry */
-void save_regs(int n)
-{
-    int r;
-    SValue *p, *p1;
-    p1 = vtop - n;
-    for(p = vstack;p <= p1; p++) {
-        r = p->r & VT_VALMASK;
-        if (r < VT_CONST) {
-            save_reg(r);
-        }
-    }
-}
-
-/* move register 's' to 'r', and flush previous value of r to memory
-   if needed */
-void move_reg(int r, int s)
-{
-    SValue sv;
-
-    if (r != s) {
-        save_reg(r);
-        sv.type.t = VT_INT;
-        sv.r = s;
-        sv.c.ul = 0;
-        load(r, &sv);
-    }
-}
-
-/* get address of vtop (vtop MUST BE an lvalue) */
-void gaddrof(void)
-{
-    vtop->r &= ~VT_LVAL;
-    /* tricky: if saved lvalue, then we can go back to lvalue */
-    if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
-        vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
-}
-
-#ifdef CONFIG_TCC_BCHECK
-/* generate lvalue bound code */
-void gbound(void)
-{
-    int lval_type;
-    CType type1;
-
-    vtop->r &= ~VT_MUSTBOUND;
-    /* if lvalue, then use checking code before dereferencing */
-    if (vtop->r & VT_LVAL) {
-        /* if not VT_BOUNDED value, then make one */
-        if (!(vtop->r & VT_BOUNDED)) {
-            lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
-            /* must save type because we must set it to int to get pointer */
-            type1 = vtop->type;
-            vtop->type.t = VT_INT;
-            gaddrof();
-            vpushi(0);
-            gen_bounded_ptr_add();
-            vtop->r |= lval_type;
-            vtop->type = type1;
-        }
-        /* then check for dereferencing */
-        gen_bounded_ptr_deref();
-    }
-}
-#endif
-
-/* store vtop a register belonging to class 'rc'. lvalues are
-   converted to values. Cannot be used if cannot be converted to
-   register value (such as structures). */
-int gv(int rc)
-{
-    int r, rc2, bit_pos, bit_size, size, align, i;
-
-    /* NOTE: get_reg can modify vstack[] */
-    if (vtop->type.t & VT_BITFIELD) {
-        CType type;
-        int bits = 32;
-        bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
-        bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
-        /* remove bit field info to avoid loops */
-        vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
-        /* cast to int to propagate signedness in following ops */
-        if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
-            type.t = VT_LLONG;
-            bits = 64;
-        } else
-            type.t = VT_INT;
-        if((vtop->type.t & VT_UNSIGNED) ||
-           (vtop->type.t & VT_BTYPE) == VT_BOOL)
-            type.t |= VT_UNSIGNED;
-        gen_cast(&type);
-        /* generate shifts */
-        vpushi(bits - (bit_pos + bit_size));
-        gen_op(TOK_SHL);
-        vpushi(bits - bit_size);
-        /* NOTE: transformed to SHR if unsigned */
-        gen_op(TOK_SAR);
-        r = gv(rc);
-    } else {
-        if (is_float(vtop->type.t) && 
-            (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
-            Sym *sym;
-            int *ptr;
-            unsigned long offset;
-#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
-            CValue check;
-#endif
-            
-            /* XXX: unify with initializers handling ? */
-            /* CPUs usually cannot use float constants, so we store them
-               generically in data segment */
-            size = type_size(&vtop->type, &align);
-            offset = (data_section->data_offset + align - 1) & -align;
-            data_section->data_offset = offset;
-            /* XXX: not portable yet */
-#if defined(__i386__) || defined(__x86_64__)
-            /* Zero pad x87 tenbyte long doubles */
-            if (size == LDOUBLE_SIZE)
-                vtop->c.tab[2] &= 0xffff;
-#endif
-            ptr = section_ptr_add(data_section, size);
-            size = size >> 2;
-#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
-            check.d = 1;
-            if(check.tab[0])
-                for(i=0;i<size;i++)
-                    ptr[i] = vtop->c.tab[size-1-i];
-            else
-#endif
-            for(i=0;i<size;i++)
-                ptr[i] = vtop->c.tab[i];
-            sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
-            vtop->r |= VT_LVAL | VT_SYM;
-            vtop->sym = sym;
-            vtop->c.ul = 0;
-        }
-#ifdef CONFIG_TCC_BCHECK
-        if (vtop->r & VT_MUSTBOUND) 
-            gbound();
-#endif
-
-        r = vtop->r & VT_VALMASK;
-        rc2 = RC_INT;
-        if (rc == RC_IRET)
-            rc2 = RC_LRET;
-        /* need to reload if:
-           - constant
-           - lvalue (need to dereference pointer)
-           - already a register, but not in the right class */
-        if (r >= VT_CONST || 
-            (vtop->r & VT_LVAL) ||
-            !(reg_classes[r] & rc) ||
-            ((vtop->type.t & VT_BTYPE) == VT_LLONG && 
-             !(reg_classes[vtop->r2] & rc2))) {
-            r = get_reg(rc);
-#ifndef TCC_TARGET_X86_64
-            if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
-                int r2;
-                unsigned long long ll;
-                /* two register type load : expand to two words
-                   temporarily */
-                if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
-                    /* load constant */
-                    ll = vtop->c.ull;
-                    vtop->c.ui = ll; /* first word */
-                    load(r, vtop);
-                    vtop->r = r; /* save register value */
-                    vpushi(ll >> 32); /* second word */
-                } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
-                           (vtop->r & VT_LVAL)) {
-                    /* We do not want to modifier the long long
-                       pointer here, so the safest (and less
-                       efficient) is to save all the other registers
-                       in the stack. XXX: totally inefficient. */
-                    save_regs(1);
-                    /* load from memory */
-                    load(r, vtop);
-                    vdup();
-                    vtop[-1].r = r; /* save register value */
-                    /* increment pointer to get second word */
-                    vtop->type.t = VT_INT;
-                    gaddrof();
-                    vpushi(4);
-                    gen_op('+');
-                    vtop->r |= VT_LVAL;
-                } else {
-                    /* move registers */
-                    load(r, vtop);
-                    vdup();
-                    vtop[-1].r = r; /* save register value */
-                    vtop->r = vtop[-1].r2;
-                }
-                /* allocate second register */
-                r2 = get_reg(rc2);
-                load(r2, vtop);
-                vpop();
-                /* write second register */
-                vtop->r2 = r2;
-            } else
-#endif
-            if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
-                int t1, t;
-                /* lvalue of scalar type : need to use lvalue type
-                   because of possible cast */
-                t = vtop->type.t;
-                t1 = t;
-                /* compute memory access type */
-                if (vtop->r & VT_LVAL_BYTE)
-                    t = VT_BYTE;
-                else if (vtop->r & VT_LVAL_SHORT)
-                    t = VT_SHORT;
-                if (vtop->r & VT_LVAL_UNSIGNED)
-                    t |= VT_UNSIGNED;
-                vtop->type.t = t;
-                load(r, vtop);
-                /* restore wanted type */
-                vtop->type.t = t1;
-            } else {
-                /* one register type load */
-                load(r, vtop);
-            }
-        }
-        vtop->r = r;
-#ifdef TCC_TARGET_C67
-        /* uses register pairs for doubles */
-        if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) 
-            vtop->r2 = r+1;
-#endif
-    }
-    return r;
-}
-
-/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
-void gv2(int rc1, int rc2)
-{
-    int v;
-
-    /* generate more generic register first. But VT_JMP or VT_CMP
-       values must be generated first in all cases to avoid possible
-       reload errors */
-    v = vtop[0].r & VT_VALMASK;
-    if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
-        vswap();
-        gv(rc1);
-        vswap();
-        gv(rc2);
-        /* test if reload is needed for first register */
-        if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
-            vswap();
-            gv(rc1);
-            vswap();
-        }
-    } else {
-        gv(rc2);
-        vswap();
-        gv(rc1);
-        vswap();
-        /* test if reload is needed for first register */
-        if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
-            gv(rc2);
-        }
-    }
-}
-
-/* wrapper around RC_FRET to return a register by type */
-int rc_fret(int t)
-{
-#ifdef TCC_TARGET_X86_64
-    if (t == VT_LDOUBLE) {
-        return RC_ST0;
-    }
-#endif
-    return RC_FRET;
-}
-
-/* wrapper around REG_FRET to return a register by type */
-int reg_fret(int t)
-{
-#ifdef TCC_TARGET_X86_64
-    if (t == VT_LDOUBLE) {
-        return TREG_ST0;
-    }
-#endif
-    return REG_FRET;
-}
-
-/* expand long long on stack in two int registers */
-void lexpand(void)
-{
-    int u;
-
-    u = vtop->type.t & VT_UNSIGNED;
-    gv(RC_INT);
-    vdup();
-    vtop[0].r = vtop[-1].r2;
-    vtop[0].r2 = VT_CONST;
-    vtop[-1].r2 = VT_CONST;
-    vtop[0].type.t = VT_INT | u;
-    vtop[-1].type.t = VT_INT | u;
-}
-
-#ifdef TCC_TARGET_ARM
-/* expand long long on stack */
-void lexpand_nr(void)
-{
-    int u,v;
-
-    u = vtop->type.t & VT_UNSIGNED;
-    vdup();
-    vtop->r2 = VT_CONST;
-    vtop->type.t = VT_INT | u;
-    v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
-    if (v == VT_CONST) {
-      vtop[-1].c.ui = vtop->c.ull;
-      vtop->c.ui = vtop->c.ull >> 32;
-      vtop->r = VT_CONST;
-    } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
-      vtop->c.ui += 4;
-      vtop->r = vtop[-1].r;
-    } else if (v > VT_CONST) {
-      vtop--;
-      lexpand();
-    } else
-      vtop->r = vtop[-1].r2;
-    vtop[-1].r2 = VT_CONST;
-    vtop[-1].type.t = VT_INT | u;
-}
-#endif
-
-/* build a long long from two ints */
-void lbuild(int t)
-{
-    gv2(RC_INT, RC_INT);
-    vtop[-1].r2 = vtop[0].r;
-    vtop[-1].type.t = t;
-    vpop();
-}
-
-/* rotate n first stack elements to the bottom 
-   I1 ... In -> I2 ... In I1 [top is right]
-*/
-void vrotb(int n)
-{
-    int i;
-    SValue tmp;
-
-    tmp = vtop[-n + 1];
-    for(i=-n+1;i!=0;i++)
-        vtop[i] = vtop[i+1];
-    vtop[0] = tmp;
-}
-
-/* rotate n first stack elements to the top 
-   I1 ... In -> In I1 ... I(n-1)  [top is right]
- */
-void vrott(int n)
-{
-    int i;
-    SValue tmp;
-
-    tmp = vtop[0];
-    for(i = 0;i < n - 1; i++)
-        vtop[-i] = vtop[-i - 1];
-    vtop[-n + 1] = tmp;
-}
-
-#ifdef TCC_TARGET_ARM
-/* like vrott but in other direction
-   In ... I1 -> I(n-1) ... I1 In  [top is right]
- */
-void vnrott(int n)
-{
-    int i;
-    SValue tmp;
-
-    tmp = vtop[-n + 1];
-    for(i = n - 1; i > 0; i--)
-        vtop[-i] = vtop[-i + 1];
-    vtop[0] = tmp;
-}
-#endif
-
-/* pop stack value */
-void vpop(void)
-{
-    int v;
-    v = vtop->r & VT_VALMASK;
-#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
-    /* for x86, we need to pop the FP stack */
-    if (v == TREG_ST0 && !nocode_wanted) {
-        o(0xd9dd); /* fstp %st(1) */
-    } else
-#endif
-    if (v == VT_JMP || v == VT_JMPI) {
-        /* need to put correct jump if && or || without test */
-        gsym(vtop->c.ul);
-    }
-    vtop--;
-}
-
-/* convert stack entry to register and duplicate its value in another
-   register */
-void gv_dup(void)
-{
-    int rc, t, r, r1;
-    SValue sv;
-
-    t = vtop->type.t;
-    if ((t & VT_BTYPE) == VT_LLONG) {
-        lexpand();
-        gv_dup();
-        vswap();
-        vrotb(3);
-        gv_dup();
-        vrotb(4);
-        /* stack: H L L1 H1 */
-        lbuild(t);
-        vrotb(3);
-        vrotb(3);
-        vswap();
-        lbuild(t);
-        vswap();
-    } else {
-        /* duplicate value */
-        rc = RC_INT;
-        sv.type.t = VT_INT;
-        if (is_float(t)) {
-            rc = RC_FLOAT;
-#ifdef TCC_TARGET_X86_64
-            if ((t & VT_BTYPE) == VT_LDOUBLE) {
-                rc = RC_ST0;
-            }
-#endif
-            sv.type.t = t;
-        }
-        r = gv(rc);
-        r1 = get_reg(rc);
-        sv.r = r;
-        sv.c.ul = 0;
-        load(r1, &sv); /* move r to r1 */
-        vdup();
-        /* duplicates value */
-        vtop->r = r1;
-    }
-}
-
-#ifndef TCC_TARGET_X86_64
-/* generate CPU independent (unsigned) long long operations */
-void gen_opl(int op)
-{
-    int t, a, b, op1, c, i;
-    int func;
-    unsigned short reg_iret = REG_IRET;
-    unsigned short reg_lret = REG_LRET;
-    SValue tmp;
-
-    switch(op) {
-    case '/':
-    case TOK_PDIV:
-        func = TOK___divdi3;
-        goto gen_func;
-    case TOK_UDIV:
-        func = TOK___udivdi3;
-        goto gen_func;
-    case '%':
-        func = TOK___moddi3;
-        goto gen_mod_func;
-    case TOK_UMOD:
-        func = TOK___umoddi3;
-    gen_mod_func:
-#ifdef TCC_ARM_EABI
-        reg_iret = TREG_R2;
-        reg_lret = TREG_R3;
-#endif
-    gen_func:
-        /* call generic long long function */
-        vpush_global_sym(&func_old_type, func);
-        vrott(3);
-        gfunc_call(2);
-        vpushi(0);
-        vtop->r = reg_iret;
-        vtop->r2 = reg_lret;
-        break;
-    case '^':
-    case '&':
-    case '|':
-    case '*':
-    case '+':
-    case '-':
-        t = vtop->type.t;
-        vswap();
-        lexpand();
-        vrotb(3);
-        lexpand();
-        /* stack: L1 H1 L2 H2 */
-        tmp = vtop[0];
-        vtop[0] = vtop[-3];
-        vtop[-3] = tmp;
-        tmp = vtop[-2];
-        vtop[-2] = vtop[-3];
-        vtop[-3] = tmp;
-        vswap();
-        /* stack: H1 H2 L1 L2 */
-        if (op == '*') {
-            vpushv(vtop - 1);
-            vpushv(vtop - 1);
-            gen_op(TOK_UMULL);
-            lexpand();
-            /* stack: H1 H2 L1 L2 ML MH */
-            for(i=0;i<4;i++)
-                vrotb(6);
-            /* stack: ML MH H1 H2 L1 L2 */
-            tmp = vtop[0];
-            vtop[0] = vtop[-2];
-            vtop[-2] = tmp;
-            /* stack: ML MH H1 L2 H2 L1 */
-            gen_op('*');
-            vrotb(3);
-            vrotb(3);
-            gen_op('*');
-            /* stack: ML MH M1 M2 */
-            gen_op('+');
-            gen_op('+');
-        } else if (op == '+' || op == '-') {
-            /* XXX: add non carry method too (for MIPS or alpha) */
-            if (op == '+')
-                op1 = TOK_ADDC1;
-            else
-                op1 = TOK_SUBC1;
-            gen_op(op1);
-            /* stack: H1 H2 (L1 op L2) */
-            vrotb(3);
-            vrotb(3);
-            gen_op(op1 + 1); /* TOK_xxxC2 */
-        } else {
-            gen_op(op);
-            /* stack: H1 H2 (L1 op L2) */
-            vrotb(3);
-            vrotb(3);
-            /* stack: (L1 op L2) H1 H2 */
-            gen_op(op);
-            /* stack: (L1 op L2) (H1 op H2) */
-        }
-        /* stack: L H */
-        lbuild(t);
-        break;
-    case TOK_SAR:
-    case TOK_SHR:
-    case TOK_SHL:
-        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-            t = vtop[-1].type.t;
-            vswap();
-            lexpand();
-            vrotb(3);
-            /* stack: L H shift */
-            c = (int)vtop->c.i;
-            /* constant: simpler */
-            /* NOTE: all comments are for SHL. the other cases are
-               done by swaping words */
-            vpop();
-            if (op != TOK_SHL)
-                vswap();
-            if (c >= 32) {
-                /* stack: L H */
-                vpop();
-                if (c > 32) {
-                    vpushi(c - 32);
-                    gen_op(op);
-                }
-                if (op != TOK_SAR) {
-                    vpushi(0);
-                } else {
-                    gv_dup();
-                    vpushi(31);
-                    gen_op(TOK_SAR);
-                }
-                vswap();
-            } else {
-                vswap();
-                gv_dup();
-                /* stack: H L L */
-                vpushi(c);
-                gen_op(op);
-                vswap();
-                vpushi(32 - c);
-                if (op == TOK_SHL)
-                    gen_op(TOK_SHR);
-                else
-                    gen_op(TOK_SHL);
-                vrotb(3);
-                /* stack: L L H */
-                vpushi(c);
-                if (op == TOK_SHL)
-                    gen_op(TOK_SHL);
-                else
-                    gen_op(TOK_SHR);
-                gen_op('|');
-            }
-            if (op != TOK_SHL)
-                vswap();
-            lbuild(t);
-        } else {
-            /* XXX: should provide a faster fallback on x86 ? */
-            switch(op) {
-            case TOK_SAR:
-                func = TOK___ashrdi3;
-                goto gen_func;
-            case TOK_SHR:
-                func = TOK___lshrdi3;
-                goto gen_func;
-            case TOK_SHL:
-                func = TOK___ashldi3;
-                goto gen_func;
-            }
-        }
-        break;
-    default:
-        /* compare operations */
-        t = vtop->type.t;
-        vswap();
-        lexpand();
-        vrotb(3);
-        lexpand();
-        /* stack: L1 H1 L2 H2 */
-        tmp = vtop[-1];
-        vtop[-1] = vtop[-2];
-        vtop[-2] = tmp;
-        /* stack: L1 L2 H1 H2 */
-        /* compare high */
-        op1 = op;
-        /* when values are equal, we need to compare low words. since
-           the jump is inverted, we invert the test too. */
-        if (op1 == TOK_LT)
-            op1 = TOK_LE;
-        else if (op1 == TOK_GT)
-            op1 = TOK_GE;
-        else if (op1 == TOK_ULT)
-            op1 = TOK_ULE;
-        else if (op1 == TOK_UGT)
-            op1 = TOK_UGE;
-        a = 0;
-        b = 0;
-        gen_op(op1);
-        if (op1 != TOK_NE) {
-            a = gtst(1, 0);
-        }
-        if (op != TOK_EQ) {
-            /* generate non equal test */
-            /* XXX: NOT PORTABLE yet */
-            if (a == 0) {
-                b = gtst(0, 0);
-            } else {
-#if defined(TCC_TARGET_I386)
-                b = psym(0x850f, 0);
-#elif defined(TCC_TARGET_ARM)
-                b = ind;
-                o(0x1A000000 | encbranch(ind, 0, 1));
-#elif defined(TCC_TARGET_C67)
-                error("not implemented");
-#else
-#error not supported
-#endif
-            }
-        }
-        /* compare low. Always unsigned */
-        op1 = op;
-        if (op1 == TOK_LT)
-            op1 = TOK_ULT;
-        else if (op1 == TOK_LE)
-            op1 = TOK_ULE;
-        else if (op1 == TOK_GT)
-            op1 = TOK_UGT;
-        else if (op1 == TOK_GE)
-            op1 = TOK_UGE;
-        gen_op(op1);
-        a = gtst(1, a);
-        gsym(b);
-        vseti(VT_JMPI, a);
-        break;
-    }
-}
-#endif
-
-/* handle integer constant optimizations and various machine
-   independent opt */
-void gen_opic(int op)
-{
-    int c1, c2, t1, t2, n;
-    SValue *v1, *v2;
-    long long l1, l2;
-    typedef unsigned long long U;
-
-    v1 = vtop - 1;
-    v2 = vtop;
-    t1 = v1->type.t & VT_BTYPE;
-    t2 = v2->type.t & VT_BTYPE;
-
-    if (t1 == VT_LLONG)
-        l1 = v1->c.ll;
-    else if (v1->type.t & VT_UNSIGNED)
-        l1 = v1->c.ui;
-    else
-        l1 = v1->c.i;
-
-    if (t2 == VT_LLONG)
-        l2 = v2->c.ll;
-    else if (v2->type.t & VT_UNSIGNED)
-        l2 = v2->c.ui;
-    else
-        l2 = v2->c.i;
-
-    /* currently, we cannot do computations with forward symbols */
-    c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
-    c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
-    if (c1 && c2) {
-        switch(op) {
-        case '+': l1 += l2; break;
-        case '-': l1 -= l2; break;
-        case '&': l1 &= l2; break;
-        case '^': l1 ^= l2; break;
-        case '|': l1 |= l2; break;
-        case '*': l1 *= l2; break;
-
-        case TOK_PDIV:
-        case '/':
-        case '%':
-        case TOK_UDIV:
-        case TOK_UMOD:
-            /* if division by zero, generate explicit division */
-            if (l2 == 0) {
-                if (const_wanted)
-                    error("division by zero in constant");
-                goto general_case;
-            }
-            switch(op) {
-            default: l1 /= l2; break;
-            case '%': l1 %= l2; break;
-            case TOK_UDIV: l1 = (U)l1 / l2; break;
-            case TOK_UMOD: l1 = (U)l1 % l2; break;
-            }
-            break;
-        case TOK_SHL: l1 <<= l2; break;
-        case TOK_SHR: l1 = (U)l1 >> l2; break;
-        case TOK_SAR: l1 >>= l2; break;
-            /* tests */
-        case TOK_ULT: l1 = (U)l1 < (U)l2; break;
-        case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
-        case TOK_EQ: l1 = l1 == l2; break;
-        case TOK_NE: l1 = l1 != l2; break;
-        case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
-        case TOK_UGT: l1 = (U)l1 > (U)l2; break;
-        case TOK_LT: l1 = l1 < l2; break;
-        case TOK_GE: l1 = l1 >= l2; break;
-        case TOK_LE: l1 = l1 <= l2; break;
-        case TOK_GT: l1 = l1 > l2; break;
-            /* logical */
-        case TOK_LAND: l1 = l1 && l2; break;
-        case TOK_LOR: l1 = l1 || l2; break;
-        default:
-            goto general_case;
-        }
-        v1->c.ll = l1;
-        vtop--;
-    } else {
-        /* if commutative ops, put c2 as constant */
-        if (c1 && (op == '+' || op == '&' || op == '^' || 
-                   op == '|' || op == '*')) {
-            vswap();
-            c2 = c1; //c = c1, c1 = c2, c2 = c;
-            l2 = l1; //l = l1, l1 = l2, l2 = l;
-        }
-        /* Filter out NOP operations like x*1, x-0, x&-1... */
-        if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV || 
-                     op == TOK_PDIV) && 
-                    l2 == 1) ||
-                   ((op == '+' || op == '-' || op == '|' || op == '^' || 
-                     op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) && 
-                    l2 == 0) ||
-                   (op == '&' && 
-                    l2 == -1))) {
-            /* nothing to do */
-            vtop--;
-        } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
-            /* try to use shifts instead of muls or divs */
-            if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
-                n = -1;
-                while (l2) {
-                    l2 >>= 1;
-                    n++;
-                }
-                vtop->c.ll = n;
-                if (op == '*')
-                    op = TOK_SHL;
-                else if (op == TOK_PDIV)
-                    op = TOK_SAR;
-                else
-                    op = TOK_SHR;
-            }
-            goto general_case;
-        } else if (c2 && (op == '+' || op == '-') &&
-                   ((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
-                   (VT_CONST | VT_SYM) ||
-                   (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
-            /* symbol + constant case */
-            if (op == '-')
-                l2 = -l2;
-            vtop--;
-            vtop->c.ll += l2;
-        } else {
-        general_case:
-            if (!nocode_wanted) {
-                /* call low level op generator */
-                if (t1 == VT_LLONG || t2 == VT_LLONG) 
-                    gen_opl(op);
-                else
-                    gen_opi(op);
-            } else {
-                vtop--;
-            }
-        }
-    }
-}
-
-/* generate a floating point operation with constant propagation */
-void gen_opif(int op)
-{
-    int c1, c2;
-    SValue *v1, *v2;
-    long double f1, f2;
-
-    v1 = vtop - 1;
-    v2 = vtop;
-    /* currently, we cannot do computations with forward symbols */
-    c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
-    c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
-    if (c1 && c2) {
-        if (v1->type.t == VT_FLOAT) {
-            f1 = v1->c.f;
-            f2 = v2->c.f;
-        } else if (v1->type.t == VT_DOUBLE) {
-            f1 = v1->c.d;
-            f2 = v2->c.d;
-        } else {
-            f1 = v1->c.ld;
-            f2 = v2->c.ld;
-        }
-
-        /* NOTE: we only do constant propagation if finite number (not
-           NaN or infinity) (ANSI spec) */
-        if (!ieee_finite(f1) || !ieee_finite(f2))
-            goto general_case;
-
-        switch(op) {
-        case '+': f1 += f2; break;
-        case '-': f1 -= f2; break;
-        case '*': f1 *= f2; break;
-        case '/': 
-            if (f2 == 0.0) {
-                if (const_wanted)
-                    error("division by zero in constant");
-                goto general_case;
-            }
-            f1 /= f2; 
-            break;
-            /* XXX: also handles tests ? */
-        default:
-            goto general_case;
-        }
-        /* XXX: overflow test ? */
-        if (v1->type.t == VT_FLOAT) {
-            v1->c.f = f1;
-        } else if (v1->type.t == VT_DOUBLE) {
-            v1->c.d = f1;
-        } else {
-            v1->c.ld = f1;
-        }
-        vtop--;
-    } else {
-    general_case:
-        if (!nocode_wanted) {
-            gen_opf(op);
-        } else {
-            vtop--;
-        }
-    }
-}
-
-static int pointed_size(CType *type)
-{
-    int align;
-    return type_size(pointed_type(type), &align);
-}
-
-static inline int is_null_pointer(SValue *p)
-{
-    if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
-        return 0;
-    return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
-        ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
-}
-
-static inline int is_integer_btype(int bt)
-{
-    return (bt == VT_BYTE || bt == VT_SHORT || 
-            bt == VT_INT || bt == VT_LLONG);
-}
-
-/* check types for comparison or substraction of pointers */
-static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
-{
-    CType *type1, *type2, tmp_type1, tmp_type2;
-    int bt1, bt2;
-    
-    /* null pointers are accepted for all comparisons as gcc */
-    if (is_null_pointer(p1) || is_null_pointer(p2))
-        return;
-    type1 = &p1->type;
-    type2 = &p2->type;
-    bt1 = type1->t & VT_BTYPE;
-    bt2 = type2->t & VT_BTYPE;
-    /* accept comparison between pointer and integer with a warning */
-    if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
-        if (op != TOK_LOR && op != TOK_LAND )
-            warning("comparison between pointer and integer");
-        return;
-    }
-
-    /* both must be pointers or implicit function pointers */
-    if (bt1 == VT_PTR) {
-        type1 = pointed_type(type1);
-    } else if (bt1 != VT_FUNC) 
-        goto invalid_operands;
-
-    if (bt2 == VT_PTR) {
-        type2 = pointed_type(type2);
-    } else if (bt2 != VT_FUNC) { 
-    invalid_operands:
-        error("invalid operands to binary %s", get_tok_str(op, NULL));
-    }
-    if ((type1->t & VT_BTYPE) == VT_VOID || 
-        (type2->t & VT_BTYPE) == VT_VOID)
-        return;
-    tmp_type1 = *type1;
-    tmp_type2 = *type2;
-    tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
-    tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
-    if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
-        /* gcc-like error if '-' is used */
-        if (op == '-')
-            goto invalid_operands;
-        else
-            warning("comparison of distinct pointer types lacks a cast");
-    }
-}
-
-/* generic gen_op: handles types problems */
-void gen_op(int op)
-{
-    int u, t1, t2, bt1, bt2, t;
-    CType type1;
-
-    t1 = vtop[-1].type.t;
-    t2 = vtop[0].type.t;
-    bt1 = t1 & VT_BTYPE;
-    bt2 = t2 & VT_BTYPE;
-        
-    if (bt1 == VT_PTR || bt2 == VT_PTR) {
-        /* at least one operand is a pointer */
-        /* relationnal op: must be both pointers */
-        if (op >= TOK_ULT && op <= TOK_LOR) {
-            check_comparison_pointer_types(vtop - 1, vtop, op);
-            /* pointers are handled are unsigned */
-#ifdef TCC_TARGET_X86_64
-            t = VT_LLONG | VT_UNSIGNED;
-#else
-            t = VT_INT | VT_UNSIGNED;
-#endif
-            goto std_op;
-        }
-        /* if both pointers, then it must be the '-' op */
-        if (bt1 == VT_PTR && bt2 == VT_PTR) {
-            if (op != '-')
-                error("cannot use pointers here");
-            check_comparison_pointer_types(vtop - 1, vtop, op);
-            /* XXX: check that types are compatible */
-            u = pointed_size(&vtop[-1].type);
-            gen_opic(op);
-            /* set to integer type */
-#ifdef TCC_TARGET_X86_64
-            vtop->type.t = VT_LLONG;
-#else
-            vtop->type.t = VT_INT; 
-#endif
-            vpushi(u);
-            gen_op(TOK_PDIV);
-        } else {
-            /* exactly one pointer : must be '+' or '-'. */
-            if (op != '-' && op != '+')
-                error("cannot use pointers here");
-            /* Put pointer as first operand */
-            if (bt2 == VT_PTR) {
-                vswap();
-                swap(&t1, &t2);
-            }
-            type1 = vtop[-1].type;
-#ifdef TCC_TARGET_X86_64
-            vpushll(pointed_size(&vtop[-1].type));
-#else
-            /* XXX: cast to int ? (long long case) */
-            vpushi(pointed_size(&vtop[-1].type));
-#endif
-            gen_op('*');
-#ifdef CONFIG_TCC_BCHECK
-            /* if evaluating constant expression, no code should be
-               generated, so no bound check */
-            if (tcc_state->do_bounds_check && !const_wanted) {
-                /* if bounded pointers, we generate a special code to
-                   test bounds */
-                if (op == '-') {
-                    vpushi(0);
-                    vswap();
-                    gen_op('-');
-                }
-                gen_bounded_ptr_add();
-            } else
-#endif
-            {
-                gen_opic(op);
-            }
-            /* put again type if gen_opic() swaped operands */
-            vtop->type = type1;
-        }
-    } else if (is_float(bt1) || is_float(bt2)) {
-        /* compute bigger type and do implicit casts */
-        if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
-            t = VT_LDOUBLE;
-        } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
-            t = VT_DOUBLE;
-        } else {
-            t = VT_FLOAT;
-        }
-        /* floats can only be used for a few operations */
-        if (op != '+' && op != '-' && op != '*' && op != '/' &&
-            (op < TOK_ULT || op > TOK_GT))
-            error("invalid operands for binary operation");
-        goto std_op;
-    } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
-        /* cast to biggest op */
-        t = VT_LLONG;
-        /* convert to unsigned if it does not fit in a long long */
-        if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
-            (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
-            t |= VT_UNSIGNED;
-        goto std_op;
-    } else {
-        /* integer operations */
-        t = VT_INT;
-        /* convert to unsigned if it does not fit in an integer */
-        if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
-            (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
-            t |= VT_UNSIGNED;
-    std_op:
-        /* XXX: currently, some unsigned operations are explicit, so
-           we modify them here */
-        if (t & VT_UNSIGNED) {
-            if (op == TOK_SAR)
-                op = TOK_SHR;
-            else if (op == '/')
-                op = TOK_UDIV;
-            else if (op == '%')
-                op = TOK_UMOD;
-            else if (op == TOK_LT)
-                op = TOK_ULT;
-            else if (op == TOK_GT)
-                op = TOK_UGT;
-            else if (op == TOK_LE)
-                op = TOK_ULE;
-            else if (op == TOK_GE)
-                op = TOK_UGE;
-        }
-        vswap();
-        type1.t = t;
-        gen_cast(&type1);
-        vswap();
-        /* special case for shifts and long long: we keep the shift as
-           an integer */
-        if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
-            type1.t = VT_INT;
-        gen_cast(&type1);
-        if (is_float(t))
-            gen_opif(op);
-        else
-            gen_opic(op);
-        if (op >= TOK_ULT && op <= TOK_GT) {
-            /* relationnal op: the result is an int */
-            vtop->type.t = VT_INT;
-        } else {
-            vtop->type.t = t;
-        }
-    }
-}
-
-#ifndef TCC_TARGET_ARM
-/* generic itof for unsigned long long case */
-void gen_cvt_itof1(int t)
-{
-    if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == 
-        (VT_LLONG | VT_UNSIGNED)) {
-
-        if (t == VT_FLOAT)
-            vpush_global_sym(&func_old_type, TOK___floatundisf);
-#if LDOUBLE_SIZE != 8
-        else if (t == VT_LDOUBLE)
-            vpush_global_sym(&func_old_type, TOK___floatundixf);
-#endif
-        else
-            vpush_global_sym(&func_old_type, TOK___floatundidf);
-        vrott(2);
-        gfunc_call(1);
-        vpushi(0);
-        vtop->r = reg_fret(t);
-    } else {
-        gen_cvt_itof(t);
-    }
-}
-#endif
-
-/* generic ftoi for unsigned long long case */
-void gen_cvt_ftoi1(int t)
-{
-    int st;
-
-    if (t == (VT_LLONG | VT_UNSIGNED)) {
-        /* not handled natively */
-        st = vtop->type.t & VT_BTYPE;
-        if (st == VT_FLOAT)
-            vpush_global_sym(&func_old_type, TOK___fixunssfdi);
-#if LDOUBLE_SIZE != 8
-        else if (st == VT_LDOUBLE)
-            vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
-#endif
-        else
-            vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
-        vrott(2);
-        gfunc_call(1);
-        vpushi(0);
-        vtop->r = REG_IRET;
-        vtop->r2 = REG_LRET;
-    } else {
-        gen_cvt_ftoi(t);
-    }
-}
-
-/* force char or short cast */
-void force_charshort_cast(int t)
-{
-    int bits, dbt;
-    dbt = t & VT_BTYPE;
-    /* XXX: add optimization if lvalue : just change type and offset */
-    if (dbt == VT_BYTE)
-        bits = 8;
-    else
-        bits = 16;
-    if (t & VT_UNSIGNED) {
-        vpushi((1 << bits) - 1);
-        gen_op('&');
-    } else {
-        bits = 32 - bits;
-        vpushi(bits);
-        gen_op(TOK_SHL);
-        /* result must be signed or the SAR is converted to an SHL
-           This was not the case when "t" was a signed short
-           and the last value on the stack was an unsigned int */
-        vtop->type.t &= ~VT_UNSIGNED;
-        vpushi(bits);
-        gen_op(TOK_SAR);
-    }
-}
-
-/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
-static void gen_cast(CType *type)
-{
-    int sbt, dbt, sf, df, c, p;
-
-    /* special delayed cast for char/short */
-    /* XXX: in some cases (multiple cascaded casts), it may still
-       be incorrect */
-    if (vtop->r & VT_MUSTCAST) {
-        vtop->r &= ~VT_MUSTCAST;
-        force_charshort_cast(vtop->type.t);
-    }
-
-    /* bitfields first get cast to ints */
-    if (vtop->type.t & VT_BITFIELD) {
-        gv(RC_INT);
-    }
-
-    dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
-    sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
-
-    if (sbt != dbt) {
-        sf = is_float(sbt);
-        df = is_float(dbt);
-        c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
-        p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM);
-        if (c) {
-            /* constant case: we can do it now */
-            /* XXX: in ISOC, cannot do it if error in convert */
-            if (sbt == VT_FLOAT)
-                vtop->c.ld = vtop->c.f;
-            else if (sbt == VT_DOUBLE)
-                vtop->c.ld = vtop->c.d;
-
-            if (df) {
-                if ((sbt & VT_BTYPE) == VT_LLONG) {
-                    if (sbt & VT_UNSIGNED)
-                        vtop->c.ld = vtop->c.ull;
-                    else
-                        vtop->c.ld = vtop->c.ll;
-                } else if(!sf) {
-                    if (sbt & VT_UNSIGNED)
-                        vtop->c.ld = vtop->c.ui;
-                    else
-                        vtop->c.ld = vtop->c.i;
-                }
-
-                if (dbt == VT_FLOAT)
-                    vtop->c.f = (float)vtop->c.ld;
-                else if (dbt == VT_DOUBLE)
-                    vtop->c.d = (double)vtop->c.ld;
-            } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
-                vtop->c.ull = (unsigned long long)vtop->c.ld;
-            } else if (sf && dbt == VT_BOOL) {
-                vtop->c.i = (vtop->c.ld != 0);
-            } else {
-                if(sf)
-                    vtop->c.ll = (long long)vtop->c.ld;
-                else if (sbt == (VT_LLONG|VT_UNSIGNED))
-                    vtop->c.ll = vtop->c.ull;
-                else if (sbt & VT_UNSIGNED)
-                    vtop->c.ll = vtop->c.ui;
-                else if (sbt != VT_LLONG)
-                    vtop->c.ll = vtop->c.i;
-
-                if (dbt == (VT_LLONG|VT_UNSIGNED))
-                    vtop->c.ull = vtop->c.ll;
-                else if (dbt == VT_BOOL)
-                    vtop->c.i = (vtop->c.ll != 0);
-                else if (dbt != VT_LLONG) {
-                    int s = 0;
-                    if ((dbt & VT_BTYPE) == VT_BYTE)
-                        s = 24;
-                    else if ((dbt & VT_BTYPE) == VT_SHORT)
-                        s = 16;
-
-                    if(dbt & VT_UNSIGNED)
-                        vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s;
-                    else
-                        vtop->c.i = ((int)vtop->c.ll << s) >> s;
-                }
-            }
-        } else if (p && dbt == VT_BOOL) {
-            vtop->r = VT_CONST;
-            vtop->c.i = 1;
-        } else if (!nocode_wanted) {
-            /* non constant case: generate code */
-            if (sf && df) {
-                /* convert from fp to fp */
-                gen_cvt_ftof(dbt);
-            } else if (df) {
-                /* convert int to fp */
-                gen_cvt_itof1(dbt);
-            } else if (sf) {
-                /* convert fp to int */
-                if (dbt == VT_BOOL) {
-                     vpushi(0);
-                     gen_op(TOK_NE);
-                } else {
-                    /* we handle char/short/etc... with generic code */
-                    if (dbt != (VT_INT | VT_UNSIGNED) &&
-                        dbt != (VT_LLONG | VT_UNSIGNED) &&
-                        dbt != VT_LLONG)
-                        dbt = VT_INT;
-                    gen_cvt_ftoi1(dbt);
-                    if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
-                        /* additional cast for char/short... */
-                        vtop->type.t = dbt;
-                        gen_cast(type);
-                    }
-                }
-#ifndef TCC_TARGET_X86_64
-            } else if ((dbt & VT_BTYPE) == VT_LLONG) {
-                if ((sbt & VT_BTYPE) != VT_LLONG) {
-                    /* scalar to long long */
-                    /* machine independent conversion */
-                    gv(RC_INT);
-                    /* generate high word */
-                    if (sbt == (VT_INT | VT_UNSIGNED)) {
-                        vpushi(0);
-                        gv(RC_INT);
-                    } else {
-                        if (sbt == VT_PTR) {
-                            /* cast from pointer to int before we apply
-                               shift operation, which pointers don't support*/
-                            gen_cast(&int_type);
-                        }
-                        gv_dup();
-                        vpushi(31);
-                        gen_op(TOK_SAR);
-                    }
-                    /* patch second register */
-                    vtop[-1].r2 = vtop->r;
-                    vpop();
-                }
-#else
-            } else if ((dbt & VT_BTYPE) == VT_LLONG ||
-                       (dbt & VT_BTYPE) == VT_PTR) {
-                /* XXX: not sure if this is perfect... need more tests */
-                if ((sbt & VT_BTYPE) != VT_LLONG) {
-                    int r = gv(RC_INT);
-                    if (sbt != (VT_INT | VT_UNSIGNED) &&
-                        sbt != VT_PTR && sbt != VT_FUNC) {
-                        /* x86_64 specific: movslq */
-                        o(0x6348);
-                        o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
-                    }
-                }
-#endif
-            } else if (dbt == VT_BOOL) {
-                /* scalar to bool */
-                vpushi(0);
-                gen_op(TOK_NE);
-            } else if ((dbt & VT_BTYPE) == VT_BYTE || 
-                       (dbt & VT_BTYPE) == VT_SHORT) {
-                if (sbt == VT_PTR) {
-                    vtop->type.t = VT_INT;
-                    warning("nonportable conversion from pointer to char/short");
-                }
-                force_charshort_cast(dbt);
-            } else if ((dbt & VT_BTYPE) == VT_INT) {
-                /* scalar to int */
-                if (sbt == VT_LLONG) {
-                    /* from long long: just take low order word */
-                    lexpand();
-                    vpop();
-                } 
-                /* if lvalue and single word type, nothing to do because
-                   the lvalue already contains the real type size (see
-                   VT_LVAL_xxx constants) */
-            }
-        }
-    } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
-        /* if we are casting between pointer types,
-           we must update the VT_LVAL_xxx size */
-        vtop->r = (vtop->r & ~VT_LVAL_TYPE)
-                  | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
-    }
-    vtop->type = *type;
-}
-
-/* return type size. Put alignment at 'a' */
-static int type_size(CType *type, int *a)
-{
-    Sym *s;
-    int bt;
-
-    bt = type->t & VT_BTYPE;
-    if (bt == VT_STRUCT) {
-        /* struct/union */
-        s = type->ref;
-        *a = s->r;
-        return s->c;
-    } else if (bt == VT_PTR) {
-        if (type->t & VT_ARRAY) {
-            int ts;
-
-            s = type->ref;
-            ts = type_size(&s->type, a);
-
-            if (ts < 0 && s->c < 0)
-                ts = -ts;
-
-            return ts * s->c;
-        } else {
-            *a = PTR_SIZE;
-            return PTR_SIZE;
-        }
-    } else if (bt == VT_LDOUBLE) {
-        *a = LDOUBLE_ALIGN;
-        return LDOUBLE_SIZE;
-    } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
-#ifdef TCC_TARGET_I386
-#ifdef TCC_TARGET_PE
-        *a = 8;
-#else
-        *a = 4;
-#endif
-#elif defined(TCC_TARGET_ARM)
-#ifdef TCC_ARM_EABI
-        *a = 8; 
-#else
-        *a = 4;
-#endif
-#else
-        *a = 8;
-#endif
-        return 8;
-    } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
-        *a = 4;
-        return 4;
-    } else if (bt == VT_SHORT) {
-        *a = 2;
-        return 2;
-    } else {
-        /* char, void, function, _Bool */
-        *a = 1;
-        return 1;
-    }
-}
-
-/* return the pointed type of t */
-static inline CType *pointed_type(CType *type)
-{
-    return &type->ref->type;
-}
-
-/* modify type so that its it is a pointer to type. */
-static void mk_pointer(CType *type)
-{
-    Sym *s;
-    s = sym_push(SYM_FIELD, type, 0, -1);
-    type->t = VT_PTR | (type->t & ~VT_TYPE);
-    type->ref = s;
-}
-
-/* compare function types. OLD functions match any new functions */
-static int is_compatible_func(CType *type1, CType *type2)
-{
-    Sym *s1, *s2;
-
-    s1 = type1->ref;
-    s2 = type2->ref;
-    if (!is_compatible_types(&s1->type, &s2->type))
-        return 0;
-    /* check func_call */
-    if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
-        return 0;
-    /* XXX: not complete */
-    if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
-        return 1;
-    if (s1->c != s2->c)
-        return 0;
-    while (s1 != NULL) {
-        if (s2 == NULL)
-            return 0;
-        if (!is_compatible_parameter_types(&s1->type, &s2->type))
-            return 0;
-        s1 = s1->next;
-        s2 = s2->next;
-    }
-    if (s2)
-        return 0;
-    return 1;
-}
-
-/* return true if type1 and type2 are the same.  If unqualified is
-   true, qualifiers on the types are ignored.
-
-   - enums are not checked as gcc __builtin_types_compatible_p () 
- */
-static int compare_types(CType *type1, CType *type2, int unqualified)
-{
-    int bt1, t1, t2;
-
-    t1 = type1->t & VT_TYPE;
-    t2 = type2->t & VT_TYPE;
-    if (unqualified) {
-        /* strip qualifiers before comparing */
-        t1 &= ~(VT_CONSTANT | VT_VOLATILE);
-        t2 &= ~(VT_CONSTANT | VT_VOLATILE);
-    }
-    /* XXX: bitfields ? */
-    if (t1 != t2)
-        return 0;
-    /* test more complicated cases */
-    bt1 = t1 & VT_BTYPE;
-    if (bt1 == VT_PTR) {
-        type1 = pointed_type(type1);
-        type2 = pointed_type(type2);
-        return is_compatible_types(type1, type2);
-    } else if (bt1 == VT_STRUCT) {
-        return (type1->ref == type2->ref);
-    } else if (bt1 == VT_FUNC) {
-        return is_compatible_func(type1, type2);
-    } else {
-        return 1;
-    }
-}
-
-/* return true if type1 and type2 are exactly the same (including
-   qualifiers). 
-*/
-static int is_compatible_types(CType *type1, CType *type2)
-{
-    return compare_types(type1,type2,0);
-}
-
-/* return true if type1 and type2 are the same (ignoring qualifiers).
-*/
-static int is_compatible_parameter_types(CType *type1, CType *type2)
-{
-    return compare_types(type1,type2,1);
-}
-
-/* print a type. If 'varstr' is not NULL, then the variable is also
-   printed in the type */
-/* XXX: union */
-/* XXX: add array and function pointers */
-void type_to_str(char *buf, int buf_size, 
-                 CType *type, const char *varstr)
-{
-    int bt, v, t;
-    Sym *s, *sa;
-    char buf1[256];
-    const char *tstr;
-
-    t = type->t & VT_TYPE;
-    bt = t & VT_BTYPE;
-    buf[0] = '\0';
-    if (t & VT_CONSTANT)
-        pstrcat(buf, buf_size, "const ");
-    if (t & VT_VOLATILE)
-        pstrcat(buf, buf_size, "volatile ");
-    if (t & VT_UNSIGNED)
-        pstrcat(buf, buf_size, "unsigned ");
-    switch(bt) {
-    case VT_VOID:
-        tstr = "void";
-        goto add_tstr;
-    case VT_BOOL:
-        tstr = "_Bool";
-        goto add_tstr;
-    case VT_BYTE:
-        tstr = "char";
-        goto add_tstr;
-    case VT_SHORT:
-        tstr = "short";
-        goto add_tstr;
-    case VT_INT:
-        tstr = "int";
-        goto add_tstr;
-    case VT_LONG:
-        tstr = "long";
-        goto add_tstr;
-    case VT_LLONG:
-        tstr = "long long";
-        goto add_tstr;
-    case VT_FLOAT:
-        tstr = "float";
-        goto add_tstr;
-    case VT_DOUBLE:
-        tstr = "double";
-        goto add_tstr;
-    case VT_LDOUBLE:
-        tstr = "long double";
-    add_tstr:
-        pstrcat(buf, buf_size, tstr);
-        break;
-    case VT_ENUM:
-    case VT_STRUCT:
-        if (bt == VT_STRUCT)
-            tstr = "struct ";
-        else
-            tstr = "enum ";
-        pstrcat(buf, buf_size, tstr);
-        v = type->ref->v & ~SYM_STRUCT;
-        if (v >= SYM_FIRST_ANOM)
-            pstrcat(buf, buf_size, "<anonymous>");
-        else
-            pstrcat(buf, buf_size, get_tok_str(v, NULL));
-        break;
-    case VT_FUNC:
-        s = type->ref;
-        type_to_str(buf, buf_size, &s->type, varstr);
-        pstrcat(buf, buf_size, "(");
-        sa = s->next;
-        while (sa != NULL) {
-            type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
-            pstrcat(buf, buf_size, buf1);
-            sa = sa->next;
-            if (sa)
-                pstrcat(buf, buf_size, ", ");
-        }
-        pstrcat(buf, buf_size, ")");
-        goto no_var;
-    case VT_PTR:
-        s = type->ref;
-        pstrcpy(buf1, sizeof(buf1), "*");
-        if (varstr)
-            pstrcat(buf1, sizeof(buf1), varstr);
-        type_to_str(buf, buf_size, &s->type, buf1);
-        goto no_var;
-    }
-    if (varstr) {
-        pstrcat(buf, buf_size, " ");
-        pstrcat(buf, buf_size, varstr);
-    }
- no_var: ;
-}
-
-/* verify type compatibility to store vtop in 'dt' type, and generate
-   casts if needed. */
-static void gen_assign_cast(CType *dt)
-{
-    CType *st, *type1, *type2, tmp_type1, tmp_type2;
-    char buf1[256], buf2[256];
-    int dbt, sbt;
-
-    st = &vtop->type; /* source type */
-    dbt = dt->t & VT_BTYPE;
-    sbt = st->t & VT_BTYPE;
-    if (dt->t & VT_CONSTANT)
-        warning("assignment of read-only location");
-    switch(dbt) {
-    case VT_PTR:
-        /* special cases for pointers */
-        /* '0' can also be a pointer */
-        if (is_null_pointer(vtop))
-            goto type_ok;
-        /* accept implicit pointer to integer cast with warning */
-        if (is_integer_btype(sbt)) {
-            warning("assignment makes pointer from integer without a cast");
-            goto type_ok;
-        }
-        type1 = pointed_type(dt);
-        /* a function is implicitely a function pointer */
-        if (sbt == VT_FUNC) {
-            if ((type1->t & VT_BTYPE) != VT_VOID &&
-                !is_compatible_types(pointed_type(dt), st))
-                goto error;
-            else
-                goto type_ok;
-        }
-        if (sbt != VT_PTR)
-            goto error;
-        type2 = pointed_type(st);
-        if ((type1->t & VT_BTYPE) == VT_VOID || 
-            (type2->t & VT_BTYPE) == VT_VOID) {
-            /* void * can match anything */
-        } else {
-            /* exact type match, except for unsigned */
-            tmp_type1 = *type1;
-            tmp_type2 = *type2;
-            tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
-            tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
-            if (!is_compatible_types(&tmp_type1, &tmp_type2))
-                warning("assignment from incompatible pointer type");
-        }
-        /* check const and volatile */
-        if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
-            (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
-            warning("assignment discards qualifiers from pointer target type");
-        break;
-    case VT_BYTE:
-    case VT_SHORT:
-    case VT_INT:
-    case VT_LLONG:
-        if (sbt == VT_PTR || sbt == VT_FUNC) {
-            warning("assignment makes integer from pointer without a cast");
-        }
-        /* XXX: more tests */
-        break;
-    case VT_STRUCT:
-        tmp_type1 = *dt;
-        tmp_type2 = *st;
-        tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
-        tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
-        if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
-        error:
-            type_to_str(buf1, sizeof(buf1), st, NULL);
-            type_to_str(buf2, sizeof(buf2), dt, NULL);
-            error("cannot cast '%s' to '%s'", buf1, buf2);
-        }
-        break;
-    }
- type_ok:
-    gen_cast(dt);
-}
-
-/* store vtop in lvalue pushed on stack */
-void vstore(void)
-{
-    int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
-
-    ft = vtop[-1].type.t;
-    sbt = vtop->type.t & VT_BTYPE;
-    dbt = ft & VT_BTYPE;
-    if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
-        (sbt == VT_INT && dbt == VT_SHORT)) {
-        /* optimize char/short casts */
-        delayed_cast = VT_MUSTCAST;
-        vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
-        /* XXX: factorize */
-        if (ft & VT_CONSTANT)
-            warning("assignment of read-only location");
-    } else {
-        delayed_cast = 0;
-        if (!(ft & VT_BITFIELD))
-            gen_assign_cast(&vtop[-1].type);
-    }
-
-    if (sbt == VT_STRUCT) {
-        /* if structure, only generate pointer */
-        /* structure assignment : generate memcpy */
-        /* XXX: optimize if small size */
-        if (!nocode_wanted) {
-            size = type_size(&vtop->type, &align);
-
-#ifdef TCC_ARM_EABI
-            if(!(align & 7))
-                vpush_global_sym(&func_old_type, TOK_memcpy8);
-            else if(!(align & 3))
-                vpush_global_sym(&func_old_type, TOK_memcpy4);
-            else
-#endif
-            vpush_global_sym(&func_old_type, TOK_memcpy);
-
-            /* destination */
-            vpushv(vtop - 2);
-            vtop->type.t = VT_PTR;
-            gaddrof();
-            /* source */
-            vpushv(vtop - 2);
-            vtop->type.t = VT_PTR;
-            gaddrof();
-            /* type size */
-            vpushi(size);
-            gfunc_call(3);
-            
-            vswap();
-            vpop();
-        } else {
-            vswap();
-            vpop();
-        }
-        /* leave source on stack */
-    } else if (ft & VT_BITFIELD) {
-        /* bitfield store handling */
-        bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
-        bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
-        /* remove bit field info to avoid loops */
-        vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
-
-        /* duplicate source into other register */
-        gv_dup();
-        vswap();
-        vrott(3);
-
-        if((ft & VT_BTYPE) == VT_BOOL) {
-            gen_cast(&vtop[-1].type);
-            vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
-        }
-
-        /* duplicate destination */
-        vdup();
-        vtop[-1] = vtop[-2];
-
-        /* mask and shift source */
-        if((ft & VT_BTYPE) != VT_BOOL) {
-            if((ft & VT_BTYPE) == VT_LLONG) {
-                vpushll((1ULL << bit_size) - 1ULL);
-            } else {
-                vpushi((1 << bit_size) - 1);
-            }
-            gen_op('&');
-        }
-        vpushi(bit_pos);
-        gen_op(TOK_SHL);
-        /* load destination, mask and or with source */
-        vswap();
-        if((ft & VT_BTYPE) == VT_LLONG) {
-            vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos));
-        } else {
-            vpushi(~(((1 << bit_size) - 1) << bit_pos));
-        }
-        gen_op('&');
-        gen_op('|');
-        /* store result */
-        vstore();
-
-        /* pop off shifted source from "duplicate source..." above */
-        vpop();
-
-    } else {
-#ifdef CONFIG_TCC_BCHECK
-        /* bound check case */
-        if (vtop[-1].r & VT_MUSTBOUND) {
-            vswap();
-            gbound();
-            vswap();
-        }
-#endif
-        if (!nocode_wanted) {
-            rc = RC_INT;
-            if (is_float(ft)) {
-                rc = RC_FLOAT;
-#ifdef TCC_TARGET_X86_64
-                if ((ft & VT_BTYPE) == VT_LDOUBLE) {
-                    rc = RC_ST0;
-                }
-#endif
-            }
-            r = gv(rc);  /* generate value */
-            /* if lvalue was saved on stack, must read it */
-            if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
-                SValue sv;
-                t = get_reg(RC_INT);
-#ifdef TCC_TARGET_X86_64
-                sv.type.t = VT_PTR;
-#else
-                sv.type.t = VT_INT;
-#endif
-                sv.r = VT_LOCAL | VT_LVAL;
-                sv.c.ul = vtop[-1].c.ul;
-                load(t, &sv);
-                vtop[-1].r = t | VT_LVAL;
-            }
-            store(r, vtop - 1);
-#ifndef TCC_TARGET_X86_64
-            /* two word case handling : store second register at word + 4 */
-            if ((ft & VT_BTYPE) == VT_LLONG) {
-                vswap();
-                /* convert to int to increment easily */
-                vtop->type.t = VT_INT;
-                gaddrof();
-                vpushi(4);
-                gen_op('+');
-                vtop->r |= VT_LVAL;
-                vswap();
-                /* XXX: it works because r2 is spilled last ! */
-                store(vtop->r2, vtop - 1);
-            }
-#endif
-        }
-        vswap();
-        vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
-        vtop->r |= delayed_cast;
-    }
-}
-
-/* post defines POST/PRE add. c is the token ++ or -- */
-void inc(int post, int c)
-{
-    test_lvalue();
-    vdup(); /* save lvalue */
-    if (post) {
-        gv_dup(); /* duplicate value */
-        vrotb(3);
-        vrotb(3);
-    }
-    /* add constant */
-    vpushi(c - TOK_MID); 
-    gen_op('+');
-    vstore(); /* store value */
-    if (post)
-        vpop(); /* if post op, return saved value */
-}
-
-/* Parse GNUC __attribute__ extension. Currently, the following
-   extensions are recognized:
-   - aligned(n) : set data/function alignment.
-   - packed : force data alignment to 1
-   - section(x) : generate data/code in this section.
-   - unused : currently ignored, but may be used someday.
-   - regparm(n) : pass function parameters in registers (i386 only)
- */
-static void parse_attribute(AttributeDef *ad)
-{
-    int t, n;
-    
-    while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
-    next();
-    skip('(');
-    skip('(');
-    while (tok != ')') {
-        if (tok < TOK_IDENT)
-            expect("attribute name");
-        t = tok;
-        next();
-        switch(t) {
-        case TOK_SECTION1:
-        case TOK_SECTION2:
-            skip('(');
-            if (tok != TOK_STR)
-                expect("section name");
-            ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
-            next();
-            skip(')');
-            break;
-        case TOK_ALIGNED1:
-        case TOK_ALIGNED2:
-            if (tok == '(') {
-                next();
-                n = expr_const();
-                if (n <= 0 || (n & (n - 1)) != 0) 
-                    error("alignment must be a positive power of two");
-                skip(')');
-            } else {
-                n = MAX_ALIGN;
-            }
-            ad->aligned = n;
-            break;
-        case TOK_PACKED1:
-        case TOK_PACKED2:
-            ad->packed = 1;
-            break;
-        case TOK_UNUSED1:
-        case TOK_UNUSED2:
-            /* currently, no need to handle it because tcc does not
-               track unused objects */
-            break;
-        case TOK_NORETURN1:
-        case TOK_NORETURN2:
-            /* currently, no need to handle it because tcc does not
-               track unused objects */
-            break;
-        case TOK_CDECL1:
-        case TOK_CDECL2:
-        case TOK_CDECL3:
-            FUNC_CALL(ad->func_attr) = FUNC_CDECL;
-            break;
-        case TOK_STDCALL1:
-        case TOK_STDCALL2:
-        case TOK_STDCALL3:
-            FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
-            break;
-#ifdef TCC_TARGET_I386
-        case TOK_REGPARM1:
-        case TOK_REGPARM2:
-            skip('(');
-            n = expr_const();
-            if (n > 3) 
-                n = 3;
-            else if (n < 0)
-                n = 0;
-            if (n > 0)
-                FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
-            skip(')');
-            break;
-        case TOK_FASTCALL1:
-        case TOK_FASTCALL2:
-        case TOK_FASTCALL3:
-            FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
-            break;            
-#endif
-        case TOK_DLLEXPORT:
-            FUNC_EXPORT(ad->func_attr) = 1;
-            break;
-        default:
-            if (tcc_state->warn_unsupported)
-                warning("'%s' attribute ignored", get_tok_str(t, NULL));
-            /* skip parameters */
-            if (tok == '(') {
-                int parenthesis = 0;
-                do {
-                    if (tok == '(') 
-                        parenthesis++;
-                    else if (tok == ')') 
-                        parenthesis--;
-                    next();
-                } while (parenthesis && tok != -1);
-            }
-            break;
-        }
-        if (tok != ',')
-            break;
-        next();
-    }
-    skip(')');
-    skip(')');
-    }
-}
-
-/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
-static void struct_decl(CType *type, int u)
-{
-    int a, v, size, align, maxalign, c, offset;
-    int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt;
-    Sym *s, *ss, *ass, **ps;
-    AttributeDef ad;
-    CType type1, btype;
-
-    a = tok; /* save decl type */
-    next();
-    if (tok != '{') {
-        v = tok;
-        next();
-        /* struct already defined ? return it */
-        if (v < TOK_IDENT)
-            expect("struct/union/enum name");
-        s = struct_find(v);
-        if (s) {
-            if (s->type.t != a)
-                error("invalid type");
-            goto do_decl;
-        }
-    } else {
-        v = anon_sym++;
-    }
-    type1.t = a;
-    /* we put an undefined size for struct/union */
-    s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
-    s->r = 0; /* default alignment is zero as gcc */
-    /* put struct/union/enum name in type */
- do_decl:
-    type->t = u;
-    type->ref = s;
-    
-    if (tok == '{') {
-        next();
-        if (s->c != -1)
-            error("struct/union/enum already defined");
-        /* cannot be empty */
-        c = 0;
-        /* non empty enums are not allowed */
-        if (a == TOK_ENUM) {
-            for(;;) {
-                v = tok;
-                if (v < TOK_UIDENT)
-                    expect("identifier");
-                next();
-                if (tok == '=') {
-                    next();
-                    c = expr_const();
-                }
-                /* enum symbols have static storage */
-                ss = sym_push(v, &int_type, VT_CONST, c);
-                ss->type.t |= VT_STATIC;
-                if (tok != ',')
-                    break;
-                next();
-                c++;
-                /* NOTE: we accept a trailing comma */
-                if (tok == '}')
-                    break;
-            }
-            skip('}');
-        } else {
-            maxalign = 1;
-            ps = &s->next;
-            prevbt = VT_INT;
-            bit_pos = 0;
-            offset = 0;
-            while (tok != '}') {
-                parse_btype(&btype, &ad);
-                while (1) {
-                    bit_size = -1;
-                    v = 0;
-                    type1 = btype;
-                    if (tok != ':') {
-                        type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
-                        if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
-                            expect("identifier");
-                        if ((type1.t & VT_BTYPE) == VT_FUNC ||
-                            (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
-                            error("invalid type for '%s'", 
-                                  get_tok_str(v, NULL));
-                    }
-                    if (tok == ':') {
-                        next();
-                        bit_size = expr_const();
-                        /* XXX: handle v = 0 case for messages */
-                        if (bit_size < 0)
-                            error("negative width in bit-field '%s'", 
-                                  get_tok_str(v, NULL));
-                        if (v && bit_size == 0)
-                            error("zero width for bit-field '%s'", 
-                                  get_tok_str(v, NULL));
-                    }
-                    size = type_size(&type1, &align);
-                    if (ad.aligned) {
-                        if (align < ad.aligned)
-                            align = ad.aligned;
-                    } else if (ad.packed) {
-                        align = 1;
-                    } else if (*tcc_state->pack_stack_ptr) {
-                        if (align > *tcc_state->pack_stack_ptr)
-                            align = *tcc_state->pack_stack_ptr;
-                    }
-                    lbit_pos = 0;
-                    if (bit_size >= 0) {
-                        bt = type1.t & VT_BTYPE;
-                        if (bt != VT_INT && 
-                            bt != VT_BYTE && 
-                            bt != VT_SHORT &&
-                            bt != VT_BOOL &&
-                            bt != VT_ENUM &&
-                            bt != VT_LLONG)
-                            error("bitfields must have scalar type");
-                        bsize = size * 8;
-                        if (bit_size > bsize) {
-                            error("width of '%s' exceeds its type",
-                                  get_tok_str(v, NULL));
-                        } else if (bit_size == bsize) {
-                            /* no need for bit fields */
-                            bit_pos = 0;
-                        } else if (bit_size == 0) {
-                            /* XXX: what to do if only padding in a
-                               structure ? */
-                            /* zero size: means to pad */
-                            bit_pos = 0;
-                        } else {
-                            /* we do not have enough room ?
-                               did the type change?
-                               is it a union? */
-                            if ((bit_pos + bit_size) > bsize ||
-                                bt != prevbt || a == TOK_UNION)
-                                bit_pos = 0;
-                            lbit_pos = bit_pos;
-                            /* XXX: handle LSB first */
-                            type1.t |= VT_BITFIELD | 
-                                (bit_pos << VT_STRUCT_SHIFT) |
-                                (bit_size << (VT_STRUCT_SHIFT + 6));
-                            bit_pos += bit_size;
-                        }
-                        prevbt = bt;
-                    } else {
-                        bit_pos = 0;
-                    }
-                    if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
-                        /* add new memory data only if starting
-                           bit field */
-                        if (lbit_pos == 0) {
-                            if (a == TOK_STRUCT) {
-                                c = (c + align - 1) & -align;
-                                offset = c;
-                                if (size > 0)
-                                    c += size;
-                            } else {
-                                offset = 0;
-                                if (size > c)
-                                    c = size;
-                            }
-                            if (align > maxalign)
-                                maxalign = align;
-                        }
-#if 0
-                        printf("add field %s offset=%d", 
-                               get_tok_str(v, NULL), offset);
-                        if (type1.t & VT_BITFIELD) {
-                            printf(" pos=%d size=%d", 
-                                   (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
-                                   (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
-                        }
-                        printf("\n");
-#endif
-                    }
-                    if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
-                        ass = type1.ref;
-                        while ((ass = ass->next) != NULL) {
-                           ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
-                           *ps = ss;
-                           ps = &ss->next;
-                        }
-                    } else if (v) {
-                        ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
-                        *ps = ss;
-                        ps = &ss->next;
-                    }
-                    if (tok == ';' || tok == TOK_EOF)
-                        break;
-                    skip(',');
-                }
-                skip(';');
-            }
-            skip('}');
-            /* store size and alignment */
-            s->c = (c + maxalign - 1) & -maxalign; 
-            s->r = maxalign;
-        }
-    }
-}
-
-/* return 0 if no type declaration. otherwise, return the basic type
-   and skip it. 
- */
-static int parse_btype(CType *type, AttributeDef *ad)
-{
-    int t, u, type_found, typespec_found, typedef_found;
-    Sym *s;
-    CType type1;
-
-    memset(ad, 0, sizeof(AttributeDef));
-    type_found = 0;
-    typespec_found = 0;
-    typedef_found = 0;
-    t = 0;
-    while(1) {
-        switch(tok) {
-        case TOK_EXTENSION:
-            /* currently, we really ignore extension */
-            next();
-            continue;
-
-            /* basic types */
-        case TOK_CHAR:
-            u = VT_BYTE;
-        basic_type:
-            next();
-        basic_type1:
-            if ((t & VT_BTYPE) != 0)
-                error("too many basic types");
-            t |= u;
-            typespec_found = 1;
-            break;
-        case TOK_VOID:
-            u = VT_VOID;
-            goto basic_type;
-        case TOK_SHORT:
-            u = VT_SHORT;
-            goto basic_type;
-        case TOK_INT:
-            next();
-            typespec_found = 1;
-            break;
-        case TOK_LONG:
-            next();
-            if ((t & VT_BTYPE) == VT_DOUBLE) {
-                t = (t & ~VT_BTYPE) | VT_LDOUBLE;
-            } else if ((t & VT_BTYPE) == VT_LONG) {
-                t = (t & ~VT_BTYPE) | VT_LLONG;
-            } else {
-                u = VT_LONG;
-                goto basic_type1;
-            }
-            break;
-        case TOK_BOOL:
-            u = VT_BOOL;
-            goto basic_type;
-        case TOK_FLOAT:
-            u = VT_FLOAT;
-            goto basic_type;
-        case TOK_DOUBLE:
-            next();
-            if ((t & VT_BTYPE) == VT_LONG) {
-                t = (t & ~VT_BTYPE) | VT_LDOUBLE;
-            } else {
-                u = VT_DOUBLE;
-                goto basic_type1;
-            }
-            break;
-        case TOK_ENUM:
-            struct_decl(&type1, VT_ENUM);
-        basic_type2:
-            u = type1.t;
-            type->ref = type1.ref;
-            goto basic_type1;
-        case TOK_STRUCT:
-        case TOK_UNION:
-            struct_decl(&type1, VT_STRUCT);
-            goto basic_type2;
-
-            /* type modifiers */
-        case TOK_CONST1:
-        case TOK_CONST2:
-        case TOK_CONST3:
-            t |= VT_CONSTANT;
-            next();
-            break;
-        case TOK_VOLATILE1:
-        case TOK_VOLATILE2:
-        case TOK_VOLATILE3:
-            t |= VT_VOLATILE;
-            next();
-            break;
-        case TOK_SIGNED1:
-        case TOK_SIGNED2:
-        case TOK_SIGNED3:
-            typespec_found = 1;
-            t |= VT_SIGNED;
-            next();
-            break;
-        case TOK_REGISTER:
-        case TOK_AUTO:
-        case TOK_RESTRICT1:
-        case TOK_RESTRICT2:
-        case TOK_RESTRICT3:
-            next();
-            break;
-        case TOK_UNSIGNED:
-            t |= VT_UNSIGNED;
-            next();
-            typespec_found = 1;
-            break;
-
-            /* storage */
-        case TOK_EXTERN:
-            t |= VT_EXTERN;
-            next();
-            break;
-        case TOK_STATIC:
-            t |= VT_STATIC;
-            next();
-            break;
-        case TOK_TYPEDEF:
-            t |= VT_TYPEDEF;
-            next();
-            break;
-        case TOK_INLINE1:
-        case TOK_INLINE2:
-        case TOK_INLINE3:
-            t |= VT_INLINE;
-            next();
-            break;
-
-            /* GNUC attribute */
-        case TOK_ATTRIBUTE1:
-        case TOK_ATTRIBUTE2:
-            parse_attribute(ad);
-            break;
-            /* GNUC typeof */
-        case TOK_TYPEOF1:
-        case TOK_TYPEOF2:
-        case TOK_TYPEOF3:
-            next();
-            parse_expr_type(&type1);
-            goto basic_type2;
-        default:
-            if (typespec_found || typedef_found)
-                goto the_end;
-            s = sym_find(tok);
-            if (!s || !(s->type.t & VT_TYPEDEF))
-                goto the_end;
-            typedef_found = 1;
-            t |= (s->type.t & ~VT_TYPEDEF);
-            type->ref = s->type.ref;
-            next();
-            typespec_found = 1;
-            break;
-        }
-        type_found = 1;
-    }
-the_end:
-    if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
-        error("signed and unsigned modifier");
-    if (tcc_state->char_is_unsigned) {
-        if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
-            t |= VT_UNSIGNED;
-    }
-    t &= ~VT_SIGNED;
-
-    /* long is never used as type */
-    if ((t & VT_BTYPE) == VT_LONG)
-#ifndef TCC_TARGET_X86_64
-        t = (t & ~VT_BTYPE) | VT_INT;
-#else
-        t = (t & ~VT_BTYPE) | VT_LLONG;
-#endif
-    type->t = t;
-    return type_found;
-}
-
-/* convert a function parameter type (array to pointer and function to
-   function pointer) */
-static inline void convert_parameter_type(CType *pt)
-{
-    /* remove const and volatile qualifiers (XXX: const could be used
-       to indicate a const function parameter */
-    pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
-    /* array must be transformed to pointer according to ANSI C */
-    pt->t &= ~VT_ARRAY;
-    if ((pt->t & VT_BTYPE) == VT_FUNC) {
-        mk_pointer(pt);
-    }
-}
-
-static void post_type(CType *type, AttributeDef *ad)
-{
-    int n, l, t1, arg_size, align;
-    Sym **plast, *s, *first;
-    AttributeDef ad1;
-    CType pt;
-
-    if (tok == '(') {
-        /* function declaration */
-        next();
-        l = 0;
-        first = NULL;
-        plast = &first;
-        arg_size = 0;
-        if (tok != ')') {
-            for(;;) {
-                /* read param name and compute offset */
-                if (l != FUNC_OLD) {
-                    if (!parse_btype(&pt, &ad1)) {
-                        if (l) {
-                            error("invalid type");
-                        } else {
-                            l = FUNC_OLD;
-                            goto old_proto;
-                        }
-                    }
-                    l = FUNC_NEW;
-                    if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
-                        break;
-                    type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
-                    if ((pt.t & VT_BTYPE) == VT_VOID)
-                        error("parameter declared as void");
-                    arg_size += (type_size(&pt, &align) + 3) & ~3;
-                } else {
-                old_proto:
-                    n = tok;
-                    if (n < TOK_UIDENT)
-                        expect("identifier");
-                    pt.t = VT_INT;
-                    next();
-                }
-                convert_parameter_type(&pt);
-                s = sym_push(n | SYM_FIELD, &pt, 0, 0);
-                *plast = s;
-                plast = &s->next;
-                if (tok == ')')
-                    break;
-                skip(',');
-                if (l == FUNC_NEW && tok == TOK_DOTS) {
-                    l = FUNC_ELLIPSIS;
-                    next();
-                    break;
-                }
-            }
-        }
-        /* if no parameters, then old type prototype */
-        if (l == 0)
-            l = FUNC_OLD;
-        skip(')');
-        t1 = type->t & VT_STORAGE;
-        /* NOTE: const is ignored in returned type as it has a special
-           meaning in gcc / C++ */
-        type->t &= ~(VT_STORAGE | VT_CONSTANT); 
-        post_type(type, ad);
-        /* we push a anonymous symbol which will contain the function prototype */
-        FUNC_ARGS(ad->func_attr) = arg_size;
-        s = sym_push(SYM_FIELD, type, ad->func_attr, l);
-        s->next = first;
-        type->t = t1 | VT_FUNC;
-        type->ref = s;
-    } else if (tok == '[') {
-        /* array definition */
-        next();
-        if (tok == TOK_RESTRICT1)
-            next();
-        n = -1;
-        if (tok != ']') {
-            n = expr_const();
-            if (n < 0)
-                error("invalid array size");    
-        }
-        skip(']');
-        /* parse next post type */
-        t1 = type->t & VT_STORAGE;
-        type->t &= ~VT_STORAGE;
-        post_type(type, ad);
-        
-        /* we push a anonymous symbol which will contain the array
-           element type */
-        s = sym_push(SYM_FIELD, type, 0, n);
-        type->t = t1 | VT_ARRAY | VT_PTR;
-        type->ref = s;
-    }
-}
-
-/* Parse a type declaration (except basic type), and return the type
-   in 'type'. 'td' is a bitmask indicating which kind of type decl is
-   expected. 'type' should contain the basic type. 'ad' is the
-   attribute definition of the basic type. It can be modified by
-   type_decl(). 
- */
-static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
-{
-    Sym *s;
-    CType type1, *type2;
-    int qualifiers;
-    
-    while (tok == '*') {
-        qualifiers = 0;
-    redo:
-        next();
-        switch(tok) {
-        case TOK_CONST1:
-        case TOK_CONST2:
-        case TOK_CONST3:
-            qualifiers |= VT_CONSTANT;
-            goto redo;
-        case TOK_VOLATILE1:
-        case TOK_VOLATILE2:
-        case TOK_VOLATILE3:
-            qualifiers |= VT_VOLATILE;
-            goto redo;
-        case TOK_RESTRICT1:
-        case TOK_RESTRICT2:
-        case TOK_RESTRICT3:
-            goto redo;
-        }
-        mk_pointer(type);
-        type->t |= qualifiers;
-    }
-    
-    /* XXX: clarify attribute handling */
-    if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
-        parse_attribute(ad);
-
-    /* recursive type */
-    /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
-    type1.t = 0; /* XXX: same as int */
-    if (tok == '(') {
-        next();
-        /* XXX: this is not correct to modify 'ad' at this point, but
-           the syntax is not clear */
-        if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
-            parse_attribute(ad);
-        type_decl(&type1, ad, v, td);
-        skip(')');
-    } else {
-        /* type identifier */
-        if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
-            *v = tok;
-            next();
-        } else {
-            if (!(td & TYPE_ABSTRACT))
-                expect("identifier");
-            *v = 0;
-        }
-    }
-    post_type(type, ad);
-    if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
-        parse_attribute(ad);
-    if (!type1.t)
-        return;
-    /* append type at the end of type1 */
-    type2 = &type1;
-    for(;;) {
-        s = type2->ref;
-        type2 = &s->type;
-        if (!type2->t) {
-            *type2 = *type;
-            break;
-        }
-    }
-    *type = type1;
-}
-
-/* compute the lvalue VT_LVAL_xxx needed to match type t. */
-static int lvalue_type(int t)
-{
-    int bt, r;
-    r = VT_LVAL;
-    bt = t & VT_BTYPE;
-    if (bt == VT_BYTE || bt == VT_BOOL)
-        r |= VT_LVAL_BYTE;
-    else if (bt == VT_SHORT)
-        r |= VT_LVAL_SHORT;
-    else
-        return r;
-    if (t & VT_UNSIGNED)
-        r |= VT_LVAL_UNSIGNED;
-    return r;
-}
-
-/* indirection with full error checking and bound check */
-static void indir(void)
-{
-    if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
-        if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
-            return;
-        expect("pointer");
-    }
-    if ((vtop->r & VT_LVAL) && !nocode_wanted)
-        gv(RC_INT);
-    vtop->type = *pointed_type(&vtop->type);
-    /* Arrays and functions are never lvalues */
-    if (!(vtop->type.t & VT_ARRAY)
-        && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
-        vtop->r |= lvalue_type(vtop->type.t);
-        /* if bound checking, the referenced pointer must be checked */
-        if (tcc_state->do_bounds_check)
-            vtop->r |= VT_MUSTBOUND;
-    }
-}
-
-/* pass a parameter to a function and do type checking and casting */
-static void gfunc_param_typed(Sym *func, Sym *arg)
-{
-    int func_type;
-    CType type;
-
-    func_type = func->c;
-    if (func_type == FUNC_OLD ||
-        (func_type == FUNC_ELLIPSIS && arg == NULL)) {
-        /* default casting : only need to convert float to double */
-        if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
-            type.t = VT_DOUBLE;
-            gen_cast(&type);
-        }
-    } else if (arg == NULL) {
-        error("too many arguments to function");
-    } else {
-        type = arg->type;
-        type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
-        gen_assign_cast(&type);
-    }
-}
-
-/* parse an expression of the form '(type)' or '(expr)' and return its
-   type */
-static void parse_expr_type(CType *type)
-{
-    int n;
-    AttributeDef ad;
-
-    skip('(');
-    if (parse_btype(type, &ad)) {
-        type_decl(type, &ad, &n, TYPE_ABSTRACT);
-    } else {
-        expr_type(type);
-    }
-    skip(')');
-}
-
-static void parse_type(CType *type)
-{
-    AttributeDef ad;
-    int n;
-
-    if (!parse_btype(type, &ad)) {
-        expect("type");
-    }
-    type_decl(type, &ad, &n, TYPE_ABSTRACT);
-}
-
-static void vpush_tokc(int t)
-{
-    CType type;
-    type.t = t;
-    vsetc(&type, VT_CONST, &tokc);
-}
-
-static void unary(void)
-{
-    int n, t, align, size, r;
-    CType type;
-    Sym *s;
-    AttributeDef ad;
-
-    /* XXX: GCC 2.95.3 does not generate a table although it should be
-       better here */
- tok_next:
-    switch(tok) {
-    case TOK_EXTENSION:
-        next();
-        goto tok_next;
-    case TOK_CINT:
-    case TOK_CCHAR: 
-    case TOK_LCHAR:
-        vpushi(tokc.i);
-        next();
-        break;
-    case TOK_CUINT:
-        vpush_tokc(VT_INT | VT_UNSIGNED);
-        next();
-        break;
-    case TOK_CLLONG:
-        vpush_tokc(VT_LLONG);
-        next();
-        break;
-    case TOK_CULLONG:
-        vpush_tokc(VT_LLONG | VT_UNSIGNED);
-        next();
-        break;
-    case TOK_CFLOAT:
-        vpush_tokc(VT_FLOAT);
-        next();
-        break;
-    case TOK_CDOUBLE:
-        vpush_tokc(VT_DOUBLE);
-        next();
-        break;
-    case TOK_CLDOUBLE:
-        vpush_tokc(VT_LDOUBLE);
-        next();
-        break;
-    case TOK___FUNCTION__:
-        if (!gnu_ext)
-            goto tok_identifier;
-        /* fall thru */
-    case TOK___FUNC__:
-        {
-            void *ptr;
-            int len;
-            /* special function name identifier */
-            len = strlen(funcname) + 1;
-            /* generate char[len] type */
-            type.t = VT_BYTE;
-            mk_pointer(&type);
-            type.t |= VT_ARRAY;
-            type.ref->c = len;
-            vpush_ref(&type, data_section, data_section->data_offset, len);
-            ptr = section_ptr_add(data_section, len);
-            memcpy(ptr, funcname, len);
-            next();
-        }
-        break;
-    case TOK_LSTR:
-#ifdef TCC_TARGET_PE
-        t = VT_SHORT | VT_UNSIGNED;
-#else
-        t = VT_INT;
-#endif
-        goto str_init;
-    case TOK_STR:
-        /* string parsing */
-        t = VT_BYTE;
-    str_init:
-        if (tcc_state->warn_write_strings)
-            t |= VT_CONSTANT;
-        type.t = t;
-        mk_pointer(&type);
-        type.t |= VT_ARRAY;
-        memset(&ad, 0, sizeof(AttributeDef));
-        decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
-        break;
-    case '(':
-        next();
-        /* cast ? */
-        if (parse_btype(&type, &ad)) {
-            type_decl(&type, &ad, &n, TYPE_ABSTRACT);
-            skip(')');
-            /* check ISOC99 compound literal */
-            if (tok == '{') {
-                    /* data is allocated locally by default */
-                if (global_expr)
-                    r = VT_CONST;
-                else
-                    r = VT_LOCAL;
-                /* all except arrays are lvalues */
-                if (!(type.t & VT_ARRAY))
-                    r |= lvalue_type(type.t);
-                memset(&ad, 0, sizeof(AttributeDef));
-                decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
-            } else {
-                unary();
-                gen_cast(&type);
-            }
-        } else if (tok == '{') {
-            /* save all registers */
-            save_regs(0); 
-            /* statement expression : we do not accept break/continue
-               inside as GCC does */
-            block(NULL, NULL, NULL, NULL, 0, 1);
-            skip(')');
-        } else {
-            gexpr();
-            skip(')');
-        }
-        break;
-    case '*':
-        next();
-        unary();
-        indir();
-        break;
-    case '&':
-        next();
-        unary();
-        /* functions names must be treated as function pointers,
-           except for unary '&' and sizeof. Since we consider that
-           functions are not lvalues, we only have to handle it
-           there and in function calls. */
-        /* arrays can also be used although they are not lvalues */
-        if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
-            !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
-            test_lvalue();
-        mk_pointer(&vtop->type);
-        gaddrof();
-        break;
-    case '!':
-        next();
-        unary();
-        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-            CType boolean;
-            boolean.t = VT_BOOL;
-            gen_cast(&boolean);
-            vtop->c.i = !vtop->c.i;
-        } else if ((vtop->r & VT_VALMASK) == VT_CMP)
-            vtop->c.i = vtop->c.i ^ 1;
-        else {
-            save_regs(1);
-            vseti(VT_JMP, gtst(1, 0));
-        }
-        break;
-    case '~':
-        next();
-        unary();
-        vpushi(-1);
-        gen_op('^');
-        break;
-    case '+':
-        next();
-        /* in order to force cast, we add zero */
-        unary();
-        if ((vtop->type.t & VT_BTYPE) == VT_PTR)
-            error("pointer not accepted for unary plus");
-        vpushi(0);
-        gen_op('+');
-        break;
-    case TOK_SIZEOF:
-    case TOK_ALIGNOF1:
-    case TOK_ALIGNOF2:
-        t = tok;
-        next();
-        if (tok == '(') {
-            parse_expr_type(&type);
-        } else {
-            unary_type(&type);
-        }
-        size = type_size(&type, &align);
-        if (t == TOK_SIZEOF) {
-            if (size < 0)
-                error("sizeof applied to an incomplete type");
-            vpushi(size);
-        } else {
-            vpushi(align);
-        }
-        vtop->type.t |= VT_UNSIGNED;
-        break;
-
-    case TOK_builtin_types_compatible_p:
-        {
-            CType type1, type2;
-            next();
-            skip('(');
-            parse_type(&type1);
-            skip(',');
-            parse_type(&type2);
-            skip(')');
-            type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
-            type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
-            vpushi(is_compatible_types(&type1, &type2));
-        }
-        break;
-    case TOK_builtin_constant_p:
-        {
-            int saved_nocode_wanted, res;
-            next();
-            skip('(');
-            saved_nocode_wanted = nocode_wanted;
-            nocode_wanted = 1;
-            gexpr();
-            res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
-            vpop();
-            nocode_wanted = saved_nocode_wanted;
-            skip(')');
-            vpushi(res);
-        }
-        break;
-    case TOK_builtin_frame_address:
-        {
-            CType type;
-            next();
-            skip('(');
-            if (tok != TOK_CINT) {
-                error("__builtin_frame_address only takes integers");
-            }
-            if (tokc.i != 0) {
-                error("TCC only supports __builtin_frame_address(0)");
-            }
-            next();
-            skip(')');
-            type.t = VT_VOID;
-            mk_pointer(&type);
-            vset(&type, VT_LOCAL, 0);
-        }
-        break;
-#ifdef TCC_TARGET_X86_64
-    case TOK_builtin_malloc:
-        tok = TOK_malloc;
-        goto tok_identifier;
-    case TOK_builtin_free:
-        tok = TOK_free;
-        goto tok_identifier;
-#endif
-    case TOK_INC:
-    case TOK_DEC:
-        t = tok;
-        next();
-        unary();
-        inc(0, t);
-        break;
-    case '-':
-        next();
-        vpushi(0);
-        unary();
-        gen_op('-');
-        break;
-    case TOK_LAND:
-        if (!gnu_ext)
-            goto tok_identifier;
-        next();
-        /* allow to take the address of a label */
-        if (tok < TOK_UIDENT)
-            expect("label identifier");
-        s = label_find(tok);
-        if (!s) {
-            s = label_push(&global_label_stack, tok, LABEL_FORWARD);
-        } else {
-            if (s->r == LABEL_DECLARED)
-                s->r = LABEL_FORWARD;
-        }
-        if (!s->type.t) {
-            s->type.t = VT_VOID;
-            mk_pointer(&s->type);
-            s->type.t |= VT_STATIC;
-        }
-        vset(&s->type, VT_CONST | VT_SYM, 0);
-        vtop->sym = s;
-        next();
-        break;
-    default:
-    tok_identifier:
-        t = tok;
-        next();
-        if (t < TOK_UIDENT)
-            expect("identifier");
-        s = sym_find(t);
-        if (!s) {
-            if (tok != '(')
-                error("'%s' undeclared", get_tok_str(t, NULL));
-            /* for simple function calls, we tolerate undeclared
-               external reference to int() function */
-            if (tcc_state->warn_implicit_function_declaration)
-                warning("implicit declaration of function '%s'",
-                        get_tok_str(t, NULL));
-            s = external_global_sym(t, &func_old_type, 0); 
-        }
-        if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
-            (VT_STATIC | VT_INLINE | VT_FUNC)) {
-            /* if referencing an inline function, then we generate a
-               symbol to it if not already done. It will have the
-               effect to generate code for it at the end of the
-               compilation unit. Inline function as always
-               generated in the text section. */
-            if (!s->c)
-                put_extern_sym(s, text_section, 0, 0);
-            r = VT_SYM | VT_CONST;
-        } else {
-            r = s->r;
-        }
-        vset(&s->type, r, s->c);
-        /* if forward reference, we must point to s */
-        if (vtop->r & VT_SYM) {
-            vtop->sym = s;
-            vtop->c.ul = 0;
-        }
-        break;
-    }
-    
-    /* post operations */
-    while (1) {
-        if (tok == TOK_INC || tok == TOK_DEC) {
-            inc(1, tok);
-            next();
-        } else if (tok == '.' || tok == TOK_ARROW) {
-            /* field */ 
-            if (tok == TOK_ARROW) 
-                indir();
-            test_lvalue();
-            gaddrof();
-            next();
-            /* expect pointer on structure */
-            if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
-                expect("struct or union");
-            s = vtop->type.ref;
-            /* find field */
-            tok |= SYM_FIELD;
-            while ((s = s->next) != NULL) {
-                if (s->v == tok)
-                    break;
-            }
-            if (!s)
-                error("field not found: %s",  get_tok_str(tok & ~SYM_FIELD, NULL));
-            /* add field offset to pointer */
-            vtop->type = char_pointer_type; /* change type to 'char *' */
-            vpushi(s->c);
-            gen_op('+');
-            /* change type to field type, and set to lvalue */
-            vtop->type = s->type;
-            /* an array is never an lvalue */
-            if (!(vtop->type.t & VT_ARRAY)) {
-                vtop->r |= lvalue_type(vtop->type.t);
-                /* if bound checking, the referenced pointer must be checked */
-                if (tcc_state->do_bounds_check)
-                    vtop->r |= VT_MUSTBOUND;
-            }
-            next();
-        } else if (tok == '[') {
-            next();
-            gexpr();
-            gen_op('+');
-            indir();
-            skip(']');
-        } else if (tok == '(') {
-            SValue ret;
-            Sym *sa;
-            int nb_args;
-
-            /* function call  */
-            if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
-                /* pointer test (no array accepted) */
-                if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
-                    vtop->type = *pointed_type(&vtop->type);
-                    if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
-                        goto error_func;
-                } else {
-                error_func:
-                    expect("function pointer");
-                }
-            } else {
-                vtop->r &= ~VT_LVAL; /* no lvalue */
-            }
-            /* get return type */
-            s = vtop->type.ref;
-            next();
-            sa = s->next; /* first parameter */
-            nb_args = 0;
-            ret.r2 = VT_CONST;
-            /* compute first implicit argument if a structure is returned */
-            if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
-                /* get some space for the returned structure */
-                size = type_size(&s->type, &align);
-                loc = (loc - size) & -align;
-                ret.type = s->type;
-                ret.r = VT_LOCAL | VT_LVAL;
-                /* pass it as 'int' to avoid structure arg passing
-                   problems */
-                vseti(VT_LOCAL, loc);
-                ret.c = vtop->c;
-                nb_args++;
-            } else {
-                ret.type = s->type; 
-                /* return in register */
-                if (is_float(ret.type.t)) {
-                    ret.r = reg_fret(ret.type.t);
-                } else {
-                    if ((ret.type.t & VT_BTYPE) == VT_LLONG)
-                        ret.r2 = REG_LRET;
-                    ret.r = REG_IRET;
-                }
-                ret.c.i = 0;
-            }
-            if (tok != ')') {
-                for(;;) {
-                    expr_eq();
-                    gfunc_param_typed(s, sa);
-                    nb_args++;
-                    if (sa)
-                        sa = sa->next;
-                    if (tok == ')')
-                        break;
-                    skip(',');
-                }
-            }
-            if (sa)
-                error("too few arguments to function");
-            skip(')');
-            if (!nocode_wanted) {
-                gfunc_call(nb_args);
-            } else {
-                vtop -= (nb_args + 1);
-            }
-            /* return value */
-            vsetc(&ret.type, ret.r, &ret.c);
-            vtop->r2 = ret.r2;
-        } else {
-            break;
-        }
-    }
-}
-
-static void uneq(void)
-{
-    int t;
-    
-    unary();
-    if (tok == '=' ||
-        (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
-        tok == TOK_A_XOR || tok == TOK_A_OR ||
-        tok == TOK_A_SHL || tok == TOK_A_SAR) {
-        test_lvalue();
-        t = tok;
-        next();
-        if (t == '=') {
-            expr_eq();
-        } else {
-            vdup();
-            expr_eq();
-            gen_op(t & 0x7f);
-        }
-        vstore();
-    }
-}
-
-static void expr_prod(void)
-{
-    int t;
-
-    uneq();
-    while (tok == '*' || tok == '/' || tok == '%') {
-        t = tok;
-        next();
-        uneq();
-        gen_op(t);
-    }
-}
-
-static void expr_sum(void)
-{
-    int t;
-
-    expr_prod();
-    while (tok == '+' || tok == '-') {
-        t = tok;
-        next();
-        expr_prod();
-        gen_op(t);
-    }
-}
-
-static void expr_shift(void)
-{
-    int t;
-
-    expr_sum();
-    while (tok == TOK_SHL || tok == TOK_SAR) {
-        t = tok;
-        next();
-        expr_sum();
-        gen_op(t);
-    }
-}
-
-static void expr_cmp(void)
-{
-    int t;
-
-    expr_shift();
-    while ((tok >= TOK_ULE && tok <= TOK_GT) ||
-           tok == TOK_ULT || tok == TOK_UGE) {
-        t = tok;
-        next();
-        expr_shift();
-        gen_op(t);
-    }
-}
-
-static void expr_cmpeq(void)
-{
-    int t;
-
-    expr_cmp();
-    while (tok == TOK_EQ || tok == TOK_NE) {
-        t = tok;
-        next();
-        expr_cmp();
-        gen_op(t);
-    }
-}
-
-static void expr_and(void)
-{
-    expr_cmpeq();
-    while (tok == '&') {
-        next();
-        expr_cmpeq();
-        gen_op('&');
-    }
-}
-
-static void expr_xor(void)
-{
-    expr_and();
-    while (tok == '^') {
-        next();
-        expr_and();
-        gen_op('^');
-    }
-}
-
-static void expr_or(void)
-{
-    expr_xor();
-    while (tok == '|') {
-        next();
-        expr_xor();
-        gen_op('|');
-    }
-}
-
-/* XXX: fix this mess */
-static void expr_land_const(void)
-{
-    expr_or();
-    while (tok == TOK_LAND) {
-        next();
-        expr_or();
-        gen_op(TOK_LAND);
-    }
-}
-
-/* XXX: fix this mess */
-static void expr_lor_const(void)
-{
-    expr_land_const();
-    while (tok == TOK_LOR) {
-        next();
-        expr_land_const();
-        gen_op(TOK_LOR);
-    }
-}
-
-/* only used if non constant */
-static void expr_land(void)
-{
-    int t;
-
-    expr_or();
-    if (tok == TOK_LAND) {
-        t = 0;
-        save_regs(1);
-        for(;;) {
-            t = gtst(1, t);
-            if (tok != TOK_LAND) {
-                vseti(VT_JMPI, t);
-                break;
-            }
-            next();
-            expr_or();
-        }
-    }
-}
-
-static void expr_lor(void)
-{
-    int t;
-
-    expr_land();
-    if (tok == TOK_LOR) {
-        t = 0;
-        save_regs(1);
-        for(;;) {
-            t = gtst(0, t);
-            if (tok != TOK_LOR) {
-                vseti(VT_JMP, t);
-                break;
-            }
-            next();
-            expr_land();
-        }
-    }
-}
-
-/* XXX: better constant handling */
-static void expr_eq(void)
-{
-    int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
-    SValue sv;
-    CType type, type1, type2;
-
-    if (const_wanted) {
-        expr_lor_const();
-        if (tok == '?') {
-            CType boolean;
-            int c;
-            boolean.t = VT_BOOL;
-            vdup();
-            gen_cast(&boolean);
-            c = vtop->c.i;
-            vpop();
-            next();
-            if (tok != ':' || !gnu_ext) {
-                vpop();
-                gexpr();
-            }
-            if (!c)
-                vpop();
-            skip(':');
-            expr_eq();
-            if (c)
-                vpop();
-        }
-    } else {
-        expr_lor();
-        if (tok == '?') {
-            next();
-            if (vtop != vstack) {
-                /* needed to avoid having different registers saved in
-                   each branch */
-                if (is_float(vtop->type.t)) {
-                    rc = RC_FLOAT;
-#ifdef TCC_TARGET_X86_64
-                    if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
-                        rc = RC_ST0;
-                    }
-#endif
-                }
-                else
-                    rc = RC_INT;
-                    gv(rc);
-                    save_regs(1);
-            }
-            if (tok == ':' && gnu_ext) {
-                gv_dup();
-                tt = gtst(1, 0);
-            } else {
-                tt = gtst(1, 0);
-                gexpr();
-            }
-            type1 = vtop->type;
-            sv = *vtop; /* save value to handle it later */
-            vtop--; /* no vpop so that FP stack is not flushed */
-            skip(':');
-            u = gjmp(0);
-            gsym(tt);
-            expr_eq();
-            type2 = vtop->type;
-
-            t1 = type1.t;
-            bt1 = t1 & VT_BTYPE;
-            t2 = type2.t;
-            bt2 = t2 & VT_BTYPE;
-            /* cast operands to correct type according to ISOC rules */
-            if (is_float(bt1) || is_float(bt2)) {
-                if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
-                    type.t = VT_LDOUBLE;
-                } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
-                    type.t = VT_DOUBLE;
-                } else {
-                    type.t = VT_FLOAT;
-                }
-            } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
-                /* cast to biggest op */
-                type.t = VT_LLONG;
-                /* convert to unsigned if it does not fit in a long long */
-                if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
-                    (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
-                    type.t |= VT_UNSIGNED;
-            } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
-                /* XXX: test pointer compatibility */
-                type = type1;
-            } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
-                /* XXX: test function pointer compatibility */
-                type = type1;
-            } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
-                /* XXX: test structure compatibility */
-                type = type1;
-            } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
-                /* NOTE: as an extension, we accept void on only one side */
-                type.t = VT_VOID;
-            } else {
-                /* integer operations */
-                type.t = VT_INT;
-                /* convert to unsigned if it does not fit in an integer */
-                if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
-                    (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
-                    type.t |= VT_UNSIGNED;
-            }
-                
-            /* now we convert second operand */
-            gen_cast(&type);
-            if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
-                gaddrof();
-            rc = RC_INT;
-            if (is_float(type.t)) {
-                rc = RC_FLOAT;
-#ifdef TCC_TARGET_X86_64
-                if ((type.t & VT_BTYPE) == VT_LDOUBLE) {
-                    rc = RC_ST0;
-                }
-#endif
-            } else if ((type.t & VT_BTYPE) == VT_LLONG) {
-                /* for long longs, we use fixed registers to avoid having
-                   to handle a complicated move */
-                rc = RC_IRET; 
-            }
-            
-            r2 = gv(rc);
-            /* this is horrible, but we must also convert first
-               operand */
-            tt = gjmp(0);
-            gsym(u);
-            /* put again first value and cast it */
-            *vtop = sv;
-            gen_cast(&type);
-            if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
-                gaddrof();
-            r1 = gv(rc);
-            move_reg(r2, r1);
-            vtop->r = r2;
-            gsym(tt);
-        }
-    }
-}
-
-static void gexpr(void)
-{
-    while (1) {
-        expr_eq();
-        if (tok != ',')
-            break;
-        vpop();
-        next();
-    }
-}
-
-/* parse an expression and return its type without any side effect. */
-static void expr_type(CType *type)
-{
-    int saved_nocode_wanted;
-
-    saved_nocode_wanted = nocode_wanted;
-    nocode_wanted = 1;
-    gexpr();
-    *type = vtop->type;
-    vpop();
-    nocode_wanted = saved_nocode_wanted;
-}
-
-/* parse a unary expression and return its type without any side
-   effect. */
-static void unary_type(CType *type)
-{
-    int a;
-
-    a = nocode_wanted;
-    nocode_wanted = 1;
-    unary();
-    *type = vtop->type;
-    vpop();
-    nocode_wanted = a;
-}
-
-/* parse a constant expression and return value in vtop.  */
-static void expr_const1(void)
-{
-    int a;
-    a = const_wanted;
-    const_wanted = 1;
-    expr_eq();
-    const_wanted = a;
-}
-
-/* parse an integer constant and return its value. */
-static int expr_const(void)
-{
-    int c;
-    expr_const1();
-    if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
-        expect("constant expression");
-    c = vtop->c.i;
-    vpop();
-    return c;
-}
-
-/* return the label token if current token is a label, otherwise
-   return zero */
-static int is_label(void)
-{
-    int last_tok;
-
-    /* fast test first */
-    if (tok < TOK_UIDENT)
-        return 0;
-    /* no need to save tokc because tok is an identifier */
-    last_tok = tok;
-    next();
-    if (tok == ':') {
-        next();
-        return last_tok;
-    } else {
-        unget_tok(last_tok);
-        return 0;
-    }
-}
-
-static void block(int *bsym, int *csym, int *case_sym, int *def_sym, 
-                  int case_reg, int is_expr)
-{
-    int a, b, c, d;
-    Sym *s;
-
-    /* generate line number info */
-    if (tcc_state->do_debug &&
-        (last_line_num != file->line_num || last_ind != ind)) {
-        put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
-        last_ind = ind;
-        last_line_num = file->line_num;
-    }
-
-    if (is_expr) {
-        /* default return value is (void) */
-        vpushi(0);
-        vtop->type.t = VT_VOID;
-    }
-
-    if (tok == TOK_IF) {
-        /* if test */
-        next();
-        skip('(');
-        gexpr();
-        skip(')');
-        a = gtst(1, 0);
-        block(bsym, csym, case_sym, def_sym, case_reg, 0);
-        c = tok;
-        if (c == TOK_ELSE) {
-            next();
-            d = gjmp(0);
-            gsym(a);
-            block(bsym, csym, case_sym, def_sym, case_reg, 0);
-            gsym(d); /* patch else jmp */
-        } else
-            gsym(a);
-    } else if (tok == TOK_WHILE) {
-        next();
-        d = ind;
-        skip('(');
-        gexpr();
-        skip(')');
-        a = gtst(1, 0);
-        b = 0;
-        block(&a, &b, case_sym, def_sym, case_reg, 0);
-        gjmp_addr(d);
-        gsym(a);
-        gsym_addr(b, d);
-    } else if (tok == '{') {
-        Sym *llabel;
-        
-        next();
-        /* record local declaration stack position */
-        s = local_stack;
-        llabel = local_label_stack;
-        /* handle local labels declarations */
-        if (tok == TOK_LABEL) {
-            next();
-            for(;;) {
-                if (tok < TOK_UIDENT)
-                    expect("label identifier");
-                label_push(&local_label_stack, tok, LABEL_DECLARED);
-                next();
-                if (tok == ',') {
-                    next();
-                } else {
-                    skip(';');
-                    break;
-                }
-            }
-        }
-        while (tok != '}') {
-            decl(VT_LOCAL);
-            if (tok != '}') {
-                if (is_expr)
-                    vpop();
-                block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
-            }
-        }
-        /* pop locally defined labels */
-        label_pop(&local_label_stack, llabel);
-        /* pop locally defined symbols */
-        if(is_expr) {
-            /* XXX: this solution makes only valgrind happy...
-               triggered by gcc.c-torture/execute/20000917-1.c */
-            Sym *p;
-            switch(vtop->type.t & VT_BTYPE) {
-            case VT_PTR:
-            case VT_STRUCT:
-            case VT_ENUM:
-            case VT_FUNC:
-                for(p=vtop->type.ref;p;p=p->prev)
-                    if(p->prev==s)
-                        error("unsupported expression type");
-            }
-        }
-        sym_pop(&local_stack, s);
-        next();
-    } else if (tok == TOK_RETURN) {
-        next();
-        if (tok != ';') {
-            gexpr();
-            gen_assign_cast(&func_vt);
-            if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
-                CType type;
-                /* if returning structure, must copy it to implicit
-                   first pointer arg location */
-#ifdef TCC_ARM_EABI
-                int align, size;
-                size = type_size(&func_vt,&align);
-                if(size <= 4)
-                {
-                    if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
-                       && (align & 3))
-                    {
-                        int addr;
-                        loc = (loc - size) & -4;
-                        addr = loc;
-                        type = func_vt;
-                        vset(&type, VT_LOCAL | VT_LVAL, addr);
-                        vswap();
-                        vstore();
-                        vset(&int_type, VT_LOCAL | VT_LVAL, addr);
-                    }
-                    vtop->type = int_type;
-                    gv(RC_IRET);
-                } else {
-#endif
-                type = func_vt;
-                mk_pointer(&type);
-                vset(&type, VT_LOCAL | VT_LVAL, func_vc);
-                indir();
-                vswap();
-                /* copy structure value to pointer */
-                vstore();
-#ifdef TCC_ARM_EABI
-                }
-#endif
-            } else if (is_float(func_vt.t)) {
-                gv(rc_fret(func_vt.t));
-            } else {
-                gv(RC_IRET);
-            }
-            vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
-        }
-        skip(';');
-        rsym = gjmp(rsym); /* jmp */
-    } else if (tok == TOK_BREAK) {
-        /* compute jump */
-        if (!bsym)
-            error("cannot break");
-        *bsym = gjmp(*bsym);
-        next();
-        skip(';');
-    } else if (tok == TOK_CONTINUE) {
-        /* compute jump */
-        if (!csym)
-            error("cannot continue");
-        *csym = gjmp(*csym);
-        next();
-        skip(';');
-    } else if (tok == TOK_FOR) {
-        int e;
-        next();
-        skip('(');
-        if (tok != ';') {
-            gexpr();
-            vpop();
-        }
-        skip(';');
-        d = ind;
-        c = ind;
-        a = 0;
-        b = 0;
-        if (tok != ';') {
-            gexpr();
-            a = gtst(1, 0);
-        }
-        skip(';');
-        if (tok != ')') {
-            e = gjmp(0);
-            c = ind;
-            gexpr();
-            vpop();
-            gjmp_addr(d);
-            gsym(e);
-        }
-        skip(')');
-        block(&a, &b, case_sym, def_sym, case_reg, 0);
-        gjmp_addr(c);
-        gsym(a);
-        gsym_addr(b, c);
-    } else 
-    if (tok == TOK_DO) {
-        next();
-        a = 0;
-        b = 0;
-        d = ind;
-        block(&a, &b, case_sym, def_sym, case_reg, 0);
-        skip(TOK_WHILE);
-        skip('(');
-        gsym(b);
-        gexpr();
-        c = gtst(0, 0);
-        gsym_addr(c, d);
-        skip(')');
-        gsym(a);
-        skip(';');
-    } else
-    if (tok == TOK_SWITCH) {
-        next();
-        skip('(');
-        gexpr();
-        /* XXX: other types than integer */
-        case_reg = gv(RC_INT);
-        vpop();
-        skip(')');
-        a = 0;
-        b = gjmp(0); /* jump to first case */
-        c = 0;
-        block(&a, csym, &b, &c, case_reg, 0);
-        /* if no default, jmp after switch */
-        if (c == 0)
-            c = ind;
-        /* default label */
-        gsym_addr(b, c);
-        /* break label */
-        gsym(a);
-    } else
-    if (tok == TOK_CASE) {
-        int v1, v2;
-        if (!case_sym)
-            expect("switch");
-        next();
-        v1 = expr_const();
-        v2 = v1;
-        if (gnu_ext && tok == TOK_DOTS) {
-            next();
-            v2 = expr_const();
-            if (v2 < v1)
-                warning("empty case range");
-        }
-        /* since a case is like a label, we must skip it with a jmp */
-        b = gjmp(0);
-        gsym(*case_sym);
-        vseti(case_reg, 0);
-        vpushi(v1);
-        if (v1 == v2) {
-            gen_op(TOK_EQ);
-            *case_sym = gtst(1, 0);
-        } else {
-            gen_op(TOK_GE);
-            *case_sym = gtst(1, 0);
-            vseti(case_reg, 0);
-            vpushi(v2);
-            gen_op(TOK_LE);
-            *case_sym = gtst(1, *case_sym);
-        }
-        gsym(b);
-        skip(':');
-        is_expr = 0;
-        goto block_after_label;
-    } else 
-    if (tok == TOK_DEFAULT) {
-        next();
-        skip(':');
-        if (!def_sym)
-            expect("switch");
-        if (*def_sym)
-            error("too many 'default'");
-        *def_sym = ind;
-        is_expr = 0;
-        goto block_after_label;
-    } else
-    if (tok == TOK_GOTO) {
-        next();
-        if (tok == '*' && gnu_ext) {
-            /* computed goto */
-            next();
-            gexpr();
-            if ((vtop->type.t & VT_BTYPE) != VT_PTR)
-                expect("pointer");
-            ggoto();
-        } else if (tok >= TOK_UIDENT) {
-            s = label_find(tok);
-            /* put forward definition if needed */
-            if (!s) {
-                s = label_push(&global_label_stack, tok, LABEL_FORWARD);
-            } else {
-                if (s->r == LABEL_DECLARED)
-                    s->r = LABEL_FORWARD;
-            }
-            /* label already defined */
-            if (s->r & LABEL_FORWARD) 
-                s->next = (void *)gjmp((long)s->next);
-            else
-                gjmp_addr((long)s->next);
-            next();
-        } else {
-            expect("label identifier");
-        }
-        skip(';');
-    } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
-        asm_instr();
-    } else {
-        b = is_label();
-        if (b) {
-            /* label case */
-            s = label_find(b);
-            if (s) {
-                if (s->r == LABEL_DEFINED)
-                    error("duplicate label '%s'", get_tok_str(s->v, NULL));
-                gsym((long)s->next);
-                s->r = LABEL_DEFINED;
-            } else {
-                s = label_push(&global_label_stack, b, LABEL_DEFINED);
-            }
-            s->next = (void *)ind;
-            /* we accept this, but it is a mistake */
-        block_after_label:
-            if (tok == '}') {
-                warning("deprecated use of label at end of compound statement");
-            } else {
-                if (is_expr)
-                    vpop();
-                block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
-            }
-        } else {
-            /* expression case */
-            if (tok != ';') {
-                if (is_expr) {
-                    vpop();
-                    gexpr();
-                } else {
-                    gexpr();
-                    vpop();
-                }
-            }
-            skip(';');
-        }
-    }
-}
-
-/* t is the array or struct type. c is the array or struct
-   address. cur_index/cur_field is the pointer to the current
-   value. 'size_only' is true if only size info is needed (only used
-   in arrays) */
-static void decl_designator(CType *type, Section *sec, unsigned long c, 
-                            int *cur_index, Sym **cur_field, 
-                            int size_only)
-{
-    Sym *s, *f;
-    int notfirst, index, index_last, align, l, nb_elems, elem_size;
-    CType type1;
-
-    notfirst = 0;
-    elem_size = 0;
-    nb_elems = 1;
-    if (gnu_ext && (l = is_label()) != 0)
-        goto struct_field;
-    while (tok == '[' || tok == '.') {
-        if (tok == '[') {
-            if (!(type->t & VT_ARRAY))
-                expect("array type");
-            s = type->ref;
-            next();
-            index = expr_const();
-            if (index < 0 || (s->c >= 0 && index >= s->c))
-                expect("invalid index");
-            if (tok == TOK_DOTS && gnu_ext) {
-                next();
-                index_last = expr_const();
-                if (index_last < 0 || 
-                    (s->c >= 0 && index_last >= s->c) ||
-                    index_last < index)
-                    expect("invalid index");
-            } else {
-                index_last = index;
-            }
-            skip(']');
-            if (!notfirst)
-                *cur_index = index_last;
-            type = pointed_type(type);
-            elem_size = type_size(type, &align);
-            c += index * elem_size;
-            /* NOTE: we only support ranges for last designator */
-            nb_elems = index_last - index + 1;
-            if (nb_elems != 1) {
-                notfirst = 1;
-                break;
-            }
-        } else {
-            next();
-            l = tok;
-            next();
-        struct_field:
-            if ((type->t & VT_BTYPE) != VT_STRUCT)
-                expect("struct/union type");
-            s = type->ref;
-            l |= SYM_FIELD;
-            f = s->next;
-            while (f) {
-                if (f->v == l)
-                    break;
-                f = f->next;
-            }
-            if (!f)
-                expect("field");
-            if (!notfirst)
-                *cur_field = f;
-            /* XXX: fix this mess by using explicit storage field */
-            type1 = f->type;
-            type1.t |= (type->t & ~VT_TYPE);
-            type = &type1;
-            c += f->c;
-        }
-        notfirst = 1;
-    }
-    if (notfirst) {
-        if (tok == '=') {
-            next();
-        } else {
-            if (!gnu_ext)
-                expect("=");
-        }
-    } else {
-        if (type->t & VT_ARRAY) {
-            index = *cur_index;
-            type = pointed_type(type);
-            c += index * type_size(type, &align);
-        } else {
-            f = *cur_field;
-            if (!f)
-                error("too many field init");
-            /* XXX: fix this mess by using explicit storage field */
-            type1 = f->type;
-            type1.t |= (type->t & ~VT_TYPE);
-            type = &type1;
-            c += f->c;
-        }
-    }
-    decl_initializer(type, sec, c, 0, size_only);
-
-    /* XXX: make it more general */
-    if (!size_only && nb_elems > 1) {
-        unsigned long c_end;
-        uint8_t *src, *dst;
-        int i;
-
-        if (!sec)
-            error("range init not supported yet for dynamic storage");
-        c_end = c + nb_elems * elem_size;
-        if (c_end > sec->data_allocated)
-            section_realloc(sec, c_end);
-        src = sec->data + c;
-        dst = src;
-        for(i = 1; i < nb_elems; i++) {
-            dst += elem_size;
-            memcpy(dst, src, elem_size);
-        }
-    }
-}
-
-#define EXPR_VAL   0
-#define EXPR_CONST 1
-#define EXPR_ANY   2
-
-/* store a value or an expression directly in global data or in local array */
-static void init_putv(CType *type, Section *sec, unsigned long c, 
-                      int v, int expr_type)
-{
-    int saved_global_expr, bt, bit_pos, bit_size;
-    void *ptr;
-    unsigned long long bit_mask;
-    CType dtype;
-
-    switch(expr_type) {
-    case EXPR_VAL:
-        vpushi(v);
-        break;
-    case EXPR_CONST:
-        /* compound literals must be allocated globally in this case */
-        saved_global_expr = global_expr;
-        global_expr = 1;
-        expr_const1();
-        global_expr = saved_global_expr;
-        /* NOTE: symbols are accepted */
-        if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
-            error("initializer element is not constant");
-        break;
-    case EXPR_ANY:
-        expr_eq();
-        break;
-    }
-    
-    dtype = *type;
-    dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
-
-    if (sec) {
-        /* XXX: not portable */
-        /* XXX: generate error if incorrect relocation */
-        gen_assign_cast(&dtype);
-        bt = type->t & VT_BTYPE;
-        /* we'll write at most 12 bytes */
-        if (c + 12 > sec->data_allocated) {
-            section_realloc(sec, c + 12);
-        }
-        ptr = sec->data + c;
-        /* XXX: make code faster ? */
-        if (!(type->t & VT_BITFIELD)) {
-            bit_pos = 0;
-            bit_size = 32;
-            bit_mask = -1LL;
-        } else {
-            bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
-            bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
-            bit_mask = (1LL << bit_size) - 1;
-        }
-        if ((vtop->r & VT_SYM) &&
-            (bt == VT_BYTE ||
-             bt == VT_SHORT ||
-             bt == VT_DOUBLE ||
-             bt == VT_LDOUBLE ||
-             bt == VT_LLONG ||
-             (bt == VT_INT && bit_size != 32)))
-            error("initializer element is not computable at load time");
-        switch(bt) {
-        case VT_BOOL:
-            vtop->c.i = (vtop->c.i != 0);
-        case VT_BYTE:
-            *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
-            break;
-        case VT_SHORT:
-            *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
-            break;
-        case VT_DOUBLE:
-            *(double *)ptr = vtop->c.d;
-            break;
-        case VT_LDOUBLE:
-            *(long double *)ptr = vtop->c.ld;
-            break;
-        case VT_LLONG:
-            *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
-            break;
-        default:
-            if (vtop->r & VT_SYM) {
-                greloc(sec, vtop->sym, c, R_DATA_32);
-            }
-            *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
-            break;
-        }
-        vtop--;
-    } else {
-        vset(&dtype, VT_LOCAL|VT_LVAL, c);
-        vswap();
-        vstore();
-        vpop();
-    }
-}
-
-/* put zeros for variable based init */
-static void init_putz(CType *t, Section *sec, unsigned long c, int size)
-{
-    if (sec) {
-        /* nothing to do because globals are already set to zero */
-    } else {
-        vpush_global_sym(&func_old_type, TOK_memset);
-        vseti(VT_LOCAL, c);
-        vpushi(0);
-        vpushi(size);
-        gfunc_call(3);
-    }
-}
-
-/* 't' contains the type and storage info. 'c' is the offset of the
-   object in section 'sec'. If 'sec' is NULL, it means stack based
-   allocation. 'first' is true if array '{' must be read (multi
-   dimension implicit array init handling). 'size_only' is true if
-   size only evaluation is wanted (only for arrays). */
-static void decl_initializer(CType *type, Section *sec, unsigned long c, 
-                             int first, int size_only)
-{
-    int index, array_length, n, no_oblock, nb, parlevel, i;
-    int size1, align1, expr_type;
-    Sym *s, *f;
-    CType *t1;
-
-    if (type->t & VT_ARRAY) {
-        s = type->ref;
-        n = s->c;
-        array_length = 0;
-        t1 = pointed_type(type);
-        size1 = type_size(t1, &align1);
-
-        no_oblock = 1;
-        if ((first && tok != TOK_LSTR && tok != TOK_STR) || 
-            tok == '{') {
-            skip('{');
-            no_oblock = 0;
-        }
-
-        /* only parse strings here if correct type (otherwise: handle
-           them as ((w)char *) expressions */
-        if ((tok == TOK_LSTR && 
-#ifdef TCC_TARGET_PE
-             (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
-#else
-             (t1->t & VT_BTYPE) == VT_INT
-#endif
-            ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
-            while (tok == TOK_STR || tok == TOK_LSTR) {
-                int cstr_len, ch;
-                CString *cstr;
-
-                cstr = tokc.cstr;
-                /* compute maximum number of chars wanted */
-                if (tok == TOK_STR)
-                    cstr_len = cstr->size;
-                else
-                    cstr_len = cstr->size / sizeof(nwchar_t);
-                cstr_len--;
-                nb = cstr_len;
-                if (n >= 0 && nb > (n - array_length))
-                    nb = n - array_length;
-                if (!size_only) {
-                    if (cstr_len > nb)
-                        warning("initializer-string for array is too long");
-                    /* in order to go faster for common case (char
-                       string in global variable, we handle it
-                       specifically */
-                    if (sec && tok == TOK_STR && size1 == 1) {
-                        memcpy(sec->data + c + array_length, cstr->data, nb);
-                    } else {
-                        for(i=0;i<nb;i++) {
-                            if (tok == TOK_STR)
-                                ch = ((unsigned char *)cstr->data)[i];
-                            else
-                                ch = ((nwchar_t *)cstr->data)[i];
-                            init_putv(t1, sec, c + (array_length + i) * size1,
-                                      ch, EXPR_VAL);
-                        }
-                    }
-                }
-                array_length += nb;
-                next();
-            }
-            /* only add trailing zero if enough storage (no
-               warning in this case since it is standard) */
-            if (n < 0 || array_length < n) {
-                if (!size_only) {
-                    init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
-                }
-                array_length++;
-            }
-        } else {
-            index = 0;
-            while (tok != '}') {
-                decl_designator(type, sec, c, &index, NULL, size_only);
-                if (n >= 0 && index >= n)
-                    error("index too large");
-                /* must put zero in holes (note that doing it that way
-                   ensures that it even works with designators) */
-                if (!size_only && array_length < index) {
-                    init_putz(t1, sec, c + array_length * size1, 
-                              (index - array_length) * size1);
-                }
-                index++;
-                if (index > array_length)
-                    array_length = index;
-                /* special test for multi dimensional arrays (may not
-                   be strictly correct if designators are used at the
-                   same time) */
-                if (index >= n && no_oblock)
-                    break;
-                if (tok == '}')
-                    break;
-                skip(',');
-            }
-        }
-        if (!no_oblock)
-            skip('}');
-        /* put zeros at the end */
-        if (!size_only && n >= 0 && array_length < n) {
-            init_putz(t1, sec, c + array_length * size1, 
-                      (n - array_length) * size1);
-        }
-        /* patch type size if needed */
-        if (n < 0)
-            s->c = array_length;
-    } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
-               (sec || !first || tok == '{')) {
-        int par_count;
-
-        /* NOTE: the previous test is a specific case for automatic
-           struct/union init */
-        /* XXX: union needs only one init */
-
-        /* XXX: this test is incorrect for local initializers
-           beginning with ( without {. It would be much more difficult
-           to do it correctly (ideally, the expression parser should
-           be used in all cases) */
-        par_count = 0;
-        if (tok == '(') {
-            AttributeDef ad1;
-            CType type1;
-            next();
-            while (tok == '(') {
-                par_count++;
-                next();
-            }
-            if (!parse_btype(&type1, &ad1))
-                expect("cast");
-            type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
-#if 0
-            if (!is_assignable_types(type, &type1))
-                error("invalid type for cast");
-#endif
-            skip(')');
-        }
-        no_oblock = 1;
-        if (first || tok == '{') {
-            skip('{');
-            no_oblock = 0;
-        }
-        s = type->ref;
-        f = s->next;
-        array_length = 0;
-        index = 0;
-        n = s->c;
-        while (tok != '}') {
-            decl_designator(type, sec, c, NULL, &f, size_only);
-            index = f->c;
-            if (!size_only && array_length < index) {
-                init_putz(type, sec, c + array_length, 
-                          index - array_length);
-            }
-            index = index + type_size(&f->type, &align1);
-            if (index > array_length)
-                array_length = index;
-            f = f->next;
-            if (no_oblock && f == NULL)
-                break;
-            if (tok == '}')
-                break;
-            skip(',');
-        }
-        /* put zeros at the end */
-        if (!size_only && array_length < n) {
-            init_putz(type, sec, c + array_length, 
-                      n - array_length);
-        }
-        if (!no_oblock)
-            skip('}');
-        while (par_count) {
-            skip(')');
-            par_count--;
-        }
-    } else if (tok == '{') {
-        next();
-        decl_initializer(type, sec, c, first, size_only);
-        skip('}');
-    } else if (size_only) {
-        /* just skip expression */
-        parlevel = 0;
-        while ((parlevel > 0 || (tok != '}' && tok != ',')) && 
-               tok != -1) {
-            if (tok == '(')
-                parlevel++;
-            else if (tok == ')')
-                parlevel--;
-            next();
-        }
-    } else {
-        /* currently, we always use constant expression for globals
-           (may change for scripting case) */
-        expr_type = EXPR_CONST;
-        if (!sec)
-            expr_type = EXPR_ANY;
-        init_putv(type, sec, c, 0, expr_type);
-    }
-}
-
-/* parse an initializer for type 't' if 'has_init' is non zero, and
-   allocate space in local or global data space ('r' is either
-   VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
-   variable 'v' of scope 'scope' is declared before initializers are
-   parsed. If 'v' is zero, then a reference to the new object is put
-   in the value stack. If 'has_init' is 2, a special parsing is done
-   to handle string constants. */
-static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, 
-                                   int has_init, int v, int scope)
-{
-    int size, align, addr, data_offset;
-    int level;
-    ParseState saved_parse_state = {0};
-    TokenString init_str;
-    Section *sec;
-
-    size = type_size(type, &align);
-    /* If unknown size, we must evaluate it before
-       evaluating initializers because
-       initializers can generate global data too
-       (e.g. string pointers or ISOC99 compound
-       literals). It also simplifies local
-       initializers handling */
-    tok_str_new(&init_str);
-    if (size < 0) {
-        if (!has_init) 
-            error("unknown type size");
-        /* get all init string */
-        if (has_init == 2) {
-            /* only get strings */
-            while (tok == TOK_STR || tok == TOK_LSTR) {
-                tok_str_add_tok(&init_str);
-                next();
-            }
-        } else {
-            level = 0;
-            while (level > 0 || (tok != ',' && tok != ';')) {
-                if (tok < 0)
-                    error("unexpected end of file in initializer");
-                tok_str_add_tok(&init_str);
-                if (tok == '{')
-                    level++;
-                else if (tok == '}') {
-                    level--;
-                    if (level <= 0) {
-                        next();
-                        break;
-                    }
-                }
-                next();
-            }
-        }
-        tok_str_add(&init_str, -1);
-        tok_str_add(&init_str, 0);
-        
-        /* compute size */
-        save_parse_state(&saved_parse_state);
-
-        macro_ptr = init_str.str;
-        next();
-        decl_initializer(type, NULL, 0, 1, 1);
-        /* prepare second initializer parsing */
-        macro_ptr = init_str.str;
-        next();
-        
-        /* if still unknown size, error */
-        size = type_size(type, &align);
-        if (size < 0) 
-            error("unknown type size");
-    }
-    /* take into account specified alignment if bigger */
-    if (ad->aligned) {
-        if (ad->aligned > align)
-            align = ad->aligned;
-    } else if (ad->packed) {
-        align = 1;
-    }
-    if ((r & VT_VALMASK) == VT_LOCAL) {
-        sec = NULL;
-        if (tcc_state->do_bounds_check && (type->t & VT_ARRAY))
-            loc--;
-        loc = (loc - size) & -align;
-        addr = loc;
-        /* handles bounds */
-        /* XXX: currently, since we do only one pass, we cannot track
-           '&' operators, so we add only arrays */
-        if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) {
-            unsigned long *bounds_ptr;
-            /* add padding between regions */
-            loc--;
-            /* then add local bound info */
-            bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
-            bounds_ptr[0] = addr;
-            bounds_ptr[1] = size;
-        }
-        if (v) {
-            /* local variable */
-            sym_push(v, type, r, addr);
-        } else {
-            /* push local reference */
-            vset(type, r, addr);
-        }
-    } else {
-        Sym *sym;
-
-        sym = NULL;
-        if (v && scope == VT_CONST) {
-            /* see if the symbol was already defined */
-            sym = sym_find(v);
-            if (sym) {
-                if (!is_compatible_types(&sym->type, type))
-                    error("incompatible types for redefinition of '%s'", 
-                          get_tok_str(v, NULL));
-                if (sym->type.t & VT_EXTERN) {
-                    /* if the variable is extern, it was not allocated */
-                    sym->type.t &= ~VT_EXTERN;
-                    /* set array size if it was ommited in extern
-                       declaration */
-                    if ((sym->type.t & VT_ARRAY) && 
-                        sym->type.ref->c < 0 &&
-                        type->ref->c >= 0)
-                        sym->type.ref->c = type->ref->c;
-                } else {
-                    /* we accept several definitions of the same
-                       global variable. this is tricky, because we
-                       must play with the SHN_COMMON type of the symbol */
-                    /* XXX: should check if the variable was already
-                       initialized. It is incorrect to initialized it
-                       twice */
-                    /* no init data, we won't add more to the symbol */
-                    if (!has_init)
-                        goto no_alloc;
-                }
-            }
-        }
-
-        /* allocate symbol in corresponding section */
-        sec = ad->section;
-        if (!sec) {
-            if (has_init)
-                sec = data_section;
-            else if (tcc_state->nocommon)
-                sec = bss_section;
-        }
-        if (sec) {
-            data_offset = sec->data_offset;
-            data_offset = (data_offset + align - 1) & -align;
-            addr = data_offset;
-            /* very important to increment global pointer at this time
-               because initializers themselves can create new initializers */
-            data_offset += size;
-            /* add padding if bound check */
-            if (tcc_state->do_bounds_check)
-                data_offset++;
-            sec->data_offset = data_offset;
-            /* allocate section space to put the data */
-            if (sec->sh_type != SHT_NOBITS && 
-                data_offset > sec->data_allocated)
-                section_realloc(sec, data_offset);
-            /* align section if needed */
-            if (align > sec->sh_addralign)
-                sec->sh_addralign = align;
-        } else {
-            addr = 0; /* avoid warning */
-        }
-
-        if (v) {
-            if (scope != VT_CONST || !sym) {
-                sym = sym_push(v, type, r | VT_SYM, 0);
-            }
-            /* update symbol definition */
-            if (sec) {
-                put_extern_sym(sym, sec, addr, size);
-            } else {
-                ElfW(Sym) *esym;
-                /* put a common area */
-                put_extern_sym(sym, NULL, align, size);
-                /* XXX: find a nicer way */
-                esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
-                esym->st_shndx = SHN_COMMON;
-            }
-        } else {
-            CValue cval;
-
-            /* push global reference */
-            sym = get_sym_ref(type, sec, addr, size);
-            cval.ul = 0;
-            vsetc(type, VT_CONST | VT_SYM, &cval);
-            vtop->sym = sym;
-        }
-
-        /* handles bounds now because the symbol must be defined
-           before for the relocation */
-        if (tcc_state->do_bounds_check) {
-            unsigned long *bounds_ptr;
-
-            greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
-            /* then add global bound info */
-            bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
-            bounds_ptr[0] = 0; /* relocated */
-            bounds_ptr[1] = size;
-        }
-    }
-    if (has_init) {
-        decl_initializer(type, sec, addr, 1, 0);
-        /* restore parse state if needed */
-        if (init_str.str) {
-            tok_str_free(init_str.str);
-            restore_parse_state(&saved_parse_state);
-        }
-    }
- no_alloc: ;
-}
-
-void put_func_debug(Sym *sym)
-{
-    char buf[512];
-
-    /* stabs info */
-    /* XXX: we put here a dummy type */
-    snprintf(buf, sizeof(buf), "%s:%c1", 
-             funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
-    put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
-                cur_text_section, sym->c);
-    /* //gr gdb wants a line at the function */
-    put_stabn(N_SLINE, 0, file->line_num, 0); 
-    last_ind = 0;
-    last_line_num = 0;
-}
-
-/* parse an old style function declaration list */
-/* XXX: check multiple parameter */
-static void func_decl_list(Sym *func_sym)
-{
-    AttributeDef ad;
-    int v;
-    Sym *s;
-    CType btype, type;
-
-    /* parse each declaration */
-    while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
-        if (!parse_btype(&btype, &ad)) 
-            expect("declaration list");
-        if (((btype.t & VT_BTYPE) == VT_ENUM ||
-             (btype.t & VT_BTYPE) == VT_STRUCT) && 
-            tok == ';') {
-            /* we accept no variable after */
-        } else {
-            for(;;) {
-                type = btype;
-                type_decl(&type, &ad, &v, TYPE_DIRECT);
-                /* find parameter in function parameter list */
-                s = func_sym->next;
-                while (s != NULL) {
-                    if ((s->v & ~SYM_FIELD) == v)
-                        goto found;
-                    s = s->next;
-                }
-                error("declaration for parameter '%s' but no such parameter",
-                      get_tok_str(v, NULL));
-            found:
-                /* check that no storage specifier except 'register' was given */
-                if (type.t & VT_STORAGE)
-                    error("storage class specified for '%s'", get_tok_str(v, NULL)); 
-                convert_parameter_type(&type);
-                /* we can add the type (NOTE: it could be local to the function) */
-                s->type = type;
-                /* accept other parameters */
-                if (tok == ',')
-                    next();
-                else
-                    break;
-            }
-        }
-        skip(';');
-    }
-}
-
-/* parse a function defined by symbol 'sym' and generate its code in
-   'cur_text_section' */
-static void gen_function(Sym *sym)
-{
-    int saved_nocode_wanted = nocode_wanted;
-    nocode_wanted = 0;
-    ind = cur_text_section->data_offset;
-    /* NOTE: we patch the symbol size later */
-    put_extern_sym(sym, cur_text_section, ind, 0);
-    funcname = get_tok_str(sym->v, NULL);
-    func_ind = ind;
-    /* put debug symbol */
-    if (tcc_state->do_debug)
-        put_func_debug(sym);
-    /* push a dummy symbol to enable local sym storage */
-    sym_push2(&local_stack, SYM_FIELD, 0, 0);
-    gfunc_prolog(&sym->type);
-    rsym = 0;
-    block(NULL, NULL, NULL, NULL, 0, 0);
-    gsym(rsym);
-    gfunc_epilog();
-    cur_text_section->data_offset = ind;
-    label_pop(&global_label_stack, NULL);
-    sym_pop(&local_stack, NULL); /* reset local stack */
-    /* end of function */
-    /* patch symbol size */
-    ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size = 
-        ind - func_ind;
-    if (tcc_state->do_debug) {
-        put_stabn(N_FUN, 0, 0, ind - func_ind);
-    }
-    /* It's better to crash than to generate wrong code */
-    cur_text_section = NULL;
-    funcname = ""; /* for safety */
-    func_vt.t = VT_VOID; /* for safety */
-    ind = 0; /* for safety */
-    nocode_wanted = saved_nocode_wanted;
-}
-
-static void gen_inline_functions(void)
-{
-    Sym *sym;
-    CType *type;
-    int *str, inline_generated;
-
-    /* iterate while inline function are referenced */
-    for(;;) {
-        inline_generated = 0;
-        for(sym = global_stack; sym != NULL; sym = sym->prev) {
-            type = &sym->type;
-            if (((type->t & VT_BTYPE) == VT_FUNC) &&
-                (type->t & (VT_STATIC | VT_INLINE)) == 
-                (VT_STATIC | VT_INLINE) &&
-                sym->c != 0) {
-                /* the function was used: generate its code and
-                   convert it to a normal function */
-                str = INLINE_DEF(sym->r);
-                sym->r = VT_SYM | VT_CONST;
-                sym->type.t &= ~VT_INLINE;
-
-                macro_ptr = str;
-                next();
-                cur_text_section = text_section;
-                gen_function(sym);
-                macro_ptr = NULL; /* fail safe */
-
-                tok_str_free(str);
-                inline_generated = 1;
-            }
-        }
-        if (!inline_generated)
-            break;
-    }
-
-    /* free all remaining inline function tokens */
-    for(sym = global_stack; sym != NULL; sym = sym->prev) {
-        type = &sym->type;
-        if (((type->t & VT_BTYPE) == VT_FUNC) &&
-            (type->t & (VT_STATIC | VT_INLINE)) == 
-            (VT_STATIC | VT_INLINE)) {
-            //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
-            if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
-                continue;
-            str = INLINE_DEF(sym->r);
-            tok_str_free(str);
-            sym->r = 0; /* fail safe */
-        }
-    }
-}
-
-/* 'l' is VT_LOCAL or VT_CONST to define default storage type */
-static void decl(int l)
-{
-    int v, has_init, r;
-    CType type, btype;
-    Sym *sym;
-    AttributeDef ad;
-    
-    while (1) {
-        if (!parse_btype(&btype, &ad)) {
-            /* skip redundant ';' */
-            /* XXX: find more elegant solution */
-            if (tok == ';') {
-                next();
-                continue;
-            }
-            if (l == VT_CONST &&
-                (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
-                /* global asm block */
-                asm_global_instr();
-                continue;
-            }
-            /* special test for old K&R protos without explicit int
-               type. Only accepted when defining global data */
-            if (l == VT_LOCAL || tok < TOK_DEFINE)
-                break;
-            btype.t = VT_INT;
-        }
-        if (((btype.t & VT_BTYPE) == VT_ENUM ||
-             (btype.t & VT_BTYPE) == VT_STRUCT) && 
-            tok == ';') {
-            /* we accept no variable after */
-            next();
-            continue;
-        }
-        while (1) { /* iterate thru each declaration */
-            type = btype;
-            type_decl(&type, &ad, &v, TYPE_DIRECT);
-#if 0
-            {
-                char buf[500];
-                type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
-                printf("type = '%s'\n", buf);
-            }
-#endif
-            if ((type.t & VT_BTYPE) == VT_FUNC) {
-                /* if old style function prototype, we accept a
-                   declaration list */
-                sym = type.ref;
-                if (sym->c == FUNC_OLD)
-                    func_decl_list(sym);
-            }
-
-            if (tok == '{') {
-                if (l == VT_LOCAL)
-                    error("cannot use local functions");
-                if ((type.t & VT_BTYPE) != VT_FUNC)
-                    expect("function definition");
-
-                /* reject abstract declarators in function definition */
-                sym = type.ref;
-                while ((sym = sym->next) != NULL)
-                    if (!(sym->v & ~SYM_FIELD))
-                       expect("identifier");
-                
-                /* XXX: cannot do better now: convert extern line to static inline */
-                if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
-                    type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
-                
-                sym = sym_find(v);
-                if (sym) {
-                    if ((sym->type.t & VT_BTYPE) != VT_FUNC)
-                        goto func_error1;
-                    /* specific case: if not func_call defined, we put
-                       the one of the prototype */
-                    /* XXX: should have default value */
-                    r = sym->type.ref->r;
-                    if (FUNC_CALL(r) != FUNC_CDECL
-                     && FUNC_CALL(type.ref->r) == FUNC_CDECL)
-                        FUNC_CALL(type.ref->r) = FUNC_CALL(r);
-                    if (FUNC_EXPORT(r))
-                        FUNC_EXPORT(type.ref->r) = 1;
-
-                    if (!is_compatible_types(&sym->type, &type)) {
-                    func_error1:
-                        error("incompatible types for redefinition of '%s'", 
-                              get_tok_str(v, NULL));
-                    }
-                    /* if symbol is already defined, then put complete type */
-                    sym->type = type;
-                } else {
-                    /* put function symbol */
-                    sym = global_identifier_push(v, type.t, 0);
-                    sym->type.ref = type.ref;
-                }
-
-                /* static inline functions are just recorded as a kind
-                   of macro. Their code will be emitted at the end of
-                   the compilation unit only if they are used */
-                if ((type.t & (VT_INLINE | VT_STATIC)) == 
-                    (VT_INLINE | VT_STATIC)) {
-                    TokenString func_str;
-                    int block_level;
-                           
-                    tok_str_new(&func_str);
-                    
-                    block_level = 0;
-                    for(;;) {
-                        int t;
-                        if (tok == TOK_EOF)
-                            error("unexpected end of file");
-                        tok_str_add_tok(&func_str);
-                        t = tok;
-                        next();
-                        if (t == '{') {
-                            block_level++;
-                        } else if (t == '}') {
-                            block_level--;
-                            if (block_level == 0)
-                                break;
-                        }
-                    }
-                    tok_str_add(&func_str, -1);
-                    tok_str_add(&func_str, 0);
-                    INLINE_DEF(sym->r) = func_str.str;
-                } else {
-                    /* compute text section */
-                    cur_text_section = ad.section;
-                    if (!cur_text_section)
-                        cur_text_section = text_section;
-                    sym->r = VT_SYM | VT_CONST;
-                    gen_function(sym);
-                }
-                break;
-            } else {
-                if (btype.t & VT_TYPEDEF) {
-                    /* save typedefed type  */
-                    /* XXX: test storage specifiers ? */
-                    sym = sym_push(v, &type, 0, 0);
-                    sym->type.t |= VT_TYPEDEF;
-                } else if ((type.t & VT_BTYPE) == VT_FUNC) {
-                    /* external function definition */
-                    /* specific case for func_call attribute */
-                    if (ad.func_attr)
-                        type.ref->r = ad.func_attr;
-                    external_sym(v, &type, 0);
-                } else {
-                    /* not lvalue if array */
-                    r = 0;
-                    if (!(type.t & VT_ARRAY))
-                        r |= lvalue_type(type.t);
-                    has_init = (tok == '=');
-                    if ((btype.t & VT_EXTERN) || 
-                        ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
-                         !has_init && l == VT_CONST && type.ref->c < 0)) {
-                        /* external variable */
-                        /* NOTE: as GCC, uninitialized global static
-                           arrays of null size are considered as
-                           extern */
-                        external_sym(v, &type, r);
-                    } else {
-                        type.t |= (btype.t & VT_STATIC); /* Retain "static". */
-                        if (type.t & VT_STATIC)
-                            r |= VT_CONST;
-                        else
-                            r |= l;
-                        if (has_init)
-                            next();
-                        decl_initializer_alloc(&type, &ad, r, 
-                                               has_init, v, l);
-                    }
-                }
-                if (tok != ',') {
-                    skip(';');
-                    break;
-                }
-                next();
-            }
-        }
-    }
-}
-

+ 0 - 1559
src/modules/native/tcc/libtcc/tccpe.c

@@ -1,1559 +0,0 @@
-/*
- *  TCCPE.C - PE file output for the Tiny C Compiler
- *
- *  Copyright (c) 2005-2007 grischka
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifdef TCC_TARGET_PE
-
-#define ST_FN static
-#define ST_DATA static
-#define PUB_FN
-
-#ifndef _WIN32
-#define stricmp strcasecmp
-#define strnicmp strncasecmp
-#endif
-
-#ifndef MAX_PATH
-#define MAX_PATH 260
-#endif
-
-#define PE_MERGE_DATA
-// #define PE_PRINT_SECTIONS
-
-/* ----------------------------------------------------------- */
-#ifndef IMAGE_NT_SIGNATURE
-/* ----------------------------------------------------------- */
-/* definitions below are from winnt.h */
-
-typedef unsigned char BYTE;
-typedef unsigned short WORD;
-typedef unsigned long DWORD;
-#pragma pack(push, 1)
-
-typedef struct _IMAGE_DOS_HEADER {  /* DOS .EXE header */
-    WORD e_magic;         /* Magic number */
-    WORD e_cblp;          /* Bytes on last page of file */
-    WORD e_cp;            /* Pages in file */
-    WORD e_crlc;          /* Relocations */
-    WORD e_cparhdr;       /* Size of header in paragraphs */
-    WORD e_minalloc;      /* Minimum extra paragraphs needed */
-    WORD e_maxalloc;      /* Maximum extra paragraphs needed */
-    WORD e_ss;            /* Initial (relative) SS value */
-    WORD e_sp;            /* Initial SP value */
-    WORD e_csum;          /* Checksum */
-    WORD e_ip;            /* Initial IP value */
-    WORD e_cs;            /* Initial (relative) CS value */
-    WORD e_lfarlc;        /* File address of relocation table */
-    WORD e_ovno;          /* Overlay number */
-    WORD e_res[4];        /* Reserved words */
-    WORD e_oemid;         /* OEM identifier (for e_oeminfo) */
-    WORD e_oeminfo;       /* OEM information; e_oemid specific */
-    WORD e_res2[10];      /* Reserved words */
-    DWORD e_lfanew;        /* File address of new exe header */
-} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
-
-#define IMAGE_NT_SIGNATURE  0x00004550  /* PE00 */
-#define SIZE_OF_NT_SIGNATURE 4
-
-typedef struct _IMAGE_FILE_HEADER {
-    WORD    Machine;
-    WORD    NumberOfSections;
-    DWORD   TimeDateStamp;
-    DWORD   PointerToSymbolTable;
-    DWORD   NumberOfSymbols;
-    WORD    SizeOfOptionalHeader;
-    WORD    Characteristics;
-} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
-
-
-#define IMAGE_SIZEOF_FILE_HEADER 20
-
-typedef struct _IMAGE_DATA_DIRECTORY {
-    DWORD   VirtualAddress;
-    DWORD   Size;
-} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
-
-
-typedef struct _IMAGE_OPTIONAL_HEADER {
-    /* Standard fields. */
-    WORD    Magic;
-    BYTE    MajorLinkerVersion;
-    BYTE    MinorLinkerVersion;
-    DWORD   SizeOfCode;
-    DWORD   SizeOfInitializedData;
-    DWORD   SizeOfUninitializedData;
-    DWORD   AddressOfEntryPoint;
-    DWORD   BaseOfCode;
-    DWORD   BaseOfData;
-
-    /* NT additional fields. */
-    DWORD   ImageBase;
-    DWORD   SectionAlignment;
-    DWORD   FileAlignment;
-    WORD    MajorOperatingSystemVersion;
-    WORD    MinorOperatingSystemVersion;
-    WORD    MajorImageVersion;
-    WORD    MinorImageVersion;
-    WORD    MajorSubsystemVersion;
-    WORD    MinorSubsystemVersion;
-    DWORD   Win32VersionValue;
-    DWORD   SizeOfImage;
-    DWORD   SizeOfHeaders;
-    DWORD   CheckSum;
-    WORD    Subsystem;
-    WORD    DllCharacteristics;
-    DWORD   SizeOfStackReserve;
-    DWORD   SizeOfStackCommit;
-    DWORD   SizeOfHeapReserve;
-    DWORD   SizeOfHeapCommit;
-    DWORD   LoaderFlags;
-    DWORD   NumberOfRvaAndSizes;
-    IMAGE_DATA_DIRECTORY DataDirectory[16];
-
-} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
-
-
-#define IMAGE_DIRECTORY_ENTRY_EXPORT          0   /* Export Directory */
-#define IMAGE_DIRECTORY_ENTRY_IMPORT          1   /* Import Directory */
-#define IMAGE_DIRECTORY_ENTRY_RESOURCE        2   /* Resource Directory */
-#define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3   /* Exception Directory */
-#define IMAGE_DIRECTORY_ENTRY_SECURITY        4   /* Security Directory */
-#define IMAGE_DIRECTORY_ENTRY_BASERELOC       5   /* Base Relocation Table */
-#define IMAGE_DIRECTORY_ENTRY_DEBUG           6   /* Debug Directory */
-/*      IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7      (X86 usage) */
-#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7   /* Architecture Specific Data */
-#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8   /* RVA of GP */
-#define IMAGE_DIRECTORY_ENTRY_TLS             9   /* TLS Directory */
-#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10   /* Load Configuration Directory */
-#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11   /* Bound Import Directory in headers */
-#define IMAGE_DIRECTORY_ENTRY_IAT            12   /* Import Address Table */
-#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13   /* Delay Load Import Descriptors */
-#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14   /* COM Runtime descriptor */
-
-/* Section header format. */
-#define IMAGE_SIZEOF_SHORT_NAME         8
-
-typedef struct _IMAGE_SECTION_HEADER {
-    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
-    union {
-            DWORD   PhysicalAddress;
-            DWORD   VirtualSize;
-    } Misc;
-    DWORD   VirtualAddress;
-    DWORD   SizeOfRawData;
-    DWORD   PointerToRawData;
-    DWORD   PointerToRelocations;
-    DWORD   PointerToLinenumbers;
-    WORD    NumberOfRelocations;
-    WORD    NumberOfLinenumbers;
-    DWORD   Characteristics;
-} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
-
-#define IMAGE_SIZEOF_SECTION_HEADER     40
-
-typedef struct _IMAGE_BASE_RELOCATION {
-    DWORD   VirtualAddress;
-    DWORD   SizeOfBlock;
-//  WORD    TypeOffset[1];
-} IMAGE_BASE_RELOCATION;
-
-#define IMAGE_SIZEOF_BASE_RELOCATION     8
-
-#define IMAGE_REL_BASED_ABSOLUTE         0
-#define IMAGE_REL_BASED_HIGH             1
-#define IMAGE_REL_BASED_LOW              2
-#define IMAGE_REL_BASED_HIGHLOW          3
-#define IMAGE_REL_BASED_HIGHADJ          4
-#define IMAGE_REL_BASED_MIPS_JMPADDR     5
-#define IMAGE_REL_BASED_SECTION          6
-#define IMAGE_REL_BASED_REL32            7
-
-#pragma pack(pop)
-
-/* ----------------------------------------------------------- */
-#endif /* ndef IMAGE_NT_SIGNATURE */
-/* ----------------------------------------------------------- */
-
-#pragma pack(push, 1)
-
-struct pe_header
-{
-    IMAGE_DOS_HEADER doshdr;
-    BYTE dosstub[0x40];
-    DWORD nt_sig;
-    IMAGE_FILE_HEADER filehdr;
-    IMAGE_OPTIONAL_HEADER opthdr;
-};
-
-struct pe_import_header {
-    DWORD first_entry;
-    DWORD time_date;
-    DWORD forwarder;
-    DWORD lib_name_offset;
-    DWORD first_thunk;
-};
-
-struct pe_export_header {
-    DWORD Characteristics;
-    DWORD TimeDateStamp;
-    DWORD Version;
-    DWORD Name;
-    DWORD Base;
-    DWORD NumberOfFunctions;
-    DWORD NumberOfNames;
-    DWORD AddressOfFunctions;
-    DWORD AddressOfNames;
-    DWORD AddressOfNameOrdinals;
-};
-
-struct pe_reloc_header {
-    DWORD offset;
-    DWORD size;
-};
-
-struct pe_rsrc_header {
-    struct _IMAGE_FILE_HEADER filehdr;
-    struct _IMAGE_SECTION_HEADER sectionhdr;
-};
-
-struct pe_rsrc_reloc {
-    DWORD offset;
-    DWORD size;
-    WORD type;
-};
-
-#pragma pack(pop)
-
-/* ----------------------------------------------------------- */
-ST_DATA struct pe_header pe_header = {
-{
-    /* IMAGE_DOS_HEADER doshdr */
-    0x5A4D, /*WORD e_magic;         Magic number */
-    0x0090, /*WORD e_cblp;          Bytes on last page of file */
-    0x0003, /*WORD e_cp;            Pages in file */
-    0x0000, /*WORD e_crlc;          Relocations */
-
-    0x0004, /*WORD e_cparhdr;       Size of header in paragraphs */
-    0x0000, /*WORD e_minalloc;      Minimum extra paragraphs needed */
-    0xFFFF, /*WORD e_maxalloc;      Maximum extra paragraphs needed */
-    0x0000, /*WORD e_ss;            Initial (relative) SS value */
-
-    0x00B8, /*WORD e_sp;            Initial SP value */
-    0x0000, /*WORD e_csum;          Checksum */
-    0x0000, /*WORD e_ip;            Initial IP value */
-    0x0000, /*WORD e_cs;            Initial (relative) CS value */
-    0x0040, /*WORD e_lfarlc;        File address of relocation table */
-    0x0000, /*WORD e_ovno;          Overlay number */
-    {0,0,0,0}, /*WORD e_res[4];     Reserved words */
-    0x0000, /*WORD e_oemid;         OEM identifier (for e_oeminfo) */
-    0x0000, /*WORD e_oeminfo;       OEM information; e_oemid specific */
-    {0,0,0,0,0,0,0,0,0,0}, /*WORD e_res2[10];      Reserved words */
-    0x00000080  /*DWORD   e_lfanew;        File address of new exe header */
-},{
-    /* BYTE dosstub[0x40] */
-    /* 14 code bytes + "This program cannot be run in DOS mode.\r\r\n$" + 6 * 0x00 */
-    0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
-    0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
-    0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
-    0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-},
-    0x00004550, /* DWORD nt_sig = IMAGE_NT_SIGNATURE */
-{
-    /* IMAGE_FILE_HEADER filehdr */
-    0x014C, /*WORD    Machine; */
-    0x0003, /*WORD    NumberOfSections; */
-    0x00000000, /*DWORD   TimeDateStamp; */
-    0x00000000, /*DWORD   PointerToSymbolTable; */
-    0x00000000, /*DWORD   NumberOfSymbols; */
-    0x00E0, /*WORD    SizeOfOptionalHeader; */
-    0x030F  /*WORD    Characteristics; */
-},{
-    /* IMAGE_OPTIONAL_HEADER opthdr */
-    /* Standard fields. */
-    0x010B, /*WORD    Magic; */
-    0x06, /*BYTE    MajorLinkerVersion; */
-    0x00, /*BYTE    MinorLinkerVersion; */
-    0x00000000, /*DWORD   SizeOfCode; */
-    0x00000000, /*DWORD   SizeOfInitializedData; */
-    0x00000000, /*DWORD   SizeOfUninitializedData; */
-    0x00000000, /*DWORD   AddressOfEntryPoint; */
-    0x00000000, /*DWORD   BaseOfCode; */
-    0x00000000, /*DWORD   BaseOfData; */
-
-    /* NT additional fields. */
-    0x00400000, /*DWORD   ImageBase; */
-    0x00001000, /*DWORD   SectionAlignment; */
-    0x00000200, /*DWORD   FileAlignment; */
-    0x0004, /*WORD    MajorOperatingSystemVersion; */
-    0x0000, /*WORD    MinorOperatingSystemVersion; */
-    0x0000, /*WORD    MajorImageVersion; */
-    0x0000, /*WORD    MinorImageVersion; */
-    0x0004, /*WORD    MajorSubsystemVersion; */
-    0x0000, /*WORD    MinorSubsystemVersion; */
-    0x00000000, /*DWORD   Win32VersionValue; */
-    0x00000000, /*DWORD   SizeOfImage; */
-    0x00000200, /*DWORD   SizeOfHeaders; */
-    0x00000000, /*DWORD   CheckSum; */
-    0x0002, /*WORD    Subsystem; */
-    0x0000, /*WORD    DllCharacteristics; */
-    0x00100000, /*DWORD   SizeOfStackReserve; */
-    0x00001000, /*DWORD   SizeOfStackCommit; */
-    0x00100000, /*DWORD   SizeOfHeapReserve; */
-    0x00001000, /*DWORD   SizeOfHeapCommit; */
-    0x00000000, /*DWORD   LoaderFlags; */
-    0x00000010, /*DWORD   NumberOfRvaAndSizes; */
-
-    /* IMAGE_DATA_DIRECTORY DataDirectory[16]; */
-    {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
-     {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}}
-}};
-
-/* ------------------------------------------------------------- */
-/* internal temporary structures */
-
-/*
-#define IMAGE_SCN_CNT_CODE                  0x00000020
-#define IMAGE_SCN_CNT_INITIALIZED_DATA      0x00000040
-#define IMAGE_SCN_CNT_UNINITIALIZED_DATA    0x00000080
-#define IMAGE_SCN_MEM_DISCARDABLE           0x02000000
-#define IMAGE_SCN_MEM_SHARED                0x10000000
-#define IMAGE_SCN_MEM_EXECUTE               0x20000000
-#define IMAGE_SCN_MEM_READ                  0x40000000
-#define IMAGE_SCN_MEM_WRITE                 0x80000000
-*/
-
-enum {
-    sec_text = 0,
-    sec_data ,
-    sec_bss ,
-    sec_idata ,
-    sec_other ,
-    sec_rsrc ,
-    sec_stab ,
-    sec_reloc ,
-    sec_last
-};
-
-ST_DATA DWORD pe_sec_flags[] = {
-    0x60000020, /* ".text"     , */
-    0xC0000040, /* ".data"     , */
-    0xC0000080, /* ".bss"      , */
-    0x40000040, /* ".idata"    , */
-    0xE0000060, /* < other >   , */
-    0x40000040, /* ".rsrc"     , */
-    0x42000802, /* ".stab"     , */
-    0x42000040, /* ".reloc"    , */
-};
-
-struct section_info {
-    int cls, ord;
-    char name[32];
-    DWORD sh_addr;
-    DWORD sh_size;
-    DWORD sh_flags;
-    unsigned char *data;
-    DWORD data_size;
-    IMAGE_SECTION_HEADER ish;
-};
-
-struct import_symbol {
-    int sym_index;
-    int iat_index;
-    int thk_offset;
-};
-
-struct pe_import_info {
-    int dll_index;
-    int sym_count;
-    struct import_symbol **symbols;
-};
-
-struct pe_info {
-    TCCState *s1;
-    Section *reloc;
-    Section *thunk;
-    const char *filename;
-    int type;
-    DWORD sizeofheaders;
-    DWORD imagebase;
-    DWORD start_addr;
-    DWORD imp_offs;
-    DWORD imp_size;
-    DWORD iat_offs;
-    DWORD iat_size;
-    DWORD exp_offs;
-    DWORD exp_size;
-    struct section_info *sec_info;
-    int sec_count;
-    struct pe_import_info **imp_info;
-    int imp_count;
-};
-
-/* ------------------------------------------------------------- */
-
-#define PE_NUL 0
-#define PE_DLL 1
-#define PE_GUI 2
-#define PE_EXE 3
-
-void error_noabort(const char *, ...);
-
-#ifdef _WIN32
-void dbg_printf (const char *fmt, ...)
-{
-    char buffer[4000];
-    va_list arg;
-    int x;
-    va_start(arg, fmt);
-    x = vsprintf (buffer, fmt, arg);
-    strcpy(buffer+x, "\n");
-    OutputDebugString(buffer);
-}
-#endif
-
-/* --------------------------------------------*/
-
-ST_FN const char* get_alt_symbol(char *buffer, const char *symbol)
-{
-    const char *p;
-    p = strrchr(symbol, '@');
-    if (p && isnum(p[1]) && symbol[0] == '_') { /* stdcall decor */
-        strcpy(buffer, symbol+1)[p-symbol-1] = 0;
-    } else if (symbol[0] != '_') { /* try non-ansi function */
-        buffer[0] = '_', strcpy(buffer + 1, symbol);
-    } else if (0 == memcmp(symbol, "__imp__", 7)) { /* mingw 2.0 */
-        strcpy(buffer, symbol + 6);
-    } else if (0 == memcmp(symbol, "_imp___", 7)) { /* mingw 3.7 */
-        strcpy(buffer, symbol + 6);
-    } else {
-        return symbol;
-    }
-    return buffer;
-}
-
-ST_FN int pe_find_import(TCCState * s1, const char *symbol)
-{
-    char buffer[200];
-    const char *s;
-    int sym_index, n = 0;
-    do {
-        s = n ? get_alt_symbol(buffer, symbol) : symbol;
-        sym_index = find_elf_sym(s1->dynsymtab_section, s);
-        // printf("find %d %s\n", sym_index, s);
-    } while (0 == sym_index && ++n < 2);
-    return sym_index;
-}
-
-#if defined _WIN32 || defined __CYGWIN__
-
-#ifdef __CYGWIN__
-# include <dlfcn.h>
-# define LoadLibrary(s) dlopen(s, RTLD_NOW)
-# define GetProcAddress(h,s) dlsym(h, s)
-#else
-# define dlclose(h) FreeLibrary(h)
-#endif
-
-/* for the -run option: dynamically load symbol from dll */
-void *resolve_sym(struct TCCState *s1, const char *symbol, int type)
-{
-    char buffer[100];
-    int sym_index, dll_index;
-    void *addr, **m;
-    DLLReference *dllref;
-
-    sym_index = pe_find_import(s1, symbol);
-    if (0 == sym_index)
-        return NULL;
-    dll_index = ((Elf32_Sym *)s1->dynsymtab_section->data + sym_index)->st_value;
-    dllref = s1->loaded_dlls[dll_index-1];
-    if ( !dllref->handle )
-    {
-        dllref->handle = LoadLibrary(dllref->name);
-    }
-    addr = GetProcAddress(dllref->handle, symbol);
-    if (NULL == addr)
-        addr = GetProcAddress(dllref->handle, get_alt_symbol(buffer, symbol));
-
-    if (addr && STT_OBJECT == type) {
-        /* need to return a pointer to the address for data objects */
-        m = (void**)tcc_malloc(sizeof addr), *m = addr, addr = m;
-#ifdef MEM_DEBUG
-        /* yep, we don't free it */
-        mem_cur_size -= sizeof (void*);
-#endif
-    }
-    return addr;
-}
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-ST_FN int dynarray_assoc(void **pp, int n, int key)
-{
-    int i;
-    for (i = 0; i < n; ++i, ++pp)
-    if (key == **(int **) pp)
-        return i;
-    return -1;
-}
-
-#if 0
-ST_FN DWORD umin(DWORD a, DWORD b)
-{
-    return a < b ? a : b;
-}
-#endif
-
-ST_FN DWORD umax(DWORD a, DWORD b)
-{
-    return a < b ? b : a;
-}
-
-ST_FN void pe_fpad(FILE *fp, DWORD new_pos)
-{
-    DWORD pos = ftell(fp);
-    while (++pos <= new_pos)
-        fputc(0, fp);
-}
-
-ST_FN DWORD pe_file_align(DWORD n)
-{
-    return (n + (0x200 - 1)) & ~(0x200 - 1);
-}
-
-ST_FN DWORD pe_virtual_align(DWORD n)
-{
-    return (n + (0x1000 - 1)) & ~(0x1000 - 1);
-}
-
-ST_FN void pe_align_section(Section *s, int a)
-{
-    int i = s->data_offset & (a-1);
-    if (i)
-        section_ptr_add(s, a - i);
-}
-
-ST_FN void pe_set_datadir(int dir, DWORD addr, DWORD size)
-{
-    pe_header.opthdr.DataDirectory[dir].VirtualAddress = addr;
-    pe_header.opthdr.DataDirectory[dir].Size = size;
-}
-
-/*----------------------------------------------------------------------------*/
-ST_FN int pe_write(struct pe_info *pe)
-{
-    int i;
-    FILE *op;
-    DWORD file_offset, r;
-
-    op = fopen(pe->filename, "wb");
-    if (NULL == op) {
-        error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
-        return 1;
-    }
-
-    pe->sizeofheaders = pe_file_align(
-        sizeof pe_header
-        + pe->sec_count * sizeof (IMAGE_SECTION_HEADER)
-        );
-
-    file_offset = pe->sizeofheaders;
-    pe_fpad(op, file_offset);
-
-    if (2 == pe->s1->verbose)
-        printf("-------------------------------"
-               "\n  virt   file   size  section" "\n");
-
-    for (i = 0; i < pe->sec_count; ++i) {
-        struct section_info *si = pe->sec_info + i;
-        const char *sh_name = si->name;
-        unsigned long addr = si->sh_addr - pe->imagebase;
-        unsigned long size = si->sh_size;
-        IMAGE_SECTION_HEADER *psh = &si->ish;
-
-        if (2 == pe->s1->verbose)
-            printf("%6lx %6lx %6lx  %s\n",
-                addr, file_offset, size, sh_name);
-
-        switch (si->cls) {
-            case sec_text:
-                pe_header.opthdr.BaseOfCode = addr;
-                pe_header.opthdr.AddressOfEntryPoint = addr + pe->start_addr;
-                break;
-
-            case sec_data:
-                pe_header.opthdr.BaseOfData = addr;
-                break;
-
-            case sec_bss:
-                break;
-
-            case sec_reloc:
-                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_BASERELOC, addr, size);
-                break;
-
-            case sec_rsrc:
-                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
-                break;
-
-            case sec_stab:
-                break;
-        }
-
-        if (pe->thunk == pe->s1->sections[si->ord]) {
-            if (pe->imp_size) {
-                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IMPORT,
-                    pe->imp_offs + addr, pe->imp_size);
-                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IAT,
-                    pe->iat_offs + addr, pe->iat_size);
-            }
-            if (pe->exp_size) {
-                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_EXPORT,
-                    pe->exp_offs + addr, pe->exp_size);
-            }
-        }
-
-        strcpy((char*)psh->Name, sh_name);
-
-        psh->Characteristics = pe_sec_flags[si->cls];
-        psh->VirtualAddress = addr;
-        psh->Misc.VirtualSize = size;
-        pe_header.opthdr.SizeOfImage =
-            umax(pe_virtual_align(size + addr), pe_header.opthdr.SizeOfImage); 
-
-        if (si->data_size) {
-            psh->PointerToRawData = r = file_offset;
-            fwrite(si->data, 1, si->data_size, op);
-            file_offset = pe_file_align(file_offset + si->data_size);
-            psh->SizeOfRawData = file_offset - r;
-            pe_fpad(op, file_offset);
-        }
-    }
-
-    // pe_header.filehdr.TimeDateStamp = time(NULL);
-    pe_header.filehdr.NumberOfSections = pe->sec_count;
-    pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
-    pe_header.opthdr.ImageBase = pe->imagebase;
-    if (PE_DLL == pe->type)
-        pe_header.filehdr.Characteristics = 0x230E;
-    else if (PE_GUI != pe->type)
-        pe_header.opthdr.Subsystem = 3;
-
-    fseek(op, SEEK_SET, 0);
-    fwrite(&pe_header,  1, sizeof pe_header, op);
-    for (i = 0; i < pe->sec_count; ++i)
-        fwrite(&pe->sec_info[i].ish, 1, sizeof(IMAGE_SECTION_HEADER), op);
-    fclose (op);
-
-    if (2 == pe->s1->verbose)
-        printf("-------------------------------\n");
-    if (pe->s1->verbose)
-        printf("<- %s (%lu bytes)\n", pe->filename, file_offset);
-
-    return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-ST_FN struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index)
-{
-    int i;
-    int dll_index;
-    struct pe_import_info *p;
-    struct import_symbol *s;
-
-    dll_index = ((Elf32_Sym *)pe->s1->dynsymtab_section->data + sym_index)->st_value;
-    if (0 == dll_index)
-        return NULL;
-
-    i = dynarray_assoc ((void**)pe->imp_info, pe->imp_count, dll_index);
-    if (-1 != i) {
-        p = pe->imp_info[i];
-        goto found_dll;
-    }
-    p = tcc_mallocz(sizeof *p);
-    p->dll_index = dll_index;
-    dynarray_add((void***)&pe->imp_info, &pe->imp_count, p);
-
-found_dll:
-    i = dynarray_assoc ((void**)p->symbols, p->sym_count, sym_index);
-    if (-1 != i)
-        return p->symbols[i];
-
-    s = tcc_mallocz(sizeof *s);
-    dynarray_add((void***)&p->symbols, &p->sym_count, s);
-    s->sym_index = sym_index;
-    return s;
-}
-
-/*----------------------------------------------------------------------------*/
-ST_FN void pe_build_imports(struct pe_info *pe)
-{
-    int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i;
-    DWORD rva_base = pe->thunk->sh_addr - pe->imagebase;
-    int ndlls = pe->imp_count;
-
-    for (sym_cnt = i = 0; i < ndlls; ++i)
-        sym_cnt += pe->imp_info[i]->sym_count;
-
-    if (0 == sym_cnt)
-        return;
-
-    pe_align_section(pe->thunk, 16);
-
-    pe->imp_offs = dll_ptr = pe->thunk->data_offset;
-    pe->imp_size = (ndlls + 1) * sizeof(struct pe_import_header);
-    pe->iat_offs = dll_ptr + pe->imp_size;
-    pe->iat_size = (sym_cnt + ndlls) * sizeof(DWORD);
-    section_ptr_add(pe->thunk, pe->imp_size + 2*pe->iat_size);
-
-    thk_ptr = pe->iat_offs;
-    ent_ptr = pe->iat_offs + pe->iat_size;
-
-    for (i = 0; i < pe->imp_count; ++i) {
-        struct pe_import_header *hdr;
-        int k, n, v;
-        struct pe_import_info *p = pe->imp_info[i];
-        const char *name = pe->s1->loaded_dlls[p->dll_index-1]->name;
-
-        /* put the dll name into the import header */
-        v = put_elf_str(pe->thunk, name);
-
-        hdr = (struct pe_import_header*)(pe->thunk->data + dll_ptr);
-        hdr->first_thunk     = thk_ptr + rva_base;
-        hdr->first_entry     = ent_ptr + rva_base;
-        hdr->lib_name_offset = v + rva_base;
-
-        for (k = 0, n = p->sym_count; k <= n; ++k) {
-            if (k < n) {
-                DWORD iat_index = p->symbols[k]->iat_index;
-                int sym_index = p->symbols[k]->sym_index;
-                Elf32_Sym *imp_sym = (Elf32_Sym *)pe->s1->dynsymtab_section->data + sym_index;
-                Elf32_Sym *org_sym = (Elf32_Sym *)symtab_section->data + iat_index;
-                const char *name = pe->s1->dynsymtab_section->link->data + imp_sym->st_name;
-
-                org_sym->st_value = thk_ptr;
-                org_sym->st_shndx = pe->thunk->sh_num;
-                v = pe->thunk->data_offset + rva_base;
-                section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
-                put_elf_str(pe->thunk, name);
-
-            } else {
-                v = 0; /* last entry is zero */
-            }
-            *(DWORD*)(pe->thunk->data+thk_ptr) =
-            *(DWORD*)(pe->thunk->data+ent_ptr) = v;
-            thk_ptr += sizeof (DWORD);
-            ent_ptr += sizeof (DWORD);
-        }
-        dll_ptr += sizeof(struct pe_import_header);
-        dynarray_reset(&p->symbols, &p->sym_count);
-    }
-    dynarray_reset(&pe->imp_info, &pe->imp_count);
-}
-
-/* ------------------------------------------------------------- */
-/*
-    For now only functions are exported. Export of data
-    would work, but import requires compiler support to
-    do an additional indirection.
-
-    For instance:
-        __declspec(dllimport) extern int something;
-
-    needs to be translated to:
-
-        *(int*)something
-*/
-
-ST_FN int sym_cmp(const void *va, const void *vb)
-{
-    const char *ca = ((const char **)va)[1];
-    const char *cb = ((const char **)vb)[1];
-    return strcmp(ca, cb);
-}
-
-ST_FN void pe_build_exports(struct pe_info *pe)
-{
-    Elf32_Sym *sym;
-    int sym_index, sym_end;
-    DWORD rva_base, func_o, name_o, ord_o, str_o;
-    struct pe_export_header *hdr;
-    int sym_count, n, ord, *sorted, *sp;
-
-    FILE *op;
-    char buf[MAX_PATH];
-    const char *dllname;
-    const char *name;
-
-    rva_base = pe->thunk->sh_addr - pe->imagebase;
-    sym_count = 0, n = 1, sorted = NULL, op = NULL;
-
-    sym_end = symtab_section->data_offset / sizeof(Elf32_Sym);
-    for (sym_index = 1; sym_index < sym_end; ++sym_index) {
-        sym = (Elf32_Sym*)symtab_section->data + sym_index;
-        name = symtab_section->link->data + sym->st_name;
-        if ((sym->st_other & 1)
-            /* export only symbols from actually written sections */
-            && pe->s1->sections[sym->st_shndx]->sh_addr) {
-            dynarray_add((void***)&sorted, &sym_count, (void*)n);
-            dynarray_add((void***)&sorted, &sym_count, (void*)name);
-        }
-        ++n;
-#if 0
-        if (sym->st_other & 1)
-            printf("export: %s\n", name);
-        if (sym->st_other & 2)
-            printf("stdcall: %s\n", name);
-#endif
-    }
-
-    if (0 == sym_count)
-        return;
-    sym_count /= 2;
-
-    qsort (sorted, sym_count, 2 * sizeof sorted[0], sym_cmp);
-    pe_align_section(pe->thunk, 16);
-    dllname = tcc_basename(pe->filename);
-
-    pe->exp_offs = pe->thunk->data_offset;
-    func_o = pe->exp_offs + sizeof(struct pe_export_header);
-    name_o = func_o + sym_count * sizeof (DWORD);
-    ord_o = name_o + sym_count * sizeof (DWORD);
-    str_o = ord_o + sym_count * sizeof(WORD);
-
-    hdr = section_ptr_add(pe->thunk, str_o - pe->exp_offs);
-    hdr->Characteristics        = 0;
-    hdr->Base                   = 1;
-    hdr->NumberOfFunctions      = sym_count;
-    hdr->NumberOfNames          = sym_count;
-    hdr->AddressOfFunctions     = func_o + rva_base;
-    hdr->AddressOfNames         = name_o + rva_base;
-    hdr->AddressOfNameOrdinals  = ord_o + rva_base;
-    hdr->Name                   = str_o + rva_base;
-    put_elf_str(pe->thunk, dllname);
-
-#if 1
-    /* automatically write exports to <output-filename>.def */
-    strcpy(buf, pe->filename);
-    strcpy(tcc_fileextension(buf), ".def");
-    op = fopen(buf, "w");
-    if (NULL == op) {
-        error_noabort("could not create '%s': %s", buf, strerror(errno));
-    } else {
-        fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
-        if (pe->s1->verbose)
-            printf("<- %s (%d symbols)\n", buf, sym_count);
-    }
-#endif
-
-    for (sp = sorted, ord = 0; ord < sym_count; ++ord, sp += 2)
-    {
-        sym_index = sp[0], name = (const char *)sp[1];
-        /* insert actual address later in pe_relocate_rva */
-        put_elf_reloc(symtab_section, pe->thunk,
-            func_o, R_386_RELATIVE, sym_index);
-        *(DWORD*)(pe->thunk->data + name_o)
-            = pe->thunk->data_offset + rva_base;
-        *(WORD*)(pe->thunk->data + ord_o)
-            = ord;
-        put_elf_str(pe->thunk, name);
-        func_o += sizeof (DWORD);
-        name_o += sizeof (DWORD);
-        ord_o += sizeof (WORD);
-
-        if (op)
-            fprintf(op, "%s\n", name);
-    }
-    pe->exp_size = pe->thunk->data_offset - pe->exp_offs;
-    tcc_free(sorted);
-}
-
-/* ------------------------------------------------------------- */
-ST_FN void pe_build_reloc (struct pe_info *pe)
-{
-    DWORD offset, block_ptr, addr;
-    int count, i;
-    Elf32_Rel *rel, *rel_end;
-    Section *s = NULL, *sr;
-
-    offset = addr = block_ptr = count = i = 0;
-    rel = rel_end = NULL;
-
-    for(;;) {
-        if (rel < rel_end) {
-            int type = ELF32_R_TYPE(rel->r_info);
-            addr = rel->r_offset + s->sh_addr;
-            ++ rel;
-            if (type != R_386_32)
-                continue;
-            if (count == 0) { /* new block */
-                block_ptr = pe->reloc->data_offset;
-                section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
-                offset = addr & 0xFFFFFFFF<<12;
-            }
-            if ((addr -= offset)  < (1<<12)) { /* one block spans 4k addresses */
-                WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD));
-                *wp = addr | IMAGE_REL_BASED_HIGHLOW<<12;
-                ++count;
-                continue;
-            }
-            -- rel;
-
-        } else if (i < pe->sec_count) {
-            sr = (s = pe->s1->sections[pe->sec_info[i++].ord])->reloc;
-            if (sr) {
-                rel = (Elf32_Rel *)sr->data;
-                rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
-            }
-            continue;
-        }
-
-        if (count) {
-            /* store the last block and ready for a new one */
-            struct pe_reloc_header *hdr;
-            if (count & 1) /* align for DWORDS */
-                section_ptr_add(pe->reloc, sizeof(WORD)), ++count;
-            hdr = (struct pe_reloc_header *)(pe->reloc->data + block_ptr);
-            hdr -> offset = offset - pe->imagebase;
-            hdr -> size = count * sizeof(WORD) + sizeof(struct pe_reloc_header);
-            count = 0;
-        }
-
-        if (rel >= rel_end)
-            break;
-    }
-}
-
-/* ------------------------------------------------------------- */
-ST_FN int pe_section_class(Section *s)
-{
-    int type, flags;
-    const char *name;
-
-    type = s->sh_type;
-    flags = s->sh_flags;
-    name = s->name;
-    if (flags & SHF_ALLOC) {
-        if (type == SHT_PROGBITS) {
-            if (flags & SHF_EXECINSTR)
-                return sec_text;
-            if (flags & SHF_WRITE)
-                return sec_data;
-            if (0 == strcmp(name, ".rsrc"))
-                return sec_rsrc;
-            if (0 == strcmp(name, ".iedat"))
-                return sec_idata;
-            return sec_other;
-        } else if (type == SHT_NOBITS) {
-            if (flags & SHF_WRITE)
-                return sec_bss;
-        }
-    } else {
-        if (0 == strcmp(name, ".reloc"))
-            return sec_reloc;
-        if (0 == strncmp(name, ".stab", 5)) /* .stab and .stabstr */
-            return sec_stab;
-    }
-    return -1;
-}
-
-ST_FN int pe_assign_addresses (struct pe_info *pe)
-{
-    int i, k, o, c;
-    DWORD addr;
-    int *section_order;
-    struct section_info *si;
-    Section *s;
-
-    // pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
-
-    section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int));
-    for (o = k = 0 ; k < sec_last; ++k) {
-        for (i = 1; i < pe->s1->nb_sections; ++i) {
-            s = pe->s1->sections[i];
-            if (k == pe_section_class(s)) {
-                // printf("%s %d\n", s->name, k);
-                s->sh_addr = pe->imagebase;
-                section_order[o++] = i;
-            }
-        }
-    }
-
-    pe->sec_info = tcc_mallocz(o * sizeof (struct section_info));
-    addr = pe->imagebase + 1;
-
-    for (i = 0; i < o; ++i)
-    {
-        k = section_order[i];
-        s = pe->s1->sections[k];
-        c = pe_section_class(s);
-        si = &pe->sec_info[pe->sec_count];
-
-#ifdef PE_MERGE_DATA
-        if (c == sec_bss && pe->sec_count && si[-1].cls == sec_data) {
-            /* append .bss to .data */
-            s->sh_addr = addr = ((addr-1) | 15) + 1;
-            addr += s->data_offset;
-            si[-1].sh_size = addr - si[-1].sh_addr;
-            continue;
-        }
-#endif
-        strcpy(si->name, s->name);
-        si->cls = c;
-        si->ord = k;
-        si->sh_addr = s->sh_addr = addr = pe_virtual_align(addr);
-        si->sh_flags = s->sh_flags;
-
-        if (c == sec_data && NULL == pe->thunk)
-            pe->thunk = s;
-
-        if (s == pe->thunk) {
-            pe_build_imports(pe);
-            pe_build_exports(pe);
-        }
-
-        if (c == sec_reloc)
-            pe_build_reloc (pe);
-
-        if (s->data_offset)
-        {
-            if (s->sh_type != SHT_NOBITS) {
-                si->data = s->data;
-                si->data_size = s->data_offset;
-            }
-
-            addr += s->data_offset;
-            si->sh_size = s->data_offset;
-            ++pe->sec_count;
-        }
-        // printf("%08x %05x %s\n", si->sh_addr, si->sh_size, si->name);
-    }
-
-#if 0
-    for (i = 1; i < pe->s1->nb_sections; ++i) {
-        Section *s = pe->s1->sections[i];
-        int type = s->sh_type;
-        int flags = s->sh_flags;
-        printf("section %-16s %-10s %5x %s,%s,%s\n",
-            s->name,
-            type == SHT_PROGBITS ? "progbits" :
-            type == SHT_NOBITS ? "nobits" :
-            type == SHT_SYMTAB ? "symtab" :
-            type == SHT_STRTAB ? "strtab" :
-            type == SHT_REL ? "rel" : "???",
-            s->data_offset,
-            flags & SHF_ALLOC ? "alloc" : "",
-            flags & SHF_WRITE ? "write" : "",
-            flags & SHF_EXECINSTR ? "exec" : ""
-            );
-    }
-    pe->s1->verbose = 2;
-#endif
-
-    tcc_free(section_order);
-    return 0;
-}
-
-/* ------------------------------------------------------------- */
-ST_FN void pe_relocate_rva (struct pe_info *pe, Section *s)
-{
-    Section *sr = s->reloc;
-    Elf32_Rel *rel, *rel_end;
-    rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
-    for(rel = (Elf32_Rel *)sr->data; rel < rel_end; rel++)
-        if (ELF32_R_TYPE(rel->r_info) == R_386_RELATIVE) {
-            int sym_index = ELF32_R_SYM(rel->r_info);
-            DWORD addr = s->sh_addr;
-            if (sym_index) {
-                Elf32_Sym *sym = (Elf32_Sym *)symtab_section->data + sym_index;
-                addr = sym->st_value;
-            }
-            *(DWORD*)(s->data + rel->r_offset) += addr - pe->imagebase;
-        }
-}
-
-/*----------------------------------------------------------------------------*/
-ST_FN int pe_check_symbols(struct pe_info *pe)
-{
-    Elf32_Sym *sym;
-    int sym_index, sym_end;
-    int ret = 0;
-
-    pe_align_section(text_section, 8);
-
-    sym_end = symtab_section->data_offset / sizeof(Elf32_Sym);
-    for (sym_index = 1; sym_index < sym_end; ++sym_index) {
-
-        sym = (Elf32_Sym*)symtab_section->data + sym_index;
-        if (sym->st_shndx == SHN_UNDEF) {
-
-            const char *name = symtab_section->link->data + sym->st_name;
-            unsigned type = ELF32_ST_TYPE(sym->st_info);
-            int imp_sym = pe_find_import(pe->s1, name);
-            struct import_symbol *is;
-
-            if (0 == imp_sym)
-                goto not_found;
-            is = pe_add_import(pe, imp_sym);
-            if (!is)
-                goto not_found;
-
-            if (type == STT_FUNC) {
-                unsigned long offset = is->thk_offset;
-                if (offset) {
-                    /* got aliased symbol, like stricmp and _stricmp */
-
-                } else {
-                    char buffer[100];
-
-                    offset = text_section->data_offset;
-                    /* add the 'jmp IAT[x]' instruction */
-                    *(WORD*)section_ptr_add(text_section, 8) = 0x25FF;
-
-                    /* add a helper symbol, will be patched later in
-                       pe_build_imports */
-                    sprintf(buffer, "IAT.%s", name);
-                    is->iat_index = put_elf_sym(
-                        symtab_section, 0, sizeof(DWORD),
-                        ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
-                        0, SHN_UNDEF, buffer);
-                    put_elf_reloc(symtab_section, text_section, 
-                        offset + 2, R_386_32, is->iat_index);
-                    is->thk_offset = offset;
-                }
-
-                /* tcc_realloc might have altered sym's address */
-                sym = (Elf32_Sym*)symtab_section->data + sym_index;
-
-                /* patch the original symbol */
-                sym->st_value = offset;
-                sym->st_shndx = text_section->sh_num;
-                sym->st_other &= ~1; /* do not export */
-                continue;
-            }
-
-            if (type == STT_OBJECT) { /* data, ptr to that should be */
-                if (0 == is->iat_index) {
-                    /* original symbol will be patched later in pe_build_imports */
-                    is->iat_index = sym_index;
-                    continue;
-                }
-            }
-
-        not_found:
-            error_noabort("undefined symbol '%s'", name);
-            ret = 1;
-
-        } else if (pe->s1->rdynamic
-                   && ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
-            /* if -rdynamic option, then export all non local symbols */
-            sym->st_other |= 1;
-        }
-    }
-    return ret;
-}
-
-/*----------------------------------------------------------------------------*/
-#ifdef PE_PRINT_SECTIONS
-ST_FN void pe_print_section(FILE * f, Section * s)
-{
-    /* just if you'r curious */
-    BYTE *p, *e, b;
-    int i, n, l, m;
-    p = s->data;
-    e = s->data + s->data_offset;
-    l = e - p;
-
-    fprintf(f, "section  \"%s\"", s->name);
-    if (s->link)
-        fprintf(f, "\nlink     \"%s\"", s->link->name);
-    if (s->reloc)
-        fprintf(f, "\nreloc    \"%s\"", s->reloc->name);
-    fprintf(f, "\nv_addr   %08X", s->sh_addr);
-    fprintf(f, "\ncontents %08X", l);
-    fprintf(f, "\n\n");
-
-    if (s->sh_type == SHT_NOBITS)
-        return;
-
-    if (0 == l)
-        return;
-
-    if (s->sh_type == SHT_SYMTAB)
-        m = sizeof(Elf32_Sym);
-    if (s->sh_type == SHT_REL)
-        m = sizeof(Elf32_Rel);
-    else
-        m = 16;
-
-    fprintf(f, "%-8s", "offset");
-    for (i = 0; i < m; ++i)
-        fprintf(f, " %02x", i);
-    n = 56;
-
-    if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_REL) {
-        const char *fields1[] = {
-            "name",
-            "value",
-            "size",
-            "bind",
-            "type",
-            "other",
-            "shndx",
-            NULL
-        };
-
-        const char *fields2[] = {
-            "offs",
-            "type",
-            "symb",
-            NULL
-        };
-
-        const char **p;
-
-        if (s->sh_type == SHT_SYMTAB)
-            p = fields1, n = 106;
-        else
-            p = fields2, n = 58;
-
-        for (i = 0; p[i]; ++i)
-            fprintf(f, "%6s", p[i]);
-        fprintf(f, "  symbol");
-    }
-
-    fprintf(f, "\n");
-    for (i = 0; i < n; ++i)
-        fprintf(f, "-");
-    fprintf(f, "\n");
-
-    for (i = 0; i < l;)
-    {
-        fprintf(f, "%08X", i);
-        for (n = 0; n < m; ++n) {
-            if (n + i < l)
-                fprintf(f, " %02X", p[i + n]);
-            else
-                fprintf(f, "   ");
-        }
-
-        if (s->sh_type == SHT_SYMTAB) {
-            Elf32_Sym *sym = (Elf32_Sym *) (p + i);
-            const char *name = s->link->data + sym->st_name;
-            fprintf(f, "  %04X  %04X  %04X   %02X    %02X    %02X   %04X  \"%s\"",
-                    sym->st_name,
-                    sym->st_value,
-                    sym->st_size,
-                    ELF32_ST_BIND(sym->st_info),
-                    ELF32_ST_TYPE(sym->st_info),
-                    sym->st_other, sym->st_shndx, name);
-
-        } else if (s->sh_type == SHT_REL) {
-            Elf32_Rel *rel = (Elf32_Rel *) (p + i);
-            Elf32_Sym *sym =
-                (Elf32_Sym *) s->link->data + ELF32_R_SYM(rel->r_info);
-            const char *name = s->link->link->data + sym->st_name;
-            fprintf(f, "  %04X   %02X   %04X  \"%s\"",
-                    rel->r_offset,
-                    ELF32_R_TYPE(rel->r_info),
-                    ELF32_R_SYM(rel->r_info), name);
-        } else {
-            fprintf(f, "   ");
-            for (n = 0; n < m; ++n) {
-                if (n + i < l) {
-                    b = p[i + n];
-                    if (b < 32 || b >= 127)
-                        b = '.';
-                    fprintf(f, "%c", b);
-                }
-            }
-        }
-        i += m;
-        fprintf(f, "\n");
-    }
-    fprintf(f, "\n\n");
-}
-
-ST_FN void pe_print_sections(TCCState *s1, const char *fname)
-{
-    Section *s;
-    FILE *f;
-    int i;
-    f = fopen(fname, "wt");
-    for (i = 1; i < s1->nb_sections; ++i) {
-        s = s1->sections[i];
-        pe_print_section(f, s);
-    }
-    pe_print_section(f, s1->dynsymtab_section);
-    fclose(f);
-}
-#endif
-
-/* -------------------------------------------------------------
- *  This is for compiled windows resources in 'coff' format
- *  as generated by 'windres.exe -O coff ...'.
- */
-
-PUB_FN int pe_test_res_file(void *v, int size)
-{
-    struct pe_rsrc_header *p = (struct pe_rsrc_header *)v;
-    return
-        size >= IMAGE_SIZEOF_FILE_HEADER + IMAGE_SIZEOF_SHORT_NAME /* = 28 */
-        && p->filehdr.Machine == 0x014C
-        && 1 == p->filehdr.NumberOfSections
-        && 0 == strcmp(p->sectionhdr.Name, ".rsrc")
-        ;
-}
-
-ST_FN int read_n(int fd, void *ptr, unsigned size)
-{
-    return size == read(fd, ptr, size);
-}
-
-PUB_FN int pe_load_res_file(TCCState *s1, int fd)
-{
-    struct pe_rsrc_header hdr;
-    Section *rsrc_section;
-    int i, ret = -1;
-    BYTE *ptr;
-
-    lseek (fd, 0, SEEK_SET);
-    if (!read_n(fd, &hdr, sizeof hdr))
-        goto quit;
-    if (!pe_test_res_file(&hdr, sizeof hdr))
-        goto quit;
-
-    rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
-    ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
-    lseek (fd, hdr.sectionhdr.PointerToRawData, SEEK_SET);
-    if (!read_n(fd, ptr, hdr.sectionhdr.SizeOfRawData))
-        goto quit;
-
-    lseek (fd, hdr.sectionhdr.PointerToRelocations, SEEK_SET);
-    for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i)
-    {
-        struct pe_rsrc_reloc rel;
-        if (!read_n(fd, &rel, sizeof rel))
-            goto quit;
-        // printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type);
-        if (rel.type != 7) /* DIR32NB */
-            goto quit;
-        put_elf_reloc(symtab_section, rsrc_section,
-            rel.offset, R_386_RELATIVE, 0);
-    }
-    ret = 0;
-quit:
-    if (ret)
-        error_noabort("unrecognized resource file format");
-    return ret;
-}
-
-/* ------------------------------------------------------------- */
-ST_FN char *trimfront(char *p)
-{
-    while (*p && (unsigned char)*p <= ' ')
-        ++p;
-    return p;
-}
-
-ST_FN char *trimback(char *a, char *e)
-{
-    while (e > a && (unsigned char)e[-1] <= ' ')
-        --e;
-    *e = 0;;
-    return a;
-}
-
-ST_FN char *get_line(char *line, int size, FILE *fp)
-{
-    if (NULL == fgets(line, size, fp))
-        return NULL;
-    trimback(line, strchr(line, 0));
-    return trimfront(line);
-}
-
-/* ------------------------------------------------------------- */
-PUB_FN int pe_load_def_file(TCCState *s1, int fd)
-{
-    DLLReference *dllref;
-    int state = 0, ret = -1;
-    char line[400], dllname[80], *p;
-    FILE *fp = fdopen(dup(fd), "rb");
-
-    if (NULL == fp)
-        goto quit;
-
-    for (;;) {
-        p = get_line(line, sizeof line, fp);
-        if (NULL == p)
-            break;
-        if (0 == *p || ';' == *p)
-            continue;
-        switch (state) {
-        case 0:
-            if (0 != strnicmp(p, "LIBRARY", 7))
-                goto quit;
-            strcpy(dllname, trimfront(p+7));
-            ++state;
-            continue;
-
-        case 1:
-            if (0 != stricmp(p, "EXPORTS"))
-                goto quit;
-            ++state;
-            continue;
-
-        case 2:
-            dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
-            strcpy(dllref->name, dllname);
-            dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
-            ++state;
-
-        default:
-            add_elf_sym(s1->dynsymtab_section,
-                s1->nb_loaded_dlls, 0,
-                ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), 0,
-                text_section->sh_num, p);
-            continue;
-        }
-    }
-    ret = 0;
-quit:
-    if (fp)
-        fclose(fp);
-    if (ret)
-        error_noabort("unrecognized export definition file format");
-    return ret;
-}
-
-/* ------------------------------------------------------------- */
-
-ST_FN void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
-{
-    const char *start_symbol;
-    unsigned long addr = 0;
-    int pe_type = 0;
-
-    if (find_elf_sym(symtab_section, "_WinMain@16"))
-        pe_type = PE_GUI;
-    else
-    if (TCC_OUTPUT_DLL == s1->output_type) {
-        pe_type = PE_DLL;
-        /* need this for 'tccelf.c:relocate_section()' */
-        s1->output_type = TCC_OUTPUT_EXE;
-    }
-
-    start_symbol =
-        TCC_OUTPUT_MEMORY == s1->output_type
-        ? PE_GUI == pe_type ? "_runwinmain" : NULL
-        : PE_DLL == pe_type ? "__dllstart@12"
-        : PE_GUI == pe_type ? "_winstart" : "_start"
-        ;
-
-    /* grab the startup code from libtcc1 */
-    if (start_symbol)
-        add_elf_sym(symtab_section,
-            0, 0,
-            ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
-            SHN_UNDEF, start_symbol);
-
-    if (0 == s1->nostdlib) {
-        tcc_add_library(s1, "tcc1");
-#ifdef __CYGWIN__
-        tcc_add_library(s1, "cygwin1");
-#else
-        tcc_add_library(s1, "msvcrt");
-#endif
-        tcc_add_library(s1, "kernel32");
-        if (PE_DLL == pe_type || PE_GUI == pe_type) {
-            tcc_add_library(s1, "user32");
-            tcc_add_library(s1, "gdi32");
-        }
-    }
-
-    if (start_symbol) {
-        addr = (unsigned long)tcc_get_symbol_err(s1, start_symbol);
-        if (s1->output_type == TCC_OUTPUT_MEMORY && addr)
-            /* for -run GUI's, put '_runwinmain' instead of 'main' */
-            add_elf_sym(symtab_section,
-                    addr, 0,
-                    ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
-                    text_section->sh_num, "main");
-    }
-
-    if (pe) {
-        pe->type = pe_type;
-        pe->start_addr = addr;
-    }
-}
-
-PUB_FN void pe_add_runtime(TCCState *s1)
-{
-    pe_add_runtime_ex(s1, NULL);
-}
-
-PUB_FN int pe_output_file(TCCState * s1, const char *filename)
-{
-    int ret;
-    struct pe_info pe;
-    int i;
-
-    memset(&pe, 0, sizeof pe);
-    pe.filename = filename;
-    pe.s1 = s1;
-
-    pe_add_runtime_ex(s1, &pe);
-    relocate_common_syms(); /* assign bss adresses */
-    tcc_add_linker_symbols(s1);
-
-    ret = pe_check_symbols(&pe);
-    if (0 == ret) {
-        if (PE_DLL == pe.type) {
-            pe.reloc = new_section(pe.s1, ".reloc", SHT_PROGBITS, 0);
-            pe.imagebase = 0x10000000;
-        } else {
-            pe.imagebase = 0x00400000;
-        }
-        pe_assign_addresses(&pe);
-        relocate_syms(s1, 0);
-        for (i = 1; i < s1->nb_sections; ++i) {
-            Section *s = s1->sections[i];
-            if (s->reloc) {
-                relocate_section(s1, s);
-                pe_relocate_rva(&pe, s);
-            }
-        }
-        if (s1->nb_errors)
-            ret = 1;
-        else
-            ret = pe_write(&pe);
-        tcc_free(pe.sec_info);
-    }
-
-#ifdef PE_PRINT_SECTIONS
-    pe_print_sections(s1, "tcc.log");
-#endif
-    return ret;
-}
-
-/* ------------------------------------------------------------- */
-#endif /* def TCC_TARGET_PE */
-/* ------------------------------------------------------------- */

+ 0 - 2935
src/modules/native/tcc/libtcc/tccpp.c

@@ -1,2935 +0,0 @@
-/*
- *  TCC - Tiny C Compiler
- * 
- *  Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-static const char tcc_keywords[] = 
-#define DEF(id, str) str "\0"
-#include "tcctok.h"
-#undef DEF
-;
-
-/* WARNING: the content of this string encodes token numbers */
-static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
-
-/* true if isid(c) || isnum(c) */
-static unsigned char isidnum_table[256-CH_EOF];
-
-
-struct macro_level {
-    struct macro_level *prev;
-    int *p;
-};
-
-static void next_nomacro(void);
-static void next_nomacro_spc(void);
-static void macro_subst(TokenString *tok_str, Sym **nested_list,
-                        const int *macro_str, struct macro_level **can_read_stream);
-
-
-/* allocate a new token */
-static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
-{
-    TokenSym *ts, **ptable;
-    int i;
-
-    if (tok_ident >= SYM_FIRST_ANOM) 
-        error("memory full");
-
-    /* expand token table if needed */
-    i = tok_ident - TOK_IDENT;
-    if ((i % TOK_ALLOC_INCR) == 0) {
-        ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
-        if (!ptable)
-            error("memory full");
-        table_ident = ptable;
-    }
-
-    ts = tcc_malloc(sizeof(TokenSym) + len);
-    table_ident[i] = ts;
-    ts->tok = tok_ident++;
-    ts->sym_define = NULL;
-    ts->sym_label = NULL;
-    ts->sym_struct = NULL;
-    ts->sym_identifier = NULL;
-    ts->len = len;
-    ts->hash_next = NULL;
-    memcpy(ts->str, str, len);
-    ts->str[len] = '\0';
-    *pts = ts;
-    return ts;
-}
-
-#define TOK_HASH_INIT 1
-#define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
-
-/* find a token and add it if not found */
-static TokenSym *tok_alloc(const char *str, int len)
-{
-    TokenSym *ts, **pts;
-    int i;
-    unsigned int h;
-    
-    h = TOK_HASH_INIT;
-    for(i=0;i<len;i++)
-        h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
-    h &= (TOK_HASH_SIZE - 1);
-
-    pts = &hash_ident[h];
-    for(;;) {
-        ts = *pts;
-        if (!ts)
-            break;
-        if (ts->len == len && !memcmp(ts->str, str, len))
-            return ts;
-        pts = &(ts->hash_next);
-    }
-    return tok_alloc_new(pts, str, len);
-}
-
-/* XXX: buffer overflow */
-/* XXX: float tokens */
-char *get_tok_str(int v, CValue *cv)
-{
-    static char buf[STRING_MAX_SIZE + 1];
-    static CString cstr_buf;
-    CString *cstr;
-    unsigned char *q;
-    char *p;
-    int i, len;
-
-    /* NOTE: to go faster, we give a fixed buffer for small strings */
-    cstr_reset(&cstr_buf);
-    cstr_buf.data = buf;
-    cstr_buf.size_allocated = sizeof(buf);
-    p = buf;
-
-    switch(v) {
-    case TOK_CINT:
-    case TOK_CUINT:
-        /* XXX: not quite exact, but only useful for testing */
-        sprintf(p, "%u", cv->ui);
-        break;
-    case TOK_CLLONG:
-    case TOK_CULLONG:
-        /* XXX: not quite exact, but only useful for testing  */
-        sprintf(p, "%Lu", cv->ull);
-        break;
-    case TOK_LCHAR:
-        cstr_ccat(&cstr_buf, 'L');
-    case TOK_CCHAR:
-        cstr_ccat(&cstr_buf, '\'');
-        add_char(&cstr_buf, cv->i);
-        cstr_ccat(&cstr_buf, '\'');
-        cstr_ccat(&cstr_buf, '\0');
-        break;
-    case TOK_PPNUM:
-        cstr = cv->cstr;
-        len = cstr->size - 1;
-        for(i=0;i<len;i++)
-            add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
-        cstr_ccat(&cstr_buf, '\0');
-        break;
-    case TOK_LSTR:
-        cstr_ccat(&cstr_buf, 'L');
-    case TOK_STR:
-        cstr = cv->cstr;
-        cstr_ccat(&cstr_buf, '\"');
-        if (v == TOK_STR) {
-            len = cstr->size - 1;
-            for(i=0;i<len;i++)
-                add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
-        } else {
-            len = (cstr->size / sizeof(nwchar_t)) - 1;
-            for(i=0;i<len;i++)
-                add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
-        }
-        cstr_ccat(&cstr_buf, '\"');
-        cstr_ccat(&cstr_buf, '\0');
-        break;
-    case TOK_LT:
-        v = '<';
-        goto addv;
-    case TOK_GT:
-        v = '>';
-        goto addv;
-    case TOK_DOTS:
-        return strcpy(p, "...");
-    case TOK_A_SHL:
-        return strcpy(p, "<<=");
-    case TOK_A_SAR:
-        return strcpy(p, ">>=");
-    default:
-        if (v < TOK_IDENT) {
-            /* search in two bytes table */
-            q = tok_two_chars;
-            while (*q) {
-                if (q[2] == v) {
-                    *p++ = q[0];
-                    *p++ = q[1];
-                    *p = '\0';
-                    return buf;
-                }
-                q += 3;
-            }
-        addv:
-            *p++ = v;
-            *p = '\0';
-        } else if (v < tok_ident) {
-            return table_ident[v - TOK_IDENT]->str;
-        } else if (v >= SYM_FIRST_ANOM) {
-            /* special name for anonymous symbol */
-            sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
-        } else {
-            /* should never happen */
-            return NULL;
-        }
-        break;
-    }
-    return cstr_buf.data;
-}
-
-/* fill input buffer and peek next char */
-static int tcc_peekc_slow(BufferedFile *bf)
-{
-    int len;
-    /* only tries to read if really end of buffer */
-    if (bf->buf_ptr >= bf->buf_end) {
-        if (bf->fd != -1) {
-#if defined(PARSE_DEBUG)
-            len = 8;
-#else
-            len = IO_BUF_SIZE;
-#endif
-            len = read(bf->fd, bf->buffer, len);
-            if (len < 0)
-                len = 0;
-        } else {
-            len = 0;
-        }
-        total_bytes += len;
-        bf->buf_ptr = bf->buffer;
-        bf->buf_end = bf->buffer + len;
-        *bf->buf_end = CH_EOB;
-    }
-    if (bf->buf_ptr < bf->buf_end) {
-        return bf->buf_ptr[0];
-    } else {
-        bf->buf_ptr = bf->buf_end;
-        return CH_EOF;
-    }
-}
-
-/* return the current character, handling end of block if necessary
-   (but not stray) */
-static int handle_eob(void)
-{
-    return tcc_peekc_slow(file);
-}
-
-/* read next char from current input file and handle end of input buffer */
-static inline void inp(void)
-{
-    ch = *(++(file->buf_ptr));
-    /* end of buffer/file handling */
-    if (ch == CH_EOB)
-        ch = handle_eob();
-}
-
-/* handle '\[\r]\n' */
-static int handle_stray_noerror(void)
-{
-    while (ch == '\\') {
-        inp();
-        if (ch == '\n') {
-            file->line_num++;
-            inp();
-        } else if (ch == '\r') {
-            inp();
-            if (ch != '\n')
-                goto fail;
-            file->line_num++;
-            inp();
-        } else {
-        fail:
-            return 1;
-        }
-    }
-    return 0;
-}
-
-static void handle_stray(void)
-{
-    if (handle_stray_noerror())
-        error("stray '\\' in program");
-}
-
-/* skip the stray and handle the \\n case. Output an error if
-   incorrect char after the stray */
-static int handle_stray1(uint8_t *p)
-{
-    int c;
-
-    if (p >= file->buf_end) {
-        file->buf_ptr = p;
-        c = handle_eob();
-        p = file->buf_ptr;
-        if (c == '\\')
-            goto parse_stray;
-    } else {
-    parse_stray:
-        file->buf_ptr = p;
-        ch = *p;
-        handle_stray();
-        p = file->buf_ptr;
-        c = *p;
-    }
-    return c;
-}
-
-/* handle just the EOB case, but not stray */
-#define PEEKC_EOB(c, p)\
-{\
-    p++;\
-    c = *p;\
-    if (c == '\\') {\
-        file->buf_ptr = p;\
-        c = handle_eob();\
-        p = file->buf_ptr;\
-    }\
-}
-
-/* handle the complicated stray case */
-#define PEEKC(c, p)\
-{\
-    p++;\
-    c = *p;\
-    if (c == '\\') {\
-        c = handle_stray1(p);\
-        p = file->buf_ptr;\
-    }\
-}
-
-/* input with '\[\r]\n' handling. Note that this function cannot
-   handle other characters after '\', so you cannot call it inside
-   strings or comments */
-static void minp(void)
-{
-    inp();
-    if (ch == '\\') 
-        handle_stray();
-}
-
-
-/* single line C++ comments */
-static uint8_t *parse_line_comment(uint8_t *p)
-{
-    int c;
-
-    p++;
-    for(;;) {
-        c = *p;
-    redo:
-        if (c == '\n' || c == CH_EOF) {
-            break;
-        } else if (c == '\\') {
-            file->buf_ptr = p;
-            c = handle_eob();
-            p = file->buf_ptr;
-            if (c == '\\') {
-                PEEKC_EOB(c, p);
-                if (c == '\n') {
-                    file->line_num++;
-                    PEEKC_EOB(c, p);
-                } else if (c == '\r') {
-                    PEEKC_EOB(c, p);
-                    if (c == '\n') {
-                        file->line_num++;
-                        PEEKC_EOB(c, p);
-                    }
-                }
-            } else {
-                goto redo;
-            }
-        } else {
-            p++;
-        }
-    }
-    return p;
-}
-
-/* C comments */
-static uint8_t *parse_comment(uint8_t *p)
-{
-    int c;
-    
-    p++;
-    for(;;) {
-        /* fast skip loop */
-        for(;;) {
-            c = *p;
-            if (c == '\n' || c == '*' || c == '\\')
-                break;
-            p++;
-            c = *p;
-            if (c == '\n' || c == '*' || c == '\\')
-                break;
-            p++;
-        }
-        /* now we can handle all the cases */
-        if (c == '\n') {
-            file->line_num++;
-            p++;
-        } else if (c == '*') {
-            p++;
-            for(;;) {
-                c = *p;
-                if (c == '*') {
-                    p++;
-                } else if (c == '/') {
-                    goto end_of_comment;
-                } else if (c == '\\') {
-                    file->buf_ptr = p;
-                    c = handle_eob();
-                    p = file->buf_ptr;
-                    if (c == '\\') {
-                        /* skip '\[\r]\n', otherwise just skip the stray */
-                        while (c == '\\') {
-                            PEEKC_EOB(c, p);
-                            if (c == '\n') {
-                                file->line_num++;
-                                PEEKC_EOB(c, p);
-                            } else if (c == '\r') {
-                                PEEKC_EOB(c, p);
-                                if (c == '\n') {
-                                    file->line_num++;
-                                    PEEKC_EOB(c, p);
-                                }
-                            } else {
-                                goto after_star;
-                            }
-                        }
-                    }
-                } else {
-                    break;
-                }
-            }
-        after_star: ;
-        } else {
-            /* stray, eob or eof */
-            file->buf_ptr = p;
-            c = handle_eob();
-            p = file->buf_ptr;
-            if (c == CH_EOF) {
-                error("unexpected end of file in comment");
-            } else if (c == '\\') {
-                p++;
-            }
-        }
-    }
- end_of_comment:
-    p++;
-    return p;
-}
-
-#define cinp minp
-
-static inline void skip_spaces(void)
-{
-    while (is_space(ch))
-        cinp();
-}
-
-static inline int check_space(int t, int *spc) 
-{
-    if (is_space(t)) {
-        if (*spc) 
-            return 1;
-        *spc = 1;
-    } else 
-        *spc = 0;
-    return 0;
-}
-
-/* parse a string without interpreting escapes */
-static uint8_t *parse_pp_string(uint8_t *p,
-                                int sep, CString *str)
-{
-    int c;
-    p++;
-    for(;;) {
-        c = *p;
-        if (c == sep) {
-            break;
-        } else if (c == '\\') {
-            file->buf_ptr = p;
-            c = handle_eob();
-            p = file->buf_ptr;
-            if (c == CH_EOF) {
-            unterminated_string:
-                /* XXX: indicate line number of start of string */
-                error("missing terminating %c character", sep);
-            } else if (c == '\\') {
-                /* escape : just skip \[\r]\n */
-                PEEKC_EOB(c, p);
-                if (c == '\n') {
-                    file->line_num++;
-                    p++;
-                } else if (c == '\r') {
-                    PEEKC_EOB(c, p);
-                    if (c != '\n')
-                        expect("'\n' after '\r'");
-                    file->line_num++;
-                    p++;
-                } else if (c == CH_EOF) {
-                    goto unterminated_string;
-                } else {
-                    if (str) {
-                        cstr_ccat(str, '\\');
-                        cstr_ccat(str, c);
-                    }
-                    p++;
-                }
-            }
-        } else if (c == '\n') {
-            file->line_num++;
-            goto add_char;
-        } else if (c == '\r') {
-            PEEKC_EOB(c, p);
-            if (c != '\n') {
-                if (str)
-                    cstr_ccat(str, '\r');
-            } else {
-                file->line_num++;
-                goto add_char;
-            }
-        } else {
-        add_char:
-            if (str)
-                cstr_ccat(str, c);
-            p++;
-        }
-    }
-    p++;
-    return p;
-}
-
-/* skip block of text until #else, #elif or #endif. skip also pairs of
-   #if/#endif */
-void preprocess_skip(void)
-{
-    int a, start_of_line, c, in_warn_or_error;
-    uint8_t *p;
-
-    p = file->buf_ptr;
-    a = 0;
-redo_start:
-    start_of_line = 1;
-    in_warn_or_error = 0;
-    for(;;) {
-    redo_no_start:
-        c = *p;
-        switch(c) {
-        case ' ':
-        case '\t':
-        case '\f':
-        case '\v':
-        case '\r':
-            p++;
-            goto redo_no_start;
-        case '\n':
-            file->line_num++;
-            p++;
-            goto redo_start;
-        case '\\':
-            file->buf_ptr = p;
-            c = handle_eob();
-            if (c == CH_EOF) {
-                expect("#endif");
-            } else if (c == '\\') {
-                ch = file->buf_ptr[0];
-                handle_stray_noerror();
-            }
-            p = file->buf_ptr;
-            goto redo_no_start;
-        /* skip strings */
-        case '\"':
-        case '\'':
-            if (in_warn_or_error)
-                goto _default;
-            p = parse_pp_string(p, c, NULL);
-            break;
-        /* skip comments */
-        case '/':
-            if (in_warn_or_error)
-                goto _default;
-            file->buf_ptr = p;
-            ch = *p;
-            minp();
-            p = file->buf_ptr;
-            if (ch == '*') {
-                p = parse_comment(p);
-            } else if (ch == '/') {
-                p = parse_line_comment(p);
-            }
-            break;
-        case '#':
-            p++;
-            if (start_of_line) {
-                file->buf_ptr = p;
-                next_nomacro();
-                p = file->buf_ptr;
-                if (a == 0 && 
-                    (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
-                    goto the_end;
-                if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
-                    a++;
-                else if (tok == TOK_ENDIF)
-                    a--;
-                else if( tok == TOK_ERROR || tok == TOK_WARNING)
-                    in_warn_or_error = 1;
-            }
-            break;
-_default:
-        default:
-            p++;
-            break;
-        }
-        start_of_line = 0;
-    }
- the_end: ;
-    file->buf_ptr = p;
-}
-
-/* ParseState handling */
-
-/* XXX: currently, no include file info is stored. Thus, we cannot display
-   accurate messages if the function or data definition spans multiple
-   files */
-
-/* save current parse state in 's' */
-void save_parse_state(ParseState *s)
-{
-    s->line_num = file->line_num;
-    s->macro_ptr = macro_ptr;
-    s->tok = tok;
-    s->tokc = tokc;
-}
-
-/* restore parse state from 's' */
-void restore_parse_state(ParseState *s)
-{
-    file->line_num = s->line_num;
-    macro_ptr = s->macro_ptr;
-    tok = s->tok;
-    tokc = s->tokc;
-}
-
-/* return the number of additional 'ints' necessary to store the
-   token */
-static inline int tok_ext_size(int t)
-{
-    switch(t) {
-        /* 4 bytes */
-    case TOK_CINT:
-    case TOK_CUINT:
-    case TOK_CCHAR:
-    case TOK_LCHAR:
-    case TOK_CFLOAT:
-    case TOK_LINENUM:
-        return 1;
-    case TOK_STR:
-    case TOK_LSTR:
-    case TOK_PPNUM:
-        error("unsupported token");
-        return 1;
-    case TOK_CDOUBLE:
-    case TOK_CLLONG:
-    case TOK_CULLONG:
-        return 2;
-    case TOK_CLDOUBLE:
-        return LDOUBLE_SIZE / 4;
-    default:
-        return 0;
-    }
-}
-
-/* token string handling */
-
-static inline void tok_str_new(TokenString *s)
-{
-    s->str = NULL;
-    s->len = 0;
-    s->allocated_len = 0;
-    s->last_line_num = -1;
-}
-
-static void tok_str_free(int *str)
-{
-    tcc_free(str);
-}
-
-static int *tok_str_realloc(TokenString *s)
-{
-    int *str, len;
-
-    if (s->allocated_len == 0) {
-        len = 8;
-    } else {
-        len = s->allocated_len * 2;
-    }
-    str = tcc_realloc(s->str, len * sizeof(int));
-    if (!str)
-        error("memory full");
-    s->allocated_len = len;
-    s->str = str;
-    return str;
-}
-
-static void tok_str_add(TokenString *s, int t)
-{
-    int len, *str;
-
-    len = s->len;
-    str = s->str;
-    if (len >= s->allocated_len)
-        str = tok_str_realloc(s);
-    str[len++] = t;
-    s->len = len;
-}
-
-static void tok_str_add2(TokenString *s, int t, CValue *cv)
-{
-    int len, *str;
-
-    len = s->len;
-    str = s->str;
-
-    /* allocate space for worst case */
-    if (len + TOK_MAX_SIZE > s->allocated_len)
-        str = tok_str_realloc(s);
-    str[len++] = t;
-    switch(t) {
-    case TOK_CINT:
-    case TOK_CUINT:
-    case TOK_CCHAR:
-    case TOK_LCHAR:
-    case TOK_CFLOAT:
-    case TOK_LINENUM:
-        str[len++] = cv->tab[0];
-        break;
-    case TOK_PPNUM:
-    case TOK_STR:
-    case TOK_LSTR:
-        {
-            int nb_words;
-            CString *cstr;
-
-            nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
-            while ((len + nb_words) > s->allocated_len)
-                str = tok_str_realloc(s);
-            cstr = (CString *)(str + len);
-            cstr->data = NULL;
-            cstr->size = cv->cstr->size;
-            cstr->data_allocated = NULL;
-            cstr->size_allocated = cstr->size;
-            memcpy((char *)cstr + sizeof(CString), 
-                   cv->cstr->data, cstr->size);
-            len += nb_words;
-        }
-        break;
-    case TOK_CDOUBLE:
-    case TOK_CLLONG:
-    case TOK_CULLONG:
-#if LDOUBLE_SIZE == 8
-    case TOK_CLDOUBLE:
-#endif
-        str[len++] = cv->tab[0];
-        str[len++] = cv->tab[1];
-        break;
-#if LDOUBLE_SIZE == 12
-    case TOK_CLDOUBLE:
-        str[len++] = cv->tab[0];
-        str[len++] = cv->tab[1];
-        str[len++] = cv->tab[2];
-#elif LDOUBLE_SIZE == 16
-    case TOK_CLDOUBLE:
-        str[len++] = cv->tab[0];
-        str[len++] = cv->tab[1];
-        str[len++] = cv->tab[2];
-        str[len++] = cv->tab[3];
-#elif LDOUBLE_SIZE != 8
-#error add long double size support
-#endif
-        break;
-    default:
-        break;
-    }
-    s->len = len;
-}
-
-/* add the current parse token in token string 's' */
-static void tok_str_add_tok(TokenString *s)
-{
-    CValue cval;
-
-    /* save line number info */
-    if (file->line_num != s->last_line_num) {
-        s->last_line_num = file->line_num;
-        cval.i = s->last_line_num;
-        tok_str_add2(s, TOK_LINENUM, &cval);
-    }
-    tok_str_add2(s, tok, &tokc);
-}
-
-#if LDOUBLE_SIZE == 16
-#define LDOUBLE_GET(p, cv)                      \
-        cv.tab[0] = p[0];                       \
-        cv.tab[1] = p[1];                       \
-        cv.tab[2] = p[2];                       \
-        cv.tab[3] = p[3];
-#elif LDOUBLE_SIZE == 12
-#define LDOUBLE_GET(p, cv)                      \
-        cv.tab[0] = p[0];                       \
-        cv.tab[1] = p[1];                       \
-        cv.tab[2] = p[2];
-#elif LDOUBLE_SIZE == 8
-#define LDOUBLE_GET(p, cv)                      \
-        cv.tab[0] = p[0];                       \
-        cv.tab[1] = p[1];
-#else
-#error add long double size support
-#endif
-
-
-/* get a token from an integer array and increment pointer
-   accordingly. we code it as a macro to avoid pointer aliasing. */
-#define TOK_GET(t, p, cv)                       \
-{                                               \
-    t = *p++;                                   \
-    switch(t) {                                 \
-    case TOK_CINT:                              \
-    case TOK_CUINT:                             \
-    case TOK_CCHAR:                             \
-    case TOK_LCHAR:                             \
-    case TOK_CFLOAT:                            \
-    case TOK_LINENUM:                           \
-        cv.tab[0] = *p++;                       \
-        break;                                  \
-    case TOK_STR:                               \
-    case TOK_LSTR:                              \
-    case TOK_PPNUM:                             \
-        cv.cstr = (CString *)p;                 \
-        cv.cstr->data = (char *)p + sizeof(CString);\
-        p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
-        break;                                  \
-    case TOK_CDOUBLE:                           \
-    case TOK_CLLONG:                            \
-    case TOK_CULLONG:                           \
-        cv.tab[0] = p[0];                       \
-        cv.tab[1] = p[1];                       \
-        p += 2;                                 \
-        break;                                  \
-    case TOK_CLDOUBLE:                          \
-        LDOUBLE_GET(p, cv);                     \
-        p += LDOUBLE_SIZE / 4;                  \
-        break;                                  \
-    default:                                    \
-        break;                                  \
-    }                                           \
-}
-
-/* defines handling */
-static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
-{
-    Sym *s;
-
-    s = sym_push2(&define_stack, v, macro_type, (long)str);
-    s->next = first_arg;
-    table_ident[v - TOK_IDENT]->sym_define = s;
-}
-
-/* undefined a define symbol. Its name is just set to zero */
-static void define_undef(Sym *s)
-{
-    int v;
-    v = s->v;
-    if (v >= TOK_IDENT && v < tok_ident)
-        table_ident[v - TOK_IDENT]->sym_define = NULL;
-    s->v = 0;
-}
-
-static inline Sym *define_find(int v)
-{
-    v -= TOK_IDENT;
-    if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
-        return NULL;
-    return table_ident[v]->sym_define;
-}
-
-/* free define stack until top reaches 'b' */
-static void free_defines(Sym *b)
-{
-    Sym *top, *top1;
-    int v;
-
-    top = define_stack;
-    while (top != b) {
-        top1 = top->prev;
-        /* do not free args or predefined defines */
-        if (top->c)
-            tok_str_free((int *)top->c);
-        v = top->v;
-        if (v >= TOK_IDENT && v < tok_ident)
-            table_ident[v - TOK_IDENT]->sym_define = NULL;
-        sym_free(top);
-        top = top1;
-    }
-    define_stack = b;
-}
-
-/* label lookup */
-static Sym *label_find(int v)
-{
-    v -= TOK_IDENT;
-    if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
-        return NULL;
-    return table_ident[v]->sym_label;
-}
-
-static Sym *label_push(Sym **ptop, int v, int flags)
-{
-    Sym *s, **ps;
-    s = sym_push2(ptop, v, 0, 0);
-    s->r = flags;
-    ps = &table_ident[v - TOK_IDENT]->sym_label;
-    if (ptop == &global_label_stack) {
-        /* modify the top most local identifier, so that
-           sym_identifier will point to 's' when popped */
-        while (*ps != NULL)
-            ps = &(*ps)->prev_tok;
-    }
-    s->prev_tok = *ps;
-    *ps = s;
-    return s;
-}
-
-/* pop labels until element last is reached. Look if any labels are
-   undefined. Define symbols if '&&label' was used. */
-static void label_pop(Sym **ptop, Sym *slast)
-{
-    Sym *s, *s1;
-    for(s = *ptop; s != slast; s = s1) {
-        s1 = s->prev;
-        if (s->r == LABEL_DECLARED) {
-            warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
-        } else if (s->r == LABEL_FORWARD) {
-                error("label '%s' used but not defined",
-                      get_tok_str(s->v, NULL));
-        } else {
-            if (s->c) {
-                /* define corresponding symbol. A size of
-                   1 is put. */
-                put_extern_sym(s, cur_text_section, (long)s->next, 1);
-            }
-        }
-        /* remove label */
-        table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
-        sym_free(s);
-    }
-    *ptop = slast;
-}
-
-/* eval an expression for #if/#elif */
-static int expr_preprocess(void)
-{
-    int c, t;
-    TokenString str;
-    
-    tok_str_new(&str);
-    while (tok != TOK_LINEFEED && tok != TOK_EOF) {
-        next(); /* do macro subst */
-        if (tok == TOK_DEFINED) {
-            next_nomacro();
-            t = tok;
-            if (t == '(') 
-                next_nomacro();
-            c = define_find(tok) != 0;
-            if (t == '(')
-                next_nomacro();
-            tok = TOK_CINT;
-            tokc.i = c;
-        } else if (tok >= TOK_IDENT) {
-            /* if undefined macro */
-            tok = TOK_CINT;
-            tokc.i = 0;
-        }
-        tok_str_add_tok(&str);
-    }
-    tok_str_add(&str, -1); /* simulate end of file */
-    tok_str_add(&str, 0);
-    /* now evaluate C constant expression */
-    macro_ptr = str.str;
-    next();
-    c = expr_const();
-    macro_ptr = NULL;
-    tok_str_free(str.str);
-    return c != 0;
-}
-
-#if defined(PARSE_DEBUG) || defined(PP_DEBUG)
-static void tok_print(int *str)
-{
-    int t;
-    CValue cval;
-
-    printf("<");
-    while (1) {
-        TOK_GET(t, str, cval);
-        if (!t)
-            break;
-        printf("%s", get_tok_str(t, &cval));
-    }
-    printf(">\n");
-}
-#endif
-
-/* parse after #define */
-static void parse_define(void)
-{
-    Sym *s, *first, **ps;
-    int v, t, varg, is_vaargs, spc;
-    TokenString str;
-    
-    v = tok;
-    if (v < TOK_IDENT)
-        error("invalid macro name '%s'", get_tok_str(tok, &tokc));
-    /* XXX: should check if same macro (ANSI) */
-    first = NULL;
-    t = MACRO_OBJ;
-    /* '(' must be just after macro definition for MACRO_FUNC */
-    next_nomacro_spc();
-    if (tok == '(') {
-        next_nomacro();
-        ps = &first;
-        while (tok != ')') {
-            varg = tok;
-            next_nomacro();
-            is_vaargs = 0;
-            if (varg == TOK_DOTS) {
-                varg = TOK___VA_ARGS__;
-                is_vaargs = 1;
-            } else if (tok == TOK_DOTS && gnu_ext) {
-                is_vaargs = 1;
-                next_nomacro();
-            }
-            if (varg < TOK_IDENT)
-                error("badly punctuated parameter list");
-            s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
-            *ps = s;
-            ps = &s->next;
-            if (tok != ',')
-                break;
-            next_nomacro();
-        }
-        if (tok == ')')
-            next_nomacro_spc();
-        t = MACRO_FUNC;
-    }
-    tok_str_new(&str);
-    spc = 2;
-    /* EOF testing necessary for '-D' handling */
-    while (tok != TOK_LINEFEED && tok != TOK_EOF) {
-        /* remove spaces around ## and after '#' */        
-        if (TOK_TWOSHARPS == tok) {
-            if (1 == spc)
-                --str.len;
-            spc = 2;
-        } else if ('#' == tok) {
-            spc = 2;
-        } else if (check_space(tok, &spc)) {
-            goto skip;
-        }
-        tok_str_add2(&str, tok, &tokc);
-    skip:
-        next_nomacro_spc();
-    }
-    if (spc == 1)
-        --str.len; /* remove trailing space */
-    tok_str_add(&str, 0);
-#ifdef PP_DEBUG
-    printf("define %s %d: ", get_tok_str(v, NULL), t);
-    tok_print(str.str);
-#endif
-    define_push(v, t, str.str, first);
-}
-
-static inline int hash_cached_include(int type, const char *filename)
-{
-    const unsigned char *s;
-    unsigned int h;
-
-    h = TOK_HASH_INIT;
-    h = TOK_HASH_FUNC(h, type);
-    s = filename;
-    while (*s) {
-        h = TOK_HASH_FUNC(h, *s);
-        s++;
-    }
-    h &= (CACHED_INCLUDES_HASH_SIZE - 1);
-    return h;
-}
-
-/* XXX: use a token or a hash table to accelerate matching ? */
-static CachedInclude *search_cached_include(TCCState *s1,
-                                            int type, const char *filename)
-{
-    CachedInclude *e;
-    int i, h;
-    h = hash_cached_include(type, filename);
-    i = s1->cached_includes_hash[h];
-    for(;;) {
-        if (i == 0)
-            break;
-        e = s1->cached_includes[i - 1];
-        if (e->type == type && !PATHCMP(e->filename, filename))
-            return e;
-        i = e->hash_next;
-    }
-    return NULL;
-}
-
-static inline void add_cached_include(TCCState *s1, int type, 
-                                      const char *filename, int ifndef_macro)
-{
-    CachedInclude *e;
-    int h;
-
-    if (search_cached_include(s1, type, filename))
-        return;
-#ifdef INC_DEBUG
-    printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
-#endif
-    e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
-    if (!e)
-        return;
-    e->type = type;
-    strcpy(e->filename, filename);
-    e->ifndef_macro = ifndef_macro;
-    dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
-    /* add in hash table */
-    h = hash_cached_include(type, filename);
-    e->hash_next = s1->cached_includes_hash[h];
-    s1->cached_includes_hash[h] = s1->nb_cached_includes;
-}
-
-static void pragma_parse(TCCState *s1)
-{
-    int val;
-
-    next();
-    if (tok == TOK_pack) {
-        /*
-          This may be:
-          #pragma pack(1) // set
-          #pragma pack() // reset to default
-          #pragma pack(push,1) // push & set
-          #pragma pack(pop) // restore previous
-        */
-        next();
-        skip('(');
-        if (tok == TOK_ASM_pop) {
-            next();
-            if (s1->pack_stack_ptr <= s1->pack_stack) {
-            stk_error:
-                error("out of pack stack");
-            }
-            s1->pack_stack_ptr--;
-        } else {
-            val = 0;
-            if (tok != ')') {
-                if (tok == TOK_ASM_push) {
-                    next();
-                    if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
-                        goto stk_error;
-                    s1->pack_stack_ptr++;
-                    skip(',');
-                }
-                if (tok != TOK_CINT) {
-                pack_error:
-                    error("invalid pack pragma");
-                }
-                val = tokc.i;
-                if (val < 1 || val > 16 || (val & (val - 1)) != 0)
-                    goto pack_error;
-                next();
-            }
-            *s1->pack_stack_ptr = val;
-            skip(')');
-        }
-    }
-}
-
-/* is_bof is true if first non space token at beginning of file */
-static void preprocess(int is_bof)
-{
-    TCCState *s1 = tcc_state;
-    int i, c, n, saved_parse_flags;
-    char buf[1024], *q;
-    Sym *s;
-
-    saved_parse_flags = parse_flags;
-    parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | 
-        PARSE_FLAG_LINEFEED;
-    next_nomacro();
- redo:
-    switch(tok) {
-    case TOK_DEFINE:
-        next_nomacro();
-        parse_define();
-        break;
-    case TOK_UNDEF:
-        next_nomacro();
-        s = define_find(tok);
-        /* undefine symbol by putting an invalid name */
-        if (s)
-            define_undef(s);
-        break;
-    case TOK_INCLUDE:
-    case TOK_INCLUDE_NEXT:
-        ch = file->buf_ptr[0];
-        /* XXX: incorrect if comments : use next_nomacro with a special mode */
-        skip_spaces();
-        if (ch == '<') {
-            c = '>';
-            goto read_name;
-        } else if (ch == '\"') {
-            c = ch;
-        read_name:
-            inp();
-            q = buf;
-            while (ch != c && ch != '\n' && ch != CH_EOF) {
-                if ((q - buf) < sizeof(buf) - 1)
-                    *q++ = ch;
-                if (ch == '\\') {
-                    if (handle_stray_noerror() == 0)
-                        --q;
-                } else
-                    inp();
-            }
-            *q = '\0';
-            minp();
-#if 0
-            /* eat all spaces and comments after include */
-            /* XXX: slightly incorrect */
-            while (ch1 != '\n' && ch1 != CH_EOF)
-                inp();
-#endif
-        } else {
-            /* computed #include : either we have only strings or
-               we have anything enclosed in '<>' */
-            next();
-            buf[0] = '\0';
-            if (tok == TOK_STR) {
-                while (tok != TOK_LINEFEED) {
-                    if (tok != TOK_STR) {
-                    include_syntax:
-                        error("'#include' expects \"FILENAME\" or <FILENAME>");
-                    }
-                    pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
-                    next();
-                }
-                c = '\"';
-            } else {
-                int len;
-                while (tok != TOK_LINEFEED) {
-                    pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
-                    next();
-                }
-                len = strlen(buf);
-                /* check syntax and remove '<>' */
-                if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
-                    goto include_syntax;
-                memmove(buf, buf + 1, len - 2);
-                buf[len - 2] = '\0';
-                c = '>';
-            }
-        }
-
-        if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
-            error("#include recursion too deep");
-
-        n = s1->nb_include_paths + s1->nb_sysinclude_paths;
-        for (i = -2; i < n; ++i) {
-            char buf1[sizeof file->filename];
-            BufferedFile *f;
-            CachedInclude *e;
-            const char *path;
-            int size;
-
-            if (i == -2) {
-                /* check absolute include path */
-                if (!IS_ABSPATH(buf))
-                    continue;
-                buf1[0] = 0;
-
-            } else if (i == -1) {
-                /* search in current dir if "header.h" */
-                if (c != '\"')
-                    continue;
-                size = tcc_basename(file->filename) - file->filename;
-                memcpy(buf1, file->filename, size);
-                buf1[size] = '\0';
-
-            } else {
-                /* search in all the include paths */
-                if (i < s1->nb_include_paths)
-                    path = s1->include_paths[i];
-                else
-                    path = s1->sysinclude_paths[i - s1->nb_include_paths];
-                pstrcpy(buf1, sizeof(buf1), path);
-                pstrcat(buf1, sizeof(buf1), "/");
-            }
-
-            pstrcat(buf1, sizeof(buf1), buf);
-
-            e = search_cached_include(s1, c, buf1);
-            if (e && define_find(e->ifndef_macro)) {
-                /* no need to parse the include because the 'ifndef macro'
-                   is defined */
-#ifdef INC_DEBUG
-                printf("%s: skipping %s\n", file->filename, buf);
-#endif
-                f = NULL;
-            }  else {
-                f = tcc_open(s1, buf1);
-                if (!f)
-                    continue;
-            }
-
-            if (tok == TOK_INCLUDE_NEXT) {
-                tok = TOK_INCLUDE;
-                if (f)
-                    tcc_close(f);
-                continue;
-            }
-
-            if (!f)
-                goto include_done;
-
-#ifdef INC_DEBUG
-            printf("%s: including %s\n", file->filename, buf1);
-#endif
-
-           /* XXX: fix current line init */
-           /* push current file in stack */
-            *s1->include_stack_ptr++ = file;
-            f->inc_type = c;
-            pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf1);
-            file = f;
-            /* add include file debug info */
-            if (tcc_state->do_debug) {
-                put_stabs(file->filename, N_BINCL, 0, 0, 0);
-            }
-            tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
-            ch = file->buf_ptr[0];
-            goto the_end;
-        }
-        error("include file '%s' not found", buf);
-include_done:
-        break;
-    case TOK_IFNDEF:
-        c = 1;
-        goto do_ifdef;
-    case TOK_IF:
-        c = expr_preprocess();
-        goto do_if;
-    case TOK_IFDEF:
-        c = 0;
-    do_ifdef:
-        next_nomacro();
-        if (tok < TOK_IDENT)
-            error("invalid argument for '#if%sdef'", c ? "n" : "");
-        if (is_bof) {
-            if (c) {
-#ifdef INC_DEBUG
-                printf("#ifndef %s\n", get_tok_str(tok, NULL));
-#endif
-                file->ifndef_macro = tok;
-            }
-        }
-        c = (define_find(tok) != 0) ^ c;
-    do_if:
-        if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
-            error("memory full");
-        *s1->ifdef_stack_ptr++ = c;
-        goto test_skip;
-    case TOK_ELSE:
-        if (s1->ifdef_stack_ptr == s1->ifdef_stack)
-            error("#else without matching #if");
-        if (s1->ifdef_stack_ptr[-1] & 2)
-            error("#else after #else");
-        c = (s1->ifdef_stack_ptr[-1] ^= 3);
-        goto test_skip;
-    case TOK_ELIF:
-        if (s1->ifdef_stack_ptr == s1->ifdef_stack)
-            error("#elif without matching #if");
-        c = s1->ifdef_stack_ptr[-1];
-        if (c > 1)
-            error("#elif after #else");
-        /* last #if/#elif expression was true: we skip */
-        if (c == 1)
-            goto skip;
-        c = expr_preprocess();
-        s1->ifdef_stack_ptr[-1] = c;
-    test_skip:
-        if (!(c & 1)) {
-        skip:
-            preprocess_skip();
-            is_bof = 0;
-            goto redo;
-        }
-        break;
-    case TOK_ENDIF:
-        if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
-            error("#endif without matching #if");
-        s1->ifdef_stack_ptr--;
-        /* '#ifndef macro' was at the start of file. Now we check if
-           an '#endif' is exactly at the end of file */
-        if (file->ifndef_macro &&
-            s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
-            file->ifndef_macro_saved = file->ifndef_macro;
-            /* need to set to zero to avoid false matches if another
-               #ifndef at middle of file */
-            file->ifndef_macro = 0;
-            while (tok != TOK_LINEFEED)
-                next_nomacro();
-            tok_flags |= TOK_FLAG_ENDIF;
-            goto the_end;
-        }
-        break;
-    case TOK_LINE:
-        next();
-        if (tok != TOK_CINT)
-            error("#line");
-        file->line_num = tokc.i - 1; /* the line number will be incremented after */
-        next();
-        if (tok != TOK_LINEFEED) {
-            if (tok != TOK_STR)
-                error("#line");
-            pstrcpy(file->filename, sizeof(file->filename), 
-                    (char *)tokc.cstr->data);
-        }
-        break;
-    case TOK_ERROR:
-    case TOK_WARNING:
-        c = tok;
-        ch = file->buf_ptr[0];
-        skip_spaces();
-        q = buf;
-        while (ch != '\n' && ch != CH_EOF) {
-            if ((q - buf) < sizeof(buf) - 1)
-                *q++ = ch;
-            if (ch == '\\') {
-                if (handle_stray_noerror() == 0)
-                    --q;
-            } else
-                inp();
-        }
-        *q = '\0';
-        if (c == TOK_ERROR)
-            error("#error %s", buf);
-        else
-            warning("#warning %s", buf);
-        break;
-    case TOK_PRAGMA:
-        pragma_parse(s1);
-        break;
-    default:
-        if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
-            /* '!' is ignored to allow C scripts. numbers are ignored
-               to emulate cpp behaviour */
-        } else {
-            if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
-                warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
-        }
-        break;
-    }
-    /* ignore other preprocess commands or #! for C scripts */
-    while (tok != TOK_LINEFEED)
-        next_nomacro();
- the_end:
-    parse_flags = saved_parse_flags;
-}
-
-/* evaluate escape codes in a string. */
-static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
-{
-    int c, n;
-    const uint8_t *p;
-
-    p = buf;
-    for(;;) {
-        c = *p;
-        if (c == '\0')
-            break;
-        if (c == '\\') {
-            p++;
-            /* escape */
-            c = *p;
-            switch(c) {
-            case '0': case '1': case '2': case '3':
-            case '4': case '5': case '6': case '7':
-                /* at most three octal digits */
-                n = c - '0';
-                p++;
-                c = *p;
-                if (isoct(c)) {
-                    n = n * 8 + c - '0';
-                    p++;
-                    c = *p;
-                    if (isoct(c)) {
-                        n = n * 8 + c - '0';
-                        p++;
-                    }
-                }
-                c = n;
-                goto add_char_nonext;
-            case 'x':
-            case 'u':
-            case 'U':
-                p++;
-                n = 0;
-                for(;;) {
-                    c = *p;
-                    if (c >= 'a' && c <= 'f')
-                        c = c - 'a' + 10;
-                    else if (c >= 'A' && c <= 'F')
-                        c = c - 'A' + 10;
-                    else if (isnum(c))
-                        c = c - '0';
-                    else
-                        break;
-                    n = n * 16 + c;
-                    p++;
-                }
-                c = n;
-                goto add_char_nonext;
-            case 'a':
-                c = '\a';
-                break;
-            case 'b':
-                c = '\b';
-                break;
-            case 'f':
-                c = '\f';
-                break;
-            case 'n':
-                c = '\n';
-                break;
-            case 'r':
-                c = '\r';
-                break;
-            case 't':
-                c = '\t';
-                break;
-            case 'v':
-                c = '\v';
-                break;
-            case 'e':
-                if (!gnu_ext)
-                    goto invalid_escape;
-                c = 27;
-                break;
-            case '\'':
-            case '\"':
-            case '\\': 
-            case '?':
-                break;
-            default:
-            invalid_escape:
-                if (c >= '!' && c <= '~')
-                    warning("unknown escape sequence: \'\\%c\'", c);
-                else
-                    warning("unknown escape sequence: \'\\x%x\'", c);
-                break;
-            }
-        }
-        p++;
-    add_char_nonext:
-        if (!is_long)
-            cstr_ccat(outstr, c);
-        else
-            cstr_wccat(outstr, c);
-    }
-    /* add a trailing '\0' */
-    if (!is_long)
-        cstr_ccat(outstr, '\0');
-    else
-        cstr_wccat(outstr, '\0');
-}
-
-/* we use 64 bit numbers */
-#define BN_SIZE 2
-
-/* bn = (bn << shift) | or_val */
-void bn_lshift(unsigned int *bn, int shift, int or_val)
-{
-    int i;
-    unsigned int v;
-    for(i=0;i<BN_SIZE;i++) {
-        v = bn[i];
-        bn[i] = (v << shift) | or_val;
-        or_val = v >> (32 - shift);
-    }
-}
-
-void bn_zero(unsigned int *bn)
-{
-    int i;
-    for(i=0;i<BN_SIZE;i++) {
-        bn[i] = 0;
-    }
-}
-
-/* parse number in null terminated string 'p' and return it in the
-   current token */
-void parse_number(const char *p)
-{
-    int b, t, shift, frac_bits, s, exp_val, ch;
-    char *q;
-    unsigned int bn[BN_SIZE];
-    double d;
-
-    /* number */
-    q = token_buf;
-    ch = *p++;
-    t = ch;
-    ch = *p++;
-    *q++ = t;
-    b = 10;
-    if (t == '.') {
-        goto float_frac_parse;
-    } else if (t == '0') {
-        if (ch == 'x' || ch == 'X') {
-            q--;
-            ch = *p++;
-            b = 16;
-        } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
-            q--;
-            ch = *p++;
-            b = 2;
-        }
-    }
-    /* parse all digits. cannot check octal numbers at this stage
-       because of floating point constants */
-    while (1) {
-        if (ch >= 'a' && ch <= 'f')
-            t = ch - 'a' + 10;
-        else if (ch >= 'A' && ch <= 'F')
-            t = ch - 'A' + 10;
-        else if (isnum(ch))
-            t = ch - '0';
-        else
-            break;
-        if (t >= b)
-            break;
-        if (q >= token_buf + STRING_MAX_SIZE) {
-        num_too_long:
-            error("number too long");
-        }
-        *q++ = ch;
-        ch = *p++;
-    }
-    if (ch == '.' ||
-        ((ch == 'e' || ch == 'E') && b == 10) ||
-        ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
-        if (b != 10) {
-            /* NOTE: strtox should support that for hexa numbers, but
-               non ISOC99 libcs do not support it, so we prefer to do
-               it by hand */
-            /* hexadecimal or binary floats */
-            /* XXX: handle overflows */
-            *q = '\0';
-            if (b == 16)
-                shift = 4;
-            else 
-                shift = 2;
-            bn_zero(bn);
-            q = token_buf;
-            while (1) {
-                t = *q++;
-                if (t == '\0') {
-                    break;
-                } else if (t >= 'a') {
-                    t = t - 'a' + 10;
-                } else if (t >= 'A') {
-                    t = t - 'A' + 10;
-                } else {
-                    t = t - '0';
-                }
-                bn_lshift(bn, shift, t);
-            }
-            frac_bits = 0;
-            if (ch == '.') {
-                ch = *p++;
-                while (1) {
-                    t = ch;
-                    if (t >= 'a' && t <= 'f') {
-                        t = t - 'a' + 10;
-                    } else if (t >= 'A' && t <= 'F') {
-                        t = t - 'A' + 10;
-                    } else if (t >= '0' && t <= '9') {
-                        t = t - '0';
-                    } else {
-                        break;
-                    }
-                    if (t >= b)
-                        error("invalid digit");
-                    bn_lshift(bn, shift, t);
-                    frac_bits += shift;
-                    ch = *p++;
-                }
-            }
-            if (ch != 'p' && ch != 'P')
-                expect("exponent");
-            ch = *p++;
-            s = 1;
-            exp_val = 0;
-            if (ch == '+') {
-                ch = *p++;
-            } else if (ch == '-') {
-                s = -1;
-                ch = *p++;
-            }
-            if (ch < '0' || ch > '9')
-                expect("exponent digits");
-            while (ch >= '0' && ch <= '9') {
-                exp_val = exp_val * 10 + ch - '0';
-                ch = *p++;
-            }
-            exp_val = exp_val * s;
-            
-            /* now we can generate the number */
-            /* XXX: should patch directly float number */
-            d = (double)bn[1] * 4294967296.0 + (double)bn[0];
-            d = ldexp(d, exp_val - frac_bits);
-            t = toup(ch);
-            if (t == 'F') {
-                ch = *p++;
-                tok = TOK_CFLOAT;
-                /* float : should handle overflow */
-                tokc.f = (float)d;
-            } else if (t == 'L') {
-                ch = *p++;
-                tok = TOK_CLDOUBLE;
-                /* XXX: not large enough */
-                tokc.ld = (long double)d;
-            } else {
-                tok = TOK_CDOUBLE;
-                tokc.d = d;
-            }
-        } else {
-            /* decimal floats */
-            if (ch == '.') {
-                if (q >= token_buf + STRING_MAX_SIZE)
-                    goto num_too_long;
-                *q++ = ch;
-                ch = *p++;
-            float_frac_parse:
-                while (ch >= '0' && ch <= '9') {
-                    if (q >= token_buf + STRING_MAX_SIZE)
-                        goto num_too_long;
-                    *q++ = ch;
-                    ch = *p++;
-                }
-            }
-            if (ch == 'e' || ch == 'E') {
-                if (q >= token_buf + STRING_MAX_SIZE)
-                    goto num_too_long;
-                *q++ = ch;
-                ch = *p++;
-                if (ch == '-' || ch == '+') {
-                    if (q >= token_buf + STRING_MAX_SIZE)
-                        goto num_too_long;
-                    *q++ = ch;
-                    ch = *p++;
-                }
-                if (ch < '0' || ch > '9')
-                    expect("exponent digits");
-                while (ch >= '0' && ch <= '9') {
-                    if (q >= token_buf + STRING_MAX_SIZE)
-                        goto num_too_long;
-                    *q++ = ch;
-                    ch = *p++;
-                }
-            }
-            *q = '\0';
-            t = toup(ch);
-            errno = 0;
-            if (t == 'F') {
-                ch = *p++;
-                tok = TOK_CFLOAT;
-                tokc.f = strtof(token_buf, NULL);
-            } else if (t == 'L') {
-                ch = *p++;
-                tok = TOK_CLDOUBLE;
-                tokc.ld = strtold(token_buf, NULL);
-            } else {
-                tok = TOK_CDOUBLE;
-                tokc.d = strtod(token_buf, NULL);
-            }
-        }
-    } else {
-        unsigned long long n, n1;
-        int lcount, ucount;
-
-        /* integer number */
-        *q = '\0';
-        q = token_buf;
-        if (b == 10 && *q == '0') {
-            b = 8;
-            q++;
-        }
-        n = 0;
-        while(1) {
-            t = *q++;
-            /* no need for checks except for base 10 / 8 errors */
-            if (t == '\0') {
-                break;
-            } else if (t >= 'a') {
-                t = t - 'a' + 10;
-            } else if (t >= 'A') {
-                t = t - 'A' + 10;
-            } else {
-                t = t - '0';
-                if (t >= b)
-                    error("invalid digit");
-            }
-            n1 = n;
-            n = n * b + t;
-            /* detect overflow */
-            /* XXX: this test is not reliable */
-            if (n < n1)
-                error("integer constant overflow");
-        }
-        
-        /* XXX: not exactly ANSI compliant */
-        if ((n & 0xffffffff00000000LL) != 0) {
-            if ((n >> 63) != 0)
-                tok = TOK_CULLONG;
-            else
-                tok = TOK_CLLONG;
-        } else if (n > 0x7fffffff) {
-            tok = TOK_CUINT;
-        } else {
-            tok = TOK_CINT;
-        }
-        lcount = 0;
-        ucount = 0;
-        for(;;) {
-            t = toup(ch);
-            if (t == 'L') {
-                if (lcount >= 2)
-                    error("three 'l's in integer constant");
-                lcount++;
-                if (lcount == 2) {
-                    if (tok == TOK_CINT)
-                        tok = TOK_CLLONG;
-                    else if (tok == TOK_CUINT)
-                        tok = TOK_CULLONG;
-                }
-                ch = *p++;
-            } else if (t == 'U') {
-                if (ucount >= 1)
-                    error("two 'u's in integer constant");
-                ucount++;
-                if (tok == TOK_CINT)
-                    tok = TOK_CUINT;
-                else if (tok == TOK_CLLONG)
-                    tok = TOK_CULLONG;
-                ch = *p++;
-            } else {
-                break;
-            }
-        }
-        if (tok == TOK_CINT || tok == TOK_CUINT)
-            tokc.ui = n;
-        else
-            tokc.ull = n;
-    }
-    if (ch)
-        error("invalid number\n");
-}
-
-
-#define PARSE2(c1, tok1, c2, tok2)              \
-    case c1:                                    \
-        PEEKC(c, p);                            \
-        if (c == c2) {                          \
-            p++;                                \
-            tok = tok2;                         \
-        } else {                                \
-            tok = tok1;                         \
-        }                                       \
-        break;
-
-/* return next token without macro substitution */
-static inline void next_nomacro1(void)
-{
-    int t, c, is_long;
-    TokenSym *ts;
-    uint8_t *p, *p1;
-    unsigned int h;
-
-    p = file->buf_ptr;
- redo_no_start:
-    c = *p;
-    switch(c) {
-    case ' ':
-    case '\t':
-        tok = c;
-        p++;
-        goto keep_tok_flags;
-    case '\f':
-    case '\v':
-    case '\r':
-        p++;
-        goto redo_no_start;
-    case '\\':
-        /* first look if it is in fact an end of buffer */
-        if (p >= file->buf_end) {
-            file->buf_ptr = p;
-            handle_eob();
-            p = file->buf_ptr;
-            if (p >= file->buf_end)
-                goto parse_eof;
-            else
-                goto redo_no_start;
-        } else {
-            file->buf_ptr = p;
-            ch = *p;
-            handle_stray();
-            p = file->buf_ptr;
-            goto redo_no_start;
-        }
-    parse_eof:
-        {
-            TCCState *s1 = tcc_state;
-            if ((parse_flags & PARSE_FLAG_LINEFEED)
-                && !(tok_flags & TOK_FLAG_EOF)) {
-                tok_flags |= TOK_FLAG_EOF;
-                tok = TOK_LINEFEED;
-                goto keep_tok_flags;
-            } else if (s1->include_stack_ptr == s1->include_stack ||
-                       !(parse_flags & PARSE_FLAG_PREPROCESS)) {
-                /* no include left : end of file. */
-                tok = TOK_EOF;
-            } else {
-                tok_flags &= ~TOK_FLAG_EOF;
-                /* pop include file */
-                
-                /* test if previous '#endif' was after a #ifdef at
-                   start of file */
-                if (tok_flags & TOK_FLAG_ENDIF) {
-#ifdef INC_DEBUG
-                    printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
-#endif
-                    add_cached_include(s1, file->inc_type, file->inc_filename,
-                                       file->ifndef_macro_saved);
-                }
-
-                /* add end of include file debug info */
-                if (tcc_state->do_debug) {
-                    put_stabd(N_EINCL, 0, 0);
-                }
-                /* pop include stack */
-                tcc_close(file);
-                s1->include_stack_ptr--;
-                file = *s1->include_stack_ptr;
-                p = file->buf_ptr;
-                goto redo_no_start;
-            }
-        }
-        break;
-
-    case '\n':
-        file->line_num++;
-        tok_flags |= TOK_FLAG_BOL;
-        p++;
-        if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
-            goto redo_no_start;
-        tok = TOK_LINEFEED;
-        goto keep_tok_flags;
-
-    case '#':
-        /* XXX: simplify */
-        PEEKC(c, p);
-        if ((tok_flags & TOK_FLAG_BOL) && 
-            (parse_flags & PARSE_FLAG_PREPROCESS)) {
-            file->buf_ptr = p;
-            preprocess(tok_flags & TOK_FLAG_BOF);
-            p = file->buf_ptr;
-            goto redo_no_start;
-        } else {
-            if (c == '#') {
-                p++;
-                tok = TOK_TWOSHARPS;
-            } else {
-                if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
-                    p = parse_line_comment(p - 1);
-                    goto redo_no_start;
-                } else {
-                    tok = '#';
-                }
-            }
-        }
-        break;
-
-    case 'a': case 'b': case 'c': case 'd':
-    case 'e': case 'f': case 'g': case 'h':
-    case 'i': case 'j': case 'k': case 'l':
-    case 'm': case 'n': case 'o': case 'p':
-    case 'q': case 'r': case 's': case 't':
-    case 'u': case 'v': case 'w': case 'x':
-    case 'y': case 'z': 
-    case 'A': case 'B': case 'C': case 'D':
-    case 'E': case 'F': case 'G': case 'H':
-    case 'I': case 'J': case 'K': 
-    case 'M': case 'N': case 'O': case 'P':
-    case 'Q': case 'R': case 'S': case 'T':
-    case 'U': case 'V': case 'W': case 'X':
-    case 'Y': case 'Z': 
-    case '_':
-    parse_ident_fast:
-        p1 = p;
-        h = TOK_HASH_INIT;
-        h = TOK_HASH_FUNC(h, c);
-        p++;
-        for(;;) {
-            c = *p;
-            if (!isidnum_table[c-CH_EOF])
-                break;
-            h = TOK_HASH_FUNC(h, c);
-            p++;
-        }
-        if (c != '\\') {
-            TokenSym **pts;
-            int len;
-
-            /* fast case : no stray found, so we have the full token
-               and we have already hashed it */
-            len = p - p1;
-            h &= (TOK_HASH_SIZE - 1);
-            pts = &hash_ident[h];
-            for(;;) {
-                ts = *pts;
-                if (!ts)
-                    break;
-                if (ts->len == len && !memcmp(ts->str, p1, len))
-                    goto token_found;
-                pts = &(ts->hash_next);
-            }
-            ts = tok_alloc_new(pts, p1, len);
-        token_found: ;
-        } else {
-            /* slower case */
-            cstr_reset(&tokcstr);
-
-            while (p1 < p) {
-                cstr_ccat(&tokcstr, *p1);
-                p1++;
-            }
-            p--;
-            PEEKC(c, p);
-        parse_ident_slow:
-            while (isidnum_table[c-CH_EOF]) {
-                cstr_ccat(&tokcstr, c);
-                PEEKC(c, p);
-            }
-            ts = tok_alloc(tokcstr.data, tokcstr.size);
-        }
-        tok = ts->tok;
-        break;
-    case 'L':
-        t = p[1];
-        if (t != '\\' && t != '\'' && t != '\"') {
-            /* fast case */
-            goto parse_ident_fast;
-        } else {
-            PEEKC(c, p);
-            if (c == '\'' || c == '\"') {
-                is_long = 1;
-                goto str_const;
-            } else {
-                cstr_reset(&tokcstr);
-                cstr_ccat(&tokcstr, 'L');
-                goto parse_ident_slow;
-            }
-        }
-        break;
-    case '0': case '1': case '2': case '3':
-    case '4': case '5': case '6': case '7':
-    case '8': case '9':
-
-        cstr_reset(&tokcstr);
-        /* after the first digit, accept digits, alpha, '.' or sign if
-           prefixed by 'eEpP' */
-    parse_num:
-        for(;;) {
-            t = c;
-            cstr_ccat(&tokcstr, c);
-            PEEKC(c, p);
-            if (!(isnum(c) || isid(c) || c == '.' ||
-                  ((c == '+' || c == '-') && 
-                   (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
-                break;
-        }
-        /* We add a trailing '\0' to ease parsing */
-        cstr_ccat(&tokcstr, '\0');
-        tokc.cstr = &tokcstr;
-        tok = TOK_PPNUM;
-        break;
-    case '.':
-        /* special dot handling because it can also start a number */
-        PEEKC(c, p);
-        if (isnum(c)) {
-            cstr_reset(&tokcstr);
-            cstr_ccat(&tokcstr, '.');
-            goto parse_num;
-        } else if (c == '.') {
-            PEEKC(c, p);
-            if (c != '.')
-                expect("'.'");
-            PEEKC(c, p);
-            tok = TOK_DOTS;
-        } else {
-            tok = '.';
-        }
-        break;
-    case '\'':
-    case '\"':
-        is_long = 0;
-    str_const:
-        {
-            CString str;
-            int sep;
-
-            sep = c;
-
-            /* parse the string */
-            cstr_new(&str);
-            p = parse_pp_string(p, sep, &str);
-            cstr_ccat(&str, '\0');
-            
-            /* eval the escape (should be done as TOK_PPNUM) */
-            cstr_reset(&tokcstr);
-            parse_escape_string(&tokcstr, str.data, is_long);
-            cstr_free(&str);
-
-            if (sep == '\'') {
-                int char_size;
-                /* XXX: make it portable */
-                if (!is_long)
-                    char_size = 1;
-                else
-                    char_size = sizeof(nwchar_t);
-                if (tokcstr.size <= char_size)
-                    error("empty character constant");
-                if (tokcstr.size > 2 * char_size)
-                    warning("multi-character character constant");
-                if (!is_long) {
-                    tokc.i = *(int8_t *)tokcstr.data;
-                    tok = TOK_CCHAR;
-                } else {
-                    tokc.i = *(nwchar_t *)tokcstr.data;
-                    tok = TOK_LCHAR;
-                }
-            } else {
-                tokc.cstr = &tokcstr;
-                if (!is_long)
-                    tok = TOK_STR;
-                else
-                    tok = TOK_LSTR;
-            }
-        }
-        break;
-
-    case '<':
-        PEEKC(c, p);
-        if (c == '=') {
-            p++;
-            tok = TOK_LE;
-        } else if (c == '<') {
-            PEEKC(c, p);
-            if (c == '=') {
-                p++;
-                tok = TOK_A_SHL;
-            } else {
-                tok = TOK_SHL;
-            }
-        } else {
-            tok = TOK_LT;
-        }
-        break;
-        
-    case '>':
-        PEEKC(c, p);
-        if (c == '=') {
-            p++;
-            tok = TOK_GE;
-        } else if (c == '>') {
-            PEEKC(c, p);
-            if (c == '=') {
-                p++;
-                tok = TOK_A_SAR;
-            } else {
-                tok = TOK_SAR;
-            }
-        } else {
-            tok = TOK_GT;
-        }
-        break;
-        
-    case '&':
-        PEEKC(c, p);
-        if (c == '&') {
-            p++;
-            tok = TOK_LAND;
-        } else if (c == '=') {
-            p++;
-            tok = TOK_A_AND;
-        } else {
-            tok = '&';
-        }
-        break;
-        
-    case '|':
-        PEEKC(c, p);
-        if (c == '|') {
-            p++;
-            tok = TOK_LOR;
-        } else if (c == '=') {
-            p++;
-            tok = TOK_A_OR;
-        } else {
-            tok = '|';
-        }
-        break;
-
-    case '+':
-        PEEKC(c, p);
-        if (c == '+') {
-            p++;
-            tok = TOK_INC;
-        } else if (c == '=') {
-            p++;
-            tok = TOK_A_ADD;
-        } else {
-            tok = '+';
-        }
-        break;
-        
-    case '-':
-        PEEKC(c, p);
-        if (c == '-') {
-            p++;
-            tok = TOK_DEC;
-        } else if (c == '=') {
-            p++;
-            tok = TOK_A_SUB;
-        } else if (c == '>') {
-            p++;
-            tok = TOK_ARROW;
-        } else {
-            tok = '-';
-        }
-        break;
-
-    PARSE2('!', '!', '=', TOK_NE)
-    PARSE2('=', '=', '=', TOK_EQ)
-    PARSE2('*', '*', '=', TOK_A_MUL)
-    PARSE2('%', '%', '=', TOK_A_MOD)
-    PARSE2('^', '^', '=', TOK_A_XOR)
-        
-        /* comments or operator */
-    case '/':
-        PEEKC(c, p);
-        if (c == '*') {
-            p = parse_comment(p);
-            goto redo_no_start;
-        } else if (c == '/') {
-            p = parse_line_comment(p);
-            goto redo_no_start;
-        } else if (c == '=') {
-            p++;
-            tok = TOK_A_DIV;
-        } else {
-            tok = '/';
-        }
-        break;
-        
-        /* simple tokens */
-    case '(':
-    case ')':
-    case '[':
-    case ']':
-    case '{':
-    case '}':
-    case ',':
-    case ';':
-    case ':':
-    case '?':
-    case '~':
-    case '$': /* only used in assembler */
-    case '@': /* dito */
-        tok = c;
-        p++;
-        break;
-    default:
-        error("unrecognized character \\x%02x", c);
-        break;
-    }
-    tok_flags = 0;
-keep_tok_flags:
-    file->buf_ptr = p;
-#if defined(PARSE_DEBUG)
-    printf("token = %s\n", get_tok_str(tok, &tokc));
-#endif
-}
-
-/* return next token without macro substitution. Can read input from
-   macro_ptr buffer */
-static void next_nomacro_spc(void)
-{
-    if (macro_ptr) {
-    redo:
-        tok = *macro_ptr;
-        if (tok) {
-            TOK_GET(tok, macro_ptr, tokc);
-            if (tok == TOK_LINENUM) {
-                file->line_num = tokc.i;
-                goto redo;
-            }
-        }
-    } else {
-        next_nomacro1();
-    }
-}
-
-static void next_nomacro(void)
-{
-    do {
-        next_nomacro_spc();
-    } while (is_space(tok));
-}
- 
-/* substitute args in macro_str and return allocated string */
-static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
-{
-    int *st, last_tok, t, spc;
-    Sym *s;
-    CValue cval;
-    TokenString str;
-    CString cstr;
-
-    tok_str_new(&str);
-    last_tok = 0;
-    while(1) {
-        TOK_GET(t, macro_str, cval);
-        if (!t)
-            break;
-        if (t == '#') {
-            /* stringize */
-            TOK_GET(t, macro_str, cval);
-            if (!t)
-                break;
-            s = sym_find2(args, t);
-            if (s) {
-                cstr_new(&cstr);
-                st = (int *)s->c;
-                spc = 0;
-                while (*st) {
-                    TOK_GET(t, st, cval);
-                    if (!check_space(t, &spc))
-                        cstr_cat(&cstr, get_tok_str(t, &cval));
-                }
-                cstr.size -= spc;
-                cstr_ccat(&cstr, '\0');
-#ifdef PP_DEBUG
-                printf("stringize: %s\n", (char *)cstr.data);
-#endif
-                /* add string */
-                cval.cstr = &cstr;
-                tok_str_add2(&str, TOK_STR, &cval);
-                cstr_free(&cstr);
-            } else {
-                tok_str_add2(&str, t, &cval);
-            }
-        } else if (t >= TOK_IDENT) {
-            s = sym_find2(args, t);
-            if (s) {
-                st = (int *)s->c;
-                /* if '##' is present before or after, no arg substitution */
-                if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
-                    /* special case for var arg macros : ## eats the
-                       ',' if empty VA_ARGS variable. */
-                    /* XXX: test of the ',' is not 100%
-                       reliable. should fix it to avoid security
-                       problems */
-                    if (gnu_ext && s->type.t &&
-                        last_tok == TOK_TWOSHARPS && 
-                        str.len >= 2 && str.str[str.len - 2] == ',') {
-                        if (*st == 0) {
-                            /* suppress ',' '##' */
-                            str.len -= 2;
-                        } else {
-                            /* suppress '##' and add variable */
-                            str.len--;
-                            goto add_var;
-                        }
-                    } else {
-                        int t1;
-                    add_var:
-                        for(;;) {
-                            TOK_GET(t1, st, cval);
-                            if (!t1)
-                                break;
-                            tok_str_add2(&str, t1, &cval);
-                        }
-                    }
-                } else {
-                    /* NOTE: the stream cannot be read when macro
-                       substituing an argument */
-                    macro_subst(&str, nested_list, st, NULL);
-                }
-            } else {
-                tok_str_add(&str, t);
-            }
-        } else {
-            tok_str_add2(&str, t, &cval);
-        }
-        last_tok = t;
-    }
-    tok_str_add(&str, 0);
-    return str.str;
-}
-
-static char const ab_month_name[12][4] =
-{
-    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-/* do macro substitution of current token with macro 's' and add
-   result to (tok_str,tok_len). 'nested_list' is the list of all
-   macros we got inside to avoid recursing. Return non zero if no
-   substitution needs to be done */
-static int macro_subst_tok(TokenString *tok_str,
-                           Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
-{
-    Sym *args, *sa, *sa1;
-    int mstr_allocated, parlevel, *mstr, t, t1, *p, spc;
-    TokenString str;
-    char *cstrval;
-    CValue cval;
-    CString cstr;
-    char buf[32];
-    
-    /* if symbol is a macro, prepare substitution */
-    /* special macros */
-    if (tok == TOK___LINE__) {
-        snprintf(buf, sizeof(buf), "%d", file->line_num);
-        cstrval = buf;
-        t1 = TOK_PPNUM;
-        goto add_cstr1;
-    } else if (tok == TOK___FILE__) {
-        cstrval = file->filename;
-        goto add_cstr;
-    } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
-        time_t ti;
-        struct tm *tm;
-
-        time(&ti);
-        tm = localtime(&ti);
-        if (tok == TOK___DATE__) {
-            snprintf(buf, sizeof(buf), "%s %2d %d", 
-                     ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
-        } else {
-            snprintf(buf, sizeof(buf), "%02d:%02d:%02d", 
-                     tm->tm_hour, tm->tm_min, tm->tm_sec);
-        }
-        cstrval = buf;
-    add_cstr:
-        t1 = TOK_STR;
-    add_cstr1:
-        cstr_new(&cstr);
-        cstr_cat(&cstr, cstrval);
-        cstr_ccat(&cstr, '\0');
-        cval.cstr = &cstr;
-        tok_str_add2(tok_str, t1, &cval);
-        cstr_free(&cstr);
-    } else {
-        mstr = (int *)s->c;
-        mstr_allocated = 0;
-        if (s->type.t == MACRO_FUNC) {
-            /* NOTE: we do not use next_nomacro to avoid eating the
-               next token. XXX: find better solution */
-        redo:
-            if (macro_ptr) {
-                p = macro_ptr;
-                while (is_space(t = *p) || TOK_LINEFEED == t) 
-                    ++p;
-                if (t == 0 && can_read_stream) {
-                    /* end of macro stream: we must look at the token
-                       after in the file */
-                    struct macro_level *ml = *can_read_stream;
-                    macro_ptr = NULL;
-                    if (ml)
-                    {
-                        macro_ptr = ml->p;
-                        ml->p = NULL;
-                        *can_read_stream = ml -> prev;
-                    }
-                    goto redo;
-                }
-            } else {
-                /* XXX: incorrect with comments */
-                ch = file->buf_ptr[0];
-                while (is_space(ch) || ch == '\n')
-                    cinp();
-                t = ch;
-            }
-            if (t != '(') /* no macro subst */
-                return -1;
-                    
-            /* argument macro */
-            next_nomacro();
-            next_nomacro();
-            args = NULL;
-            sa = s->next;
-            /* NOTE: empty args are allowed, except if no args */
-            for(;;) {
-                /* handle '()' case */
-                if (!args && !sa && tok == ')')
-                    break;
-                if (!sa)
-                    error("macro '%s' used with too many args",
-                          get_tok_str(s->v, 0));
-                tok_str_new(&str);
-                parlevel = spc = 0;
-                /* NOTE: non zero sa->t indicates VA_ARGS */
-                while ((parlevel > 0 || 
-                        (tok != ')' && 
-                         (tok != ',' || sa->type.t))) && 
-                       tok != -1) {
-                    if (tok == '(')
-                        parlevel++;
-                    else if (tok == ')')
-                        parlevel--;
-                    if (tok == TOK_LINEFEED)
-                        tok = ' ';
-                    if (!check_space(tok, &spc))
-                        tok_str_add2(&str, tok, &tokc);
-                    next_nomacro_spc();
-                }
-                str.len -= spc;
-                tok_str_add(&str, 0);
-                sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
-                sa = sa->next;
-                if (tok == ')') {
-                    /* special case for gcc var args: add an empty
-                       var arg argument if it is omitted */
-                    if (sa && sa->type.t && gnu_ext)
-                        continue;
-                    else
-                        break;
-                }
-                if (tok != ',')
-                    expect(",");
-                next_nomacro();
-            }
-            if (sa) {
-                error("macro '%s' used with too few args",
-                      get_tok_str(s->v, 0));
-            }
-
-            /* now subst each arg */
-            mstr = macro_arg_subst(nested_list, mstr, args);
-            /* free memory */
-            sa = args;
-            while (sa) {
-                sa1 = sa->prev;
-                tok_str_free((int *)sa->c);
-                sym_free(sa);
-                sa = sa1;
-            }
-            mstr_allocated = 1;
-        }
-        sym_push2(nested_list, s->v, 0, 0);
-        macro_subst(tok_str, nested_list, mstr, can_read_stream);
-        /* pop nested defined symbol */
-        sa1 = *nested_list;
-        *nested_list = sa1->prev;
-        sym_free(sa1);
-        if (mstr_allocated)
-            tok_str_free(mstr);
-    }
-    return 0;
-}
-
-/* handle the '##' operator. Return NULL if no '##' seen. Otherwise
-   return the resulting string (which must be freed). */
-static inline int *macro_twosharps(const int *macro_str)
-{
-    TokenSym *ts;
-    const int *ptr, *saved_macro_ptr;
-    int t;
-    const char *p1, *p2;
-    CValue cval;
-    TokenString macro_str1;
-    CString cstr;
-
-    /* we search the first '##' */
-    for(ptr = macro_str;;) {
-        TOK_GET(t, ptr, cval);
-        if (t == TOK_TWOSHARPS)
-            break;
-        /* nothing more to do if end of string */
-        if (t == 0)
-            return NULL;
-    }
-
-    /* we saw '##', so we need more processing to handle it */
-    cstr_new(&cstr);
-    tok_str_new(&macro_str1);
-    saved_macro_ptr = macro_ptr;
-    /* XXX: get rid of the use of macro_ptr here */
-    macro_ptr = (int *)macro_str;
-    for(;;) {
-        next_nomacro_spc();
-        if (tok == 0)
-            break;
-        if (tok == TOK_TWOSHARPS)
-            continue;
-        while (*macro_ptr == TOK_TWOSHARPS) {
-            t = *++macro_ptr;
-            if (t && t != TOK_TWOSHARPS) {
-                TOK_GET(t, macro_ptr, cval);
-                /* We concatenate the two tokens if we have an
-                   identifier or a preprocessing number */
-                cstr_reset(&cstr);
-                p1 = get_tok_str(tok, &tokc);
-                cstr_cat(&cstr, p1);
-                p2 = get_tok_str(t, &cval);
-                cstr_cat(&cstr, p2);
-                cstr_ccat(&cstr, '\0');
-
-                if ((tok >= TOK_IDENT || tok == TOK_PPNUM) && 
-                    (t >= TOK_IDENT || t == TOK_PPNUM)) {
-                    if (tok == TOK_PPNUM) {
-                        /* if number, then create a number token */
-                        /* NOTE: no need to allocate because
-                           tok_str_add2() does it */
-                        cstr_reset(&tokcstr);
-                        tokcstr = cstr;
-                        cstr_new(&cstr);
-                        tokc.cstr = &tokcstr;
-                    } else {
-                        /* if identifier, we must do a test to
-                           validate we have a correct identifier */
-                        if (t == TOK_PPNUM) {
-                            const char *p;
-                            int c;
-
-                            p = p2;
-                            for(;;) {
-                                c = *p;
-                                if (c == '\0')
-                                    break;
-                                p++;
-                                if (!isnum(c) && !isid(c))
-                                    goto error_pasting;
-                            }
-                        }
-                        ts = tok_alloc(cstr.data, strlen(cstr.data));
-                        tok = ts->tok; /* modify current token */
-                    }
-                } else {
-                    const char *str = cstr.data;
-                    const unsigned char *q;
-
-                    /* we look for a valid token */
-                    /* XXX: do more extensive checks */
-                    if (!strcmp(str, ">>=")) {
-                        tok = TOK_A_SAR;
-                    } else if (!strcmp(str, "<<=")) {
-                        tok = TOK_A_SHL;
-                    } else if (strlen(str) == 2) {
-                        /* search in two bytes table */
-                        q = tok_two_chars;
-                        for(;;) {
-                            if (!*q)
-                                goto error_pasting;
-                            if (q[0] == str[0] && q[1] == str[1])
-                                break;
-                            q += 3;
-                        }
-                        tok = q[2];
-                    } else {
-                    error_pasting:
-                        /* NOTE: because get_tok_str use a static buffer,
-                           we must save it */
-                        cstr_reset(&cstr);
-                        p1 = get_tok_str(tok, &tokc);
-                        cstr_cat(&cstr, p1);
-                        cstr_ccat(&cstr, '\0');
-                        p2 = get_tok_str(t, &cval);
-                        warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
-                        /* cannot merge tokens: just add them separately */
-                        tok_str_add2(&macro_str1, tok, &tokc);
-                        /* XXX: free associated memory ? */
-                        tok = t;
-                        tokc = cval;
-                    }
-                }
-            }
-        }
-        tok_str_add2(&macro_str1, tok, &tokc);
-    }
-    macro_ptr = (int *)saved_macro_ptr;
-    cstr_free(&cstr);
-    tok_str_add(&macro_str1, 0);
-    return macro_str1.str;
-}
-
-
-/* do macro substitution of macro_str and add result to
-   (tok_str,tok_len). 'nested_list' is the list of all macros we got
-   inside to avoid recursing. */
-static void macro_subst(TokenString *tok_str, Sym **nested_list, 
-                        const int *macro_str, struct macro_level ** can_read_stream)
-{
-    Sym *s;
-    int *macro_str1;
-    const int *ptr;
-    int t, ret, spc;
-    CValue cval;
-    struct macro_level ml;
-    
-    /* first scan for '##' operator handling */
-    ptr = macro_str;
-    macro_str1 = macro_twosharps(ptr);
-    if (macro_str1) 
-        ptr = macro_str1;
-    spc = 0;
-    while (1) {
-        /* NOTE: ptr == NULL can only happen if tokens are read from
-           file stream due to a macro function call */
-        if (ptr == NULL)
-            break;
-        TOK_GET(t, ptr, cval);
-        if (t == 0)
-            break;
-        s = define_find(t);
-        if (s != NULL) {
-            /* if nested substitution, do nothing */
-            if (sym_find2(*nested_list, t))
-                goto no_subst;
-            ml.p = macro_ptr;
-            if (can_read_stream)
-                ml.prev = *can_read_stream, *can_read_stream = &ml;
-            macro_ptr = (int *)ptr;
-            tok = t;
-            ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
-            ptr = (int *)macro_ptr;
-            macro_ptr = ml.p;
-            if (can_read_stream && *can_read_stream == &ml)
-                *can_read_stream = ml.prev;
-            if (ret != 0)
-                goto no_subst;
-        } else {
-        no_subst:
-            if (!check_space(t, &spc)) 
-                tok_str_add2(tok_str, t, &cval);
-        }
-    }
-    if (macro_str1)
-        tok_str_free(macro_str1);
-}
-
-/* return next token with macro substitution */
-static void next(void)
-{
-    Sym *nested_list, *s;
-    TokenString str;
-    struct macro_level *ml;
-
- redo:
-    if (parse_flags & PARSE_FLAG_SPACES)
-        next_nomacro_spc();
-    else
-        next_nomacro();
-    if (!macro_ptr) {
-        /* if not reading from macro substituted string, then try
-           to substitute macros */
-        if (tok >= TOK_IDENT &&
-            (parse_flags & PARSE_FLAG_PREPROCESS)) {
-            s = define_find(tok);
-            if (s) {
-                /* we have a macro: we try to substitute */
-                tok_str_new(&str);
-                nested_list = NULL;
-                ml = NULL;
-                if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
-                    /* substitution done, NOTE: maybe empty */
-                    tok_str_add(&str, 0);
-                    macro_ptr = str.str;
-                    macro_ptr_allocated = str.str;
-                    goto redo;
-                }
-            }
-        }
-    } else {
-        if (tok == 0) {
-            /* end of macro or end of unget buffer */
-            if (unget_buffer_enabled) {
-                macro_ptr = unget_saved_macro_ptr;
-                unget_buffer_enabled = 0;
-            } else {
-                /* end of macro string: free it */
-                tok_str_free(macro_ptr_allocated);
-                macro_ptr = NULL;
-            }
-            goto redo;
-        }
-    }
-    
-    /* convert preprocessor tokens into C tokens */
-    if (tok == TOK_PPNUM &&
-        (parse_flags & PARSE_FLAG_TOK_NUM)) {
-        parse_number((char *)tokc.cstr->data);
-    }
-}
-
-/* push back current token and set current token to 'last_tok'. Only
-   identifier case handled for labels. */
-static inline void unget_tok(int last_tok)
-{
-    int i, n;
-    int *q;
-    unget_saved_macro_ptr = macro_ptr;
-    unget_buffer_enabled = 1;
-    q = unget_saved_buffer;
-    macro_ptr = q;
-    *q++ = tok;
-    n = tok_ext_size(tok) - 1;
-    for(i=0;i<n;i++)
-        *q++ = tokc.tab[i];
-    *q = 0; /* end of token string */
-    tok = last_tok;
-}
-
-
-/* better than nothing, but needs extension to handle '-E' option
-   correctly too */
-static void preprocess_init(TCCState *s1)
-{
-    s1->include_stack_ptr = s1->include_stack;
-    /* XXX: move that before to avoid having to initialize
-       file->ifdef_stack_ptr ? */
-    s1->ifdef_stack_ptr = s1->ifdef_stack;
-    file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
-
-    /* XXX: not ANSI compliant: bound checking says error */
-    vtop = vstack - 1;
-    s1->pack_stack[0] = 0;
-    s1->pack_stack_ptr = s1->pack_stack;
-}
-
-void preprocess_new()
-{
-    int i, c;
-    const char *p, *r;
-    TokenSym *ts;
-
-    /* init isid table */
-    for(i=CH_EOF;i<256;i++)
-        isidnum_table[i-CH_EOF] = isid(i) || isnum(i);
-
-    /* add all tokens */
-    table_ident = NULL;
-    memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
-    
-    tok_ident = TOK_IDENT;
-    p = tcc_keywords;
-    while (*p) {
-        r = p;
-        for(;;) {
-            c = *r++;
-            if (c == '\0')
-                break;
-        }
-        ts = tok_alloc(p, r - p - 1);
-        p = r;
-    }
-}
-
-/* Preprocess the current file */
-static int tcc_preprocess(TCCState *s1)
-{
-    Sym *define_start;
-    BufferedFile *file_ref;
-    int token_seen, line_ref;
-
-    preprocess_init(s1);
-    define_start = define_stack;
-    ch = file->buf_ptr[0];
-    tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
-    parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
-        PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
-    token_seen = 0;
-    line_ref = 0;
-    file_ref = NULL;
-
-    for (;;) {
-        next();
-        if (tok == TOK_EOF) {
-            break;
-        } else if (tok == TOK_LINEFEED) {
-            if (!token_seen)
-                continue;
-            ++line_ref;
-            token_seen = 0;
-        } else if (!token_seen) {
-            int d = file->line_num - line_ref;
-            if (file != file_ref || d < 0 || d >= 8)
-                fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename);
-            else
-                while (d)
-                    fputs("\n", s1->outfile), --d;
-            line_ref = (file_ref = file)->line_num;
-            token_seen = 1;
-        }
-        fputs(get_tok_str(tok, &tokc), s1->outfile);
-    }
-    free_defines(define_start); 
-    return 0;
-}
-

+ 0 - 469
src/modules/native/tcc/libtcc/tcctok.h

@@ -1,469 +0,0 @@
-/* keywords */
-     DEF(TOK_INT, "int")
-     DEF(TOK_VOID, "void")
-     DEF(TOK_CHAR, "char")
-     DEF(TOK_IF, "if")
-     DEF(TOK_ELSE, "else")
-     DEF(TOK_WHILE, "while")
-     DEF(TOK_BREAK, "break")
-     DEF(TOK_RETURN, "return")
-     DEF(TOK_FOR, "for")
-     DEF(TOK_EXTERN, "extern")
-     DEF(TOK_STATIC, "static")
-     DEF(TOK_UNSIGNED, "unsigned")
-     DEF(TOK_GOTO, "goto")
-     DEF(TOK_DO, "do")
-     DEF(TOK_CONTINUE, "continue")
-     DEF(TOK_SWITCH, "switch")
-     DEF(TOK_CASE, "case")
-
-     DEF(TOK_CONST1, "const")
-     DEF(TOK_CONST2, "__const") /* gcc keyword */
-     DEF(TOK_CONST3, "__const__") /* gcc keyword */
-     DEF(TOK_VOLATILE1, "volatile")
-     DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
-     DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
-     DEF(TOK_LONG, "long")
-     DEF(TOK_REGISTER, "register")
-     DEF(TOK_SIGNED1, "signed")
-     DEF(TOK_SIGNED2, "__signed") /* gcc keyword */
-     DEF(TOK_SIGNED3, "__signed__") /* gcc keyword */
-     DEF(TOK_AUTO, "auto")
-     DEF(TOK_INLINE1, "inline")
-     DEF(TOK_INLINE2, "__inline") /* gcc keyword */
-     DEF(TOK_INLINE3, "__inline__") /* gcc keyword */
-     DEF(TOK_RESTRICT1, "restrict")
-     DEF(TOK_RESTRICT2, "__restrict")
-     DEF(TOK_RESTRICT3, "__restrict__")
-     DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
-     
-     DEF(TOK_FLOAT, "float")
-     DEF(TOK_DOUBLE, "double")
-     DEF(TOK_BOOL, "_Bool")
-     DEF(TOK_SHORT, "short")
-     DEF(TOK_STRUCT, "struct")
-     DEF(TOK_UNION, "union")
-     DEF(TOK_TYPEDEF, "typedef")
-     DEF(TOK_DEFAULT, "default")
-     DEF(TOK_ENUM, "enum")
-     DEF(TOK_SIZEOF, "sizeof")
-     DEF(TOK_ATTRIBUTE1, "__attribute")
-     DEF(TOK_ATTRIBUTE2, "__attribute__")
-     DEF(TOK_ALIGNOF1, "__alignof")
-     DEF(TOK_ALIGNOF2, "__alignof__")
-     DEF(TOK_TYPEOF1, "typeof")
-     DEF(TOK_TYPEOF2, "__typeof")
-     DEF(TOK_TYPEOF3, "__typeof__")
-     DEF(TOK_LABEL, "__label__")
-     DEF(TOK_ASM1, "asm")
-     DEF(TOK_ASM2, "__asm")
-     DEF(TOK_ASM3, "__asm__")
-
-/*********************************************************************/
-/* the following are not keywords. They are included to ease parsing */
-/* preprocessor only */
-     DEF(TOK_DEFINE, "define")
-     DEF(TOK_INCLUDE, "include")
-     DEF(TOK_INCLUDE_NEXT, "include_next")
-     DEF(TOK_IFDEF, "ifdef")
-     DEF(TOK_IFNDEF, "ifndef")
-     DEF(TOK_ELIF, "elif")
-     DEF(TOK_ENDIF, "endif")
-     DEF(TOK_DEFINED, "defined")
-     DEF(TOK_UNDEF, "undef")
-     DEF(TOK_ERROR, "error")
-     DEF(TOK_WARNING, "warning")
-     DEF(TOK_LINE, "line")
-     DEF(TOK_PRAGMA, "pragma")
-     DEF(TOK___LINE__, "__LINE__")
-     DEF(TOK___FILE__, "__FILE__")
-     DEF(TOK___DATE__, "__DATE__")
-     DEF(TOK___TIME__, "__TIME__")
-     DEF(TOK___FUNCTION__, "__FUNCTION__")
-     DEF(TOK___VA_ARGS__, "__VA_ARGS__")
-     
-/* special identifiers */
-     DEF(TOK___FUNC__, "__func__")
-     
-/* attribute identifiers */
-/* XXX: handle all tokens generically since speed is not critical */
-     DEF(TOK_SECTION1, "section")
-     DEF(TOK_SECTION2, "__section__")
-     DEF(TOK_ALIGNED1, "aligned")
-     DEF(TOK_ALIGNED2, "__aligned__")
-     DEF(TOK_PACKED1, "packed")
-     DEF(TOK_PACKED2, "__packed__")
-     DEF(TOK_UNUSED1, "unused")
-     DEF(TOK_UNUSED2, "__unused__")
-     DEF(TOK_CDECL1, "cdecl")
-     DEF(TOK_CDECL2, "__cdecl")
-     DEF(TOK_CDECL3, "__cdecl__")
-     DEF(TOK_STDCALL1, "stdcall")
-     DEF(TOK_STDCALL2, "__stdcall")
-     DEF(TOK_STDCALL3, "__stdcall__")
-     DEF(TOK_FASTCALL1, "fastcall")
-     DEF(TOK_FASTCALL2, "__fastcall")
-     DEF(TOK_FASTCALL3, "__fastcall__")
-     DEF(TOK_DLLEXPORT, "dllexport")
-     DEF(TOK_NORETURN1, "noreturn")
-     DEF(TOK_NORETURN2, "__noreturn__")
-     DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
-     DEF(TOK_builtin_constant_p, "__builtin_constant_p")
-     DEF(TOK_builtin_frame_address, "__builtin_frame_address")
-#ifdef TCC_TARGET_X86_64
-     DEF(TOK_builtin_malloc, "__builtin_malloc")
-     DEF(TOK_builtin_free, "__builtin_free")
-     DEF(TOK_malloc, "malloc")
-     DEF(TOK_free, "free")
-#endif
-     DEF(TOK_REGPARM1, "regparm")
-     DEF(TOK_REGPARM2, "__regparm__")
-
-/* pragma */
-     DEF(TOK_pack, "pack")
-#if !defined(TCC_TARGET_I386)
-     /* already defined for assembler */
-     DEF(TOK_ASM_push, "push")
-     DEF(TOK_ASM_pop, "pop")
-#endif
-
-/* builtin functions or variables */
-#ifdef TCC_ARM_EABI
-     DEF(TOK_memcpy, "__aeabi_memcpy")
-     DEF(TOK_memcpy4, "__aeabi_memcpy4")
-     DEF(TOK_memcpy8, "__aeabi_memcpy8")
-     DEF(TOK_memset, "__aeabi_memset")
-     DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
-     DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
-#else
-     DEF(TOK_memcpy, "memcpy")
-     DEF(TOK_memset, "memset")
-     DEF(TOK___divdi3, "__divdi3")
-     DEF(TOK___moddi3, "__moddi3")
-     DEF(TOK___udivdi3, "__udivdi3")
-     DEF(TOK___umoddi3, "__umoddi3")
-#endif
-#if defined(TCC_TARGET_ARM)
-#ifdef TCC_ARM_EABI
-     DEF(TOK___aeabi_idivmod, "__aeabi_idivmod")
-     DEF(TOK___aeabi_uidivmod, "__aeabi_uidivmod")
-     DEF(TOK___divsi3, "__aeabi_idiv")
-     DEF(TOK___udivsi3, "__aeabi_uidiv")
-     DEF(TOK___floatdisf, "__aeabi_l2f")
-     DEF(TOK___floatdidf, "__aeabi_l2d")
-     DEF(TOK___fixsfdi, "__aeabi_f2lz")
-     DEF(TOK___fixdfdi, "__aeabi_d2lz")
-#else
-     DEF(TOK___modsi3, "__modsi3")
-     DEF(TOK___umodsi3, "__umodsi3")
-     DEF(TOK___divsi3, "__divsi3")
-     DEF(TOK___udivsi3, "__udivsi3")
-     DEF(TOK___floatdisf, "__floatdisf")
-     DEF(TOK___floatdidf, "__floatdidf")
-#ifndef TCC_ARM_VFP
-     DEF(TOK___floatdixf, "__floatdixf")
-     DEF(TOK___fixunssfsi, "__fixunssfsi")
-     DEF(TOK___fixunsdfsi, "__fixunsdfsi")
-     DEF(TOK___fixunsxfsi, "__fixunsxfsi")
-     DEF(TOK___fixxfdi, "__fixxfdi")
-#endif
-     DEF(TOK___fixsfdi, "__fixsfdi")
-     DEF(TOK___fixdfdi, "__fixdfdi")
-#endif
-#elif defined(TCC_TARGET_C67)
-     DEF(TOK__divi, "_divi")
-     DEF(TOK__divu, "_divu")
-     DEF(TOK__divf, "_divf")
-     DEF(TOK__divd, "_divd")
-     DEF(TOK__remi, "_remi")
-     DEF(TOK__remu, "_remu")
-#endif
-#ifdef TCC_TARGET_I386
-     DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
-     DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
-#endif
-#ifdef TCC_ARM_EABI
-     DEF(TOK___ashrdi3, "__aeabi_lasr")
-     DEF(TOK___lshrdi3, "__aeabi_llsr")
-     DEF(TOK___ashldi3, "__aeabi_llsl")
-     DEF(TOK___floatundisf, "__aeabi_ul2f")
-     DEF(TOK___floatundidf, "__aeabi_ul2d")
-     DEF(TOK___fixunssfdi, "__aeabi_f2ulz")
-     DEF(TOK___fixunsdfdi, "__aeabi_d2ulz")
-#else
-     DEF(TOK___ashrdi3, "__ashrdi3")
-     DEF(TOK___lshrdi3, "__lshrdi3")
-     DEF(TOK___ashldi3, "__ashldi3")
-     DEF(TOK___floatundisf, "__floatundisf")
-     DEF(TOK___floatundidf, "__floatundidf")
-#ifndef TCC_ARM_VFP
-     DEF(TOK___floatundixf, "__floatundixf")
-     DEF(TOK___fixunsxfdi, "__fixunsxfdi")
-#endif
-     DEF(TOK___fixunssfdi, "__fixunssfdi")
-     DEF(TOK___fixunsdfdi, "__fixunsdfdi")
-#endif
-#ifdef TCC_TARGET_PE
-     DEF(TOK___chkstk, "__chkstk")
-#endif
-
-/* bound checking symbols */
-#ifdef CONFIG_TCC_BCHECK
-     DEF(TOK___bound_ptr_add, "__bound_ptr_add")
-     DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
-     DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
-     DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
-     DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
-     DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
-     DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
-     DEF(TOK___bound_local_new, "__bound_local_new")
-     DEF(TOK___bound_local_delete, "__bound_local_delete")
-#if 0
-     DEF(TOK_malloc, "malloc")
-     DEF(TOK_free, "free")
-     DEF(TOK_realloc, "realloc")
-     DEF(TOK_memalign, "memalign")
-     DEF(TOK_calloc, "calloc")
-#endif
-     DEF(TOK_memmove, "memmove")
-     DEF(TOK_strlen, "strlen")
-     DEF(TOK_strcpy, "strcpy")
-     DEF(TOK_alloca, "alloca")
-#endif
-
-/* Tiny Assembler */
-
- DEF_ASM(byte)
- DEF_ASM(align)
- DEF_ASM(skip)
- DEF_ASM(space)
- DEF_ASM(string)
- DEF_ASM(asciz)
- DEF_ASM(ascii)
- DEF_ASM(globl)
- DEF_ASM(global)
- DEF_ASM(text)
- DEF_ASM(data)
- DEF_ASM(bss)
- DEF_ASM(previous)
- DEF_ASM(fill)
- DEF_ASM(org)
- DEF_ASM(quad)
-
-#ifdef TCC_TARGET_I386
-
-/* WARNING: relative order of tokens is important. */
- DEF_ASM(al)
- DEF_ASM(cl)
- DEF_ASM(dl)
- DEF_ASM(bl)
- DEF_ASM(ah)
- DEF_ASM(ch)
- DEF_ASM(dh)
- DEF_ASM(bh)
- DEF_ASM(ax)
- DEF_ASM(cx)
- DEF_ASM(dx)
- DEF_ASM(bx)
- DEF_ASM(sp)
- DEF_ASM(bp)
- DEF_ASM(si)
- DEF_ASM(di)
- DEF_ASM(eax)
- DEF_ASM(ecx)
- DEF_ASM(edx)
- DEF_ASM(ebx)
- DEF_ASM(esp)
- DEF_ASM(ebp)
- DEF_ASM(esi)
- DEF_ASM(edi)
- DEF_ASM(mm0)
- DEF_ASM(mm1)
- DEF_ASM(mm2)
- DEF_ASM(mm3)
- DEF_ASM(mm4)
- DEF_ASM(mm5)
- DEF_ASM(mm6)
- DEF_ASM(mm7)
- DEF_ASM(xmm0)
- DEF_ASM(xmm1)
- DEF_ASM(xmm2)
- DEF_ASM(xmm3)
- DEF_ASM(xmm4)
- DEF_ASM(xmm5)
- DEF_ASM(xmm6)
- DEF_ASM(xmm7)
- DEF_ASM(cr0)
- DEF_ASM(cr1)
- DEF_ASM(cr2)
- DEF_ASM(cr3)
- DEF_ASM(cr4)
- DEF_ASM(cr5)
- DEF_ASM(cr6)
- DEF_ASM(cr7)
- DEF_ASM(tr0)
- DEF_ASM(tr1)
- DEF_ASM(tr2)
- DEF_ASM(tr3)
- DEF_ASM(tr4)
- DEF_ASM(tr5)
- DEF_ASM(tr6)
- DEF_ASM(tr7)
- DEF_ASM(db0)
- DEF_ASM(db1)
- DEF_ASM(db2)
- DEF_ASM(db3)
- DEF_ASM(db4)
- DEF_ASM(db5)
- DEF_ASM(db6)
- DEF_ASM(db7)
- DEF_ASM(dr0)
- DEF_ASM(dr1)
- DEF_ASM(dr2)
- DEF_ASM(dr3)
- DEF_ASM(dr4)
- DEF_ASM(dr5)
- DEF_ASM(dr6)
- DEF_ASM(dr7)
- DEF_ASM(es)
- DEF_ASM(cs)
- DEF_ASM(ss)
- DEF_ASM(ds)
- DEF_ASM(fs)
- DEF_ASM(gs)
- DEF_ASM(st)
-
- DEF_BWL(mov)
-
- /* generic two operands */
- DEF_BWL(add)
- DEF_BWL(or)
- DEF_BWL(adc)
- DEF_BWL(sbb)
- DEF_BWL(and)
- DEF_BWL(sub)
- DEF_BWL(xor)
- DEF_BWL(cmp)
-
- /* unary ops */
- DEF_BWL(inc)
- DEF_BWL(dec)
- DEF_BWL(not)
- DEF_BWL(neg)
- DEF_BWL(mul)
- DEF_BWL(imul)
- DEF_BWL(div)
- DEF_BWL(idiv)
-
- DEF_BWL(xchg)
- DEF_BWL(test)
-
- /* shifts */
- DEF_BWL(rol)
- DEF_BWL(ror)
- DEF_BWL(rcl)
- DEF_BWL(rcr)
- DEF_BWL(shl)
- DEF_BWL(shr)
- DEF_BWL(sar)
-
- DEF_ASM(shldw)
- DEF_ASM(shldl)
- DEF_ASM(shld)
- DEF_ASM(shrdw)
- DEF_ASM(shrdl)
- DEF_ASM(shrd)
-
- DEF_ASM(pushw)
- DEF_ASM(pushl)
- DEF_ASM(push)
- DEF_ASM(popw)
- DEF_ASM(popl)
- DEF_ASM(pop)
- DEF_BWL(in)
- DEF_BWL(out)
-
- DEF_WL(movzb)
-
- DEF_ASM(movzwl)
- DEF_ASM(movsbw)
- DEF_ASM(movsbl)
- DEF_ASM(movswl)
-
- DEF_WL(lea) 
-
- DEF_ASM(les) 
- DEF_ASM(lds) 
- DEF_ASM(lss) 
- DEF_ASM(lfs) 
- DEF_ASM(lgs) 
-
- DEF_ASM(call)
- DEF_ASM(jmp)
- DEF_ASM(lcall)
- DEF_ASM(ljmp)
- 
- DEF_ASMTEST(j)
-
- DEF_ASMTEST(set)
- DEF_ASMTEST(cmov)
-
- DEF_WL(bsf)
- DEF_WL(bsr)
- DEF_WL(bt)
- DEF_WL(bts)
- DEF_WL(btr)
- DEF_WL(btc)
-
- DEF_WL(lsl)
-
- /* generic FP ops */
- DEF_FP(add)
- DEF_FP(mul)
-
- DEF_ASM(fcom)
- DEF_ASM(fcom_1) /* non existant op, just to have a regular table */
- DEF_FP1(com)
-
- DEF_FP(comp)
- DEF_FP(sub)
- DEF_FP(subr)
- DEF_FP(div)
- DEF_FP(divr)
-
- DEF_BWL(xadd)
- DEF_BWL(cmpxchg)
-
- /* string ops */
- DEF_BWL(cmps)
- DEF_BWL(scmp)
- DEF_BWL(ins)
- DEF_BWL(outs)
- DEF_BWL(lods)
- DEF_BWL(slod)
- DEF_BWL(movs)
- DEF_BWL(smov)
- DEF_BWL(scas)
- DEF_BWL(ssca)
- DEF_BWL(stos)
- DEF_BWL(ssto)
-
- /* generic asm ops */
-
-#define ALT(x)
-#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
-#define DEF_ASM_OP0L(name, opcode, group, instr_type)
-#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
-#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
-#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
-#include "i386-asm.h"
-
-#define ALT(x)
-#define DEF_ASM_OP0(name, opcode)
-#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
-#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
-#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
-#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
-#include "i386-asm.h"
-
-#endif

+ 0 - 1419
src/modules/native/tcc/libtcc/x86_64-gen.c

@@ -1,1419 +0,0 @@
-/*
- *  x86-64 code generator for TCC
- *
- *  Copyright (c) 2008 Shinichiro Hamaji
- *
- *  Based on i386-gen.c by Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <assert.h>
-
-/* number of available registers */
-#define NB_REGS             5
-
-/* a register can belong to several classes. The classes must be
-   sorted from more general to more precise (see gv2() code which does
-   assumptions on it). */
-#define RC_INT     0x0001 /* generic integer register */
-#define RC_FLOAT   0x0002 /* generic float register */
-#define RC_RAX     0x0004
-#define RC_RCX     0x0008
-#define RC_RDX     0x0010
-#define RC_XMM0    0x0020
-#define RC_ST0     0x0040 /* only for long double */
-#define RC_IRET    RC_RAX /* function return: integer register */
-#define RC_LRET    RC_RDX /* function return: second integer register */
-#define RC_FRET    RC_XMM0 /* function return: float register */
-
-/* pretty names for the registers */
-enum {
-    TREG_RAX = 0,
-    TREG_RCX = 1,
-    TREG_RDX = 2,
-    TREG_RSI = 6,
-    TREG_RDI = 7,
-    TREG_R8  = 8,
-    TREG_R9  = 9,
-    TREG_R10 = 10,
-    TREG_R11 = 11,
-
-    TREG_XMM0 = 3,
-    TREG_ST0 = 4,
-
-    TREG_MEM = 0x10,
-};
-
-#define REX_BASE(reg) (((reg) >> 3) & 1)
-#define REG_VALUE(reg) ((reg) & 7)
-
-int reg_classes[NB_REGS] = {
-    /* eax */ RC_INT | RC_RAX,
-    /* ecx */ RC_INT | RC_RCX,
-    /* edx */ RC_INT | RC_RDX,
-    /* xmm0 */ RC_FLOAT | RC_XMM0,
-    /* st0 */ RC_ST0,
-};
-
-/* return registers for function */
-#define REG_IRET TREG_RAX /* single word int return register */
-#define REG_LRET TREG_RDX /* second word return register (for long long) */
-#define REG_FRET TREG_XMM0 /* float return register */
-
-/* defined if function parameters must be evaluated in reverse order */
-#define INVERT_FUNC_PARAMS
-
-/* pointer size, in bytes */
-#define PTR_SIZE 8
-
-/* long double size and alignment, in bytes */
-#define LDOUBLE_SIZE  16
-#define LDOUBLE_ALIGN 8
-/* maximum alignment (for aligned attribute support) */
-#define MAX_ALIGN     8
-
-/******************************************************/
-/* ELF defines */
-
-#define EM_TCC_TARGET EM_X86_64
-
-/* relocation type for 32 bit data relocation */
-#define R_DATA_32   R_X86_64_64
-#define R_JMP_SLOT  R_X86_64_JUMP_SLOT
-#define R_COPY      R_X86_64_COPY
-
-#define ELF_START_ADDR 0x08048000
-#define ELF_PAGE_SIZE  0x1000
-
-/******************************************************/
-
-static unsigned long func_sub_sp_offset;
-static int func_ret_sub;
-
-/* XXX: make it faster ? */
-void g(int c)
-{
-    int ind1;
-    ind1 = ind + 1;
-    if (ind1 > cur_text_section->data_allocated)
-        section_realloc(cur_text_section, ind1);
-    cur_text_section->data[ind] = c;
-    ind = ind1;
-}
-
-void o(unsigned int c)
-{
-    while (c) {
-        g(c);
-        c = c >> 8;
-    }
-}
-
-void gen_le32(int c)
-{
-    g(c);
-    g(c >> 8);
-    g(c >> 16);
-    g(c >> 24);
-}
-
-void gen_le64(int64_t c)
-{
-    g(c);
-    g(c >> 8);
-    g(c >> 16);
-    g(c >> 24);
-    g(c >> 32);
-    g(c >> 40);
-    g(c >> 48);
-    g(c >> 56);
-}
-
-/* output a symbol and patch all calls to it */
-void gsym_addr(int t, int a)
-{
-    int n, *ptr;
-    while (t) {
-        ptr = (int *)(cur_text_section->data + t);
-        n = *ptr; /* next value */
-        *ptr = a - t - 4;
-        t = n;
-    }
-}
-
-void gsym(int t)
-{
-    gsym_addr(t, ind);
-}
-
-/* psym is used to put an instruction with a data field which is a
-   reference to a symbol. It is in fact the same as oad ! */
-#define psym oad
-
-static int is64_type(int t)
-{
-    return ((t & VT_BTYPE) == VT_PTR ||
-            (t & VT_BTYPE) == VT_FUNC ||
-            (t & VT_BTYPE) == VT_LLONG);
-}
-
-static int is_sse_float(int t) {
-    int bt;
-    bt = t & VT_BTYPE;
-    return bt == VT_DOUBLE || bt == VT_FLOAT;
-}
-
-/* instruction + 4 bytes data. Return the address of the data */
-static int oad(int c, int s)
-{
-    int ind1;
-
-    o(c);
-    ind1 = ind + 4;
-    if (ind1 > cur_text_section->data_allocated)
-        section_realloc(cur_text_section, ind1);
-    *(int *)(cur_text_section->data + ind) = s;
-    s = ind;
-    ind = ind1;
-    return s;
-}
-
-/* output constant with relocation if 'r & VT_SYM' is true */
-static void gen_addr64(int r, Sym *sym, int64_t c)
-{
-    if (r & VT_SYM)
-        greloc(cur_text_section, sym, ind, R_X86_64_64);
-    gen_le64(c);
-}
-
-/* output constant with relocation if 'r & VT_SYM' is true */
-static void gen_addrpc32(int r, Sym *sym, int c)
-{
-    if (r & VT_SYM)
-        greloc(cur_text_section, sym, ind, R_X86_64_PC32);
-    gen_le32(c-4);
-}
-
-/* output got address with relocation */
-static void gen_gotpcrel(int r, Sym *sym, int c)
-{
-    Section *sr;
-    ElfW(Rela) *rel;
-    greloc(cur_text_section, sym, ind, R_X86_64_GOTPCREL);
-    sr = cur_text_section->reloc;
-    rel = (ElfW(Rela) *)(sr->data + sr->data_offset - sizeof(ElfW(Rela)));
-    rel->r_addend = -4;
-    gen_le32(0);
-
-    if (c) {
-        /* we use add c, %xxx for displacement */
-        o(0x48 + REX_BASE(r));
-        o(0x81);
-        o(0xc0 + REG_VALUE(r));
-        gen_le32(c);
-    }
-}
-
-static void gen_modrm_impl(int op_reg, int r, Sym *sym, int c, int is_got)
-{
-    op_reg = REG_VALUE(op_reg) << 3;
-    if ((r & VT_VALMASK) == VT_CONST) {
-        /* constant memory reference */
-        o(0x05 | op_reg);
-        if (is_got) {
-            gen_gotpcrel(r, sym, c);
-        } else {
-            gen_addrpc32(r, sym, c);
-        }
-    } else if ((r & VT_VALMASK) == VT_LOCAL) {
-        /* currently, we use only ebp as base */
-        if (c == (char)c) {
-            /* short reference */
-            o(0x45 | op_reg);
-            g(c);
-        } else {
-            oad(0x85 | op_reg, c);
-        }
-    } else if ((r & VT_VALMASK) >= TREG_MEM) {
-        if (c) {
-            g(0x80 | op_reg | REG_VALUE(r));
-            gen_le32(c);
-        } else {
-            g(0x00 | op_reg | REG_VALUE(r));
-        }
-    } else {
-        g(0x00 | op_reg | (r & VT_VALMASK));
-    }
-}
-
-/* generate a modrm reference. 'op_reg' contains the addtionnal 3
-   opcode bits */
-static void gen_modrm(int op_reg, int r, Sym *sym, int c)
-{
-    gen_modrm_impl(op_reg, r, sym, c, 0);
-}
-
-/* generate a modrm reference. 'op_reg' contains the addtionnal 3
-   opcode bits */
-static void gen_modrm64(int opcode, int op_reg, int r, Sym *sym, int c)
-{
-    int is_got;
-    int rex = 0x48 | (REX_BASE(op_reg) << 2);
-    if ((r & VT_VALMASK) != VT_CONST &&
-        (r & VT_VALMASK) != VT_LOCAL) {
-        rex |= REX_BASE(VT_VALMASK & r);
-    }
-    o(rex);
-    o(opcode);
-    is_got = (op_reg & TREG_MEM) && !(sym->type.t & VT_STATIC);
-    gen_modrm_impl(op_reg, r, sym, c, is_got);
-}
-
-
-/* load 'r' from value 'sv' */
-void load(int r, SValue *sv)
-{
-    int v, t, ft, fc, fr;
-    SValue v1;
-
-    fr = sv->r;
-    ft = sv->type.t;
-    fc = sv->c.ul;
-
-    /* we use indirect access via got */
-    if ((fr & VT_VALMASK) == VT_CONST && (fr & VT_SYM) &&
-        (fr & VT_LVAL) && !(sv->sym->type.t & VT_STATIC)) {
-        /* use the result register as a temporal register */
-        int tr = r | TREG_MEM;
-        if (is_float(ft)) {
-            /* we cannot use float registers as a temporal register */
-            tr = get_reg(RC_INT) | TREG_MEM;
-        }
-        gen_modrm64(0x8b, tr, fr, sv->sym, 0);
-
-        /* load from the temporal register */
-        fr = tr | VT_LVAL;
-    }
-
-    v = fr & VT_VALMASK;
-    if (fr & VT_LVAL) {
-        if (v == VT_LLOCAL) {
-            v1.type.t = VT_PTR;
-            v1.r = VT_LOCAL | VT_LVAL;
-            v1.c.ul = fc;
-            load(r, &v1);
-            fr = r;
-        }
-        if ((ft & VT_BTYPE) == VT_FLOAT) {
-            o(0x6e0f66); /* movd */
-            r = 0;
-        } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
-            o(0x7e0ff3); /* movq */
-            r = 0;
-        } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
-            o(0xdb); /* fldt */
-            r = 5;
-        } else if ((ft & VT_TYPE) == VT_BYTE) {
-            o(0xbe0f);   /* movsbl */
-        } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
-            o(0xb60f);   /* movzbl */
-        } else if ((ft & VT_TYPE) == VT_SHORT) {
-            o(0xbf0f);   /* movswl */
-        } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
-            o(0xb70f);   /* movzwl */
-        } else if (is64_type(ft)) {
-            gen_modrm64(0x8b, r, fr, sv->sym, fc);
-            return;
-        } else {
-            o(0x8b);   /* movl */
-        }
-        gen_modrm(r, fr, sv->sym, fc);
-    } else {
-        if (v == VT_CONST) {
-            if ((ft & VT_BTYPE) == VT_LLONG) {
-                assert(!(fr & VT_SYM));
-                o(0x48);
-                o(0xb8 + REG_VALUE(r)); /* mov $xx, r */
-                gen_addr64(fr, sv->sym, sv->c.ull);
-            } else {
-                if (fr & VT_SYM) {
-                    if (sv->sym->type.t & VT_STATIC) {
-                        o(0x8d48);
-                        o(0x05 + REG_VALUE(r) * 8); /* lea xx(%rip), r */
-                        gen_addrpc32(fr, sv->sym, fc);
-                    } else {
-                        o(0x8b48);
-                        o(0x05 + REG_VALUE(r) * 8); /* mov xx(%rip), r */
-                        gen_gotpcrel(r, sv->sym, fc);
-                    }
-                } else {
-                    o(0xb8 + REG_VALUE(r)); /* mov $xx, r */
-                    gen_le32(fc);
-                }
-            }
-        } else if (v == VT_LOCAL) {
-            o(0x48 | REX_BASE(r));
-            o(0x8d); /* lea xxx(%ebp), r */
-            gen_modrm(r, VT_LOCAL, sv->sym, fc);
-        } else if (v == VT_CMP) {
-            oad(0xb8 + r, 0); /* mov $0, r */
-            o(0x0f); /* setxx %br */
-            o(fc);
-            o(0xc0 + r);
-        } else if (v == VT_JMP || v == VT_JMPI) {
-            t = v & 1;
-            oad(0xb8 + r, t); /* mov $1, r */
-            o(0x05eb); /* jmp after */
-            gsym(fc);
-            oad(0xb8 + r, t ^ 1); /* mov $0, r */
-        } else if (v != r) {
-            if (r == TREG_XMM0) {
-                assert(v == TREG_ST0);
-                /* gen_cvt_ftof(VT_DOUBLE); */
-                o(0xf0245cdd); /* fstpl -0x10(%rsp) */
-                /* movsd -0x10(%rsp),%xmm0 */
-                o(0x44100ff2);
-                o(0xf024);
-            } else if (r == TREG_ST0) {
-                assert(v == TREG_XMM0);
-                /* gen_cvt_ftof(VT_LDOUBLE); */
-                /* movsd %xmm0,-0x10(%rsp) */
-                o(0x44110ff2);
-                o(0xf024);
-                o(0xf02444dd); /* fldl -0x10(%rsp) */
-            } else {
-                o(0x48 | REX_BASE(r) | (REX_BASE(v) << 2));
-                o(0x89);
-                o(0xc0 + r + v * 8); /* mov v, r */
-            }
-        }
-    }
-}
-
-/* store register 'r' in lvalue 'v' */
-void store(int r, SValue *v)
-{
-    int fr, bt, ft, fc;
-    int op64 = 0;
-    /* store the REX prefix in this variable when PIC is enabled */
-    int pic = 0;
-
-    ft = v->type.t;
-    fc = v->c.ul;
-    fr = v->r & VT_VALMASK;
-    bt = ft & VT_BTYPE;
-
-    /* we need to access the variable via got */
-    if (fr == VT_CONST && (v->r & VT_SYM)) {
-        /* mov xx(%rip), %r11 */
-        o(0x1d8b4c);
-        gen_gotpcrel(TREG_R11, v->sym, v->c.ul);
-        pic = is64_type(bt) ? 0x49 : 0x41;
-    }
-
-    /* XXX: incorrect if float reg to reg */
-    if (bt == VT_FLOAT) {
-        o(0x66);
-        o(pic);
-        o(0x7e0f); /* movd */
-        r = 0;
-    } else if (bt == VT_DOUBLE) {
-        o(0x66);
-        o(pic);
-        o(0xd60f); /* movq */
-        r = 0;
-    } else if (bt == VT_LDOUBLE) {
-        o(0xc0d9); /* fld %st(0) */
-        o(pic);
-        o(0xdb); /* fstpt */
-        r = 7;
-    } else {
-        if (bt == VT_SHORT)
-            o(0x66);
-        o(pic);
-        if (bt == VT_BYTE || bt == VT_BOOL)
-            o(0x88);
-        else if (is64_type(bt))
-            op64 = 0x89;
-        else
-            o(0x89);
-    }
-    if (pic) {
-        /* xxx r, (%r11) where xxx is mov, movq, fld, or etc */
-        if (op64)
-            o(op64);
-        o(3 + (r << 3));
-    } else if (op64) {
-        if (fr == VT_CONST ||
-            fr == VT_LOCAL ||
-            (v->r & VT_LVAL)) {
-            gen_modrm64(op64, r, v->r, v->sym, fc);
-        } else if (fr != r) {
-            /* XXX: don't we really come here? */
-            abort();
-            o(0xc0 + fr + r * 8); /* mov r, fr */
-        }
-    } else {
-        if (fr == VT_CONST ||
-            fr == VT_LOCAL ||
-            (v->r & VT_LVAL)) {
-            gen_modrm(r, v->r, v->sym, fc);
-        } else if (fr != r) {
-            /* XXX: don't we really come here? */
-            abort();
-            o(0xc0 + fr + r * 8); /* mov r, fr */
-        }
-    }
-}
-
-static void gadd_sp(int val)
-{
-    if (val == (char)val) {
-        o(0xc48348);
-        g(val);
-    } else {
-        oad(0xc48148, val); /* add $xxx, %rsp */
-    }
-}
-
-/* 'is_jmp' is '1' if it is a jump */
-static void gcall_or_jmp(int is_jmp)
-{
-    int r;
-    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
-        /* constant case */
-        if (vtop->r & VT_SYM) {
-            /* relocation case */
-            greloc(cur_text_section, vtop->sym,
-                   ind + 1, R_X86_64_PC32);
-        } else {
-            /* put an empty PC32 relocation */
-            put_elf_reloc(symtab_section, cur_text_section,
-                          ind + 1, R_X86_64_PC32, 0);
-        }
-        oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */
-    } else {
-        /* otherwise, indirect call */
-        r = TREG_R11;
-        load(r, vtop);
-        o(0x41); /* REX */
-        o(0xff); /* call/jmp *r */
-        o(0xd0 + REG_VALUE(r) + (is_jmp << 4));
-    }
-}
-
-static uint8_t arg_regs[6] = {
-    TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9
-};
-/* Generate function call. The function address is pushed first, then
-   all the parameters in call order. This functions pops all the
-   parameters and the function address. */
-void gfunc_call(int nb_args)
-{
-    int size, align, r, args_size, i, func_call;
-    Sym *func_sym;
-    SValue *orig_vtop;
-    int nb_reg_args = 0;
-    int nb_sse_args = 0;
-    int sse_reg, gen_reg;
-
-    /* calculate the number of integer/float arguments */
-    args_size = 0;
-    for(i = 0; i < nb_args; i++) {
-        if ((vtop[-i].type.t & VT_BTYPE) == VT_STRUCT) {
-            args_size += type_size(&vtop->type, &align);
-        } else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE) {
-            args_size += 16;
-        } else if (is_sse_float(vtop[-i].type.t)) {
-            nb_sse_args++;
-            if (nb_sse_args > 8) args_size += 8;
-        } else {
-            nb_reg_args++;
-            if (nb_reg_args > 6) args_size += 8;
-        }
-    }
-
-    /* for struct arguments, we need to call memcpy and the function
-       call breaks register passing arguments we are preparing.
-       So, we process arguments which will be passed by stack first. */
-    orig_vtop = vtop;
-    gen_reg = nb_reg_args;
-    sse_reg = nb_sse_args;
-    /* adjust stack to align SSE boundary */
-    if (args_size &= 8) {
-        o(0x50); /* push $rax */
-    }
-    for(i = 0; i < nb_args; i++) {
-        if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
-            size = type_size(&vtop->type, &align);
-            /* align to stack align size */
-            size = (size + 3) & ~3;
-            /* allocate the necessary size on stack */
-            o(0x48);
-            oad(0xec81, size); /* sub $xxx, %rsp */
-            /* generate structure store */
-            r = get_reg(RC_INT);
-            o(0x48 + REX_BASE(r));
-            o(0x89); /* mov %rsp, r */
-            o(0xe0 + r);
-            {
-                /* following code breaks vtop[1] */
-                SValue tmp = vtop[1];
-                vset(&vtop->type, r | VT_LVAL, 0);
-                vswap();
-                vstore();
-                vtop[1] = tmp;
-            }
-            args_size += size;
-        } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
-            gv(RC_ST0);
-            size = LDOUBLE_SIZE;
-            oad(0xec8148, size); /* sub $xxx, %rsp */
-            o(0x7cdb); /* fstpt 0(%rsp) */
-            g(0x24);
-            g(0x00);
-            args_size += size;
-        } else if (is_sse_float(vtop->type.t)) {
-            int j = --sse_reg;
-            if (j >= 8) {
-                gv(RC_FLOAT);
-                o(0x50); /* push $rax */
-                /* movq %xmm0, (%rsp) */
-                o(0x04d60f66);
-                o(0x24);
-                args_size += 8;
-            }
-        } else {
-            int j = --gen_reg;
-            /* simple type */
-            /* XXX: implicit cast ? */
-            if (j >= 6) {
-                r = gv(RC_INT);
-                o(0x50 + r); /* push r */
-                args_size += 8;
-            }
-        }
-        vtop--;
-    }
-    vtop = orig_vtop;
-
-    /* then, we prepare register passing arguments.
-       Note that we cannot set RDX and RCX in this loop because gv()
-       may break these temporary registers. Let's use R10 and R11
-       instead of them */
-    gen_reg = nb_reg_args;
-    sse_reg = nb_sse_args;
-    for(i = 0; i < nb_args; i++) {
-        if ((vtop->type.t & VT_BTYPE) == VT_STRUCT ||
-            (vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
-        } else if (is_sse_float(vtop->type.t)) {
-            int j = --sse_reg;
-            if (j < 8) {
-                gv(RC_FLOAT); /* only one float register */
-                /* movaps %xmm0, %xmmN */
-                o(0x280f);
-                o(0xc0 + (sse_reg << 3));
-            }
-        } else {
-            int j = --gen_reg;
-            /* simple type */
-            /* XXX: implicit cast ? */
-            if (j < 6) {
-                r = gv(RC_INT);
-                if (j < 2) {
-                    o(0x8948); /* mov */
-                    o(0xc0 + r * 8 + arg_regs[j]);
-                } else if (j < 4) {
-                    o(0x8949); /* mov */
-                    /* j=2: r10, j=3: r11 */
-                    o(0xc0 + r * 8 + j);
-                } else {
-                    o(0x8949); /* mov */
-                    /* j=4: r8, j=5: r9 */
-                    o(0xc0 + r * 8 + j - 4);
-                }
-            }
-        }
-        vtop--;
-    }
-
-    save_regs(0); /* save used temporary registers */
-
-    /* Copy R10 and R11 into RDX and RCX, respectively */
-    if (nb_reg_args > 2) {
-        o(0xd2894c); /* mov %r10, %rdx */
-        if (nb_reg_args > 3) {
-            o(0xd9894c); /* mov %r11, %rcx */
-        }
-    }
-
-    func_sym = vtop->type.ref;
-    func_call = FUNC_CALL(func_sym->r);
-    oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */
-    gcall_or_jmp(0);
-    if (args_size)
-        gadd_sp(args_size);
-    vtop--;
-}
-
-#ifdef TCC_TARGET_PE
-/* XXX: support PE? */
-#warning "PE isn't tested at all"
-#define FUNC_PROLOG_SIZE 12
-#else
-#define FUNC_PROLOG_SIZE 11
-#endif
-
-static void push_arg_reg(int i) {
-    loc -= 8;
-    gen_modrm64(0x89, arg_regs[i], VT_LOCAL, NULL, loc);
-}
-
-/* generate function prolog of type 't' */
-void gfunc_prolog(CType *func_type)
-{
-    int i, addr, align, size, func_call;
-    int param_index, param_addr, reg_param_index, sse_param_index;
-    Sym *sym;
-    CType *type;
-
-    func_ret_sub = 0;
-
-    sym = func_type->ref;
-    func_call = FUNC_CALL(sym->r);
-    addr = PTR_SIZE * 2;
-    loc = 0;
-    ind += FUNC_PROLOG_SIZE;
-    func_sub_sp_offset = ind;
-
-    if (func_type->ref->c == FUNC_ELLIPSIS) {
-        int seen_reg_num, seen_sse_num, seen_stack_size;
-        seen_reg_num = seen_sse_num = 0;
-        /* frame pointer and return address */
-        seen_stack_size = PTR_SIZE * 2;
-        /* count the number of seen parameters */
-        sym = func_type->ref;
-        while ((sym = sym->next) != NULL) {
-            type = &sym->type;
-            if (is_sse_float(type->t)) {
-                if (seen_sse_num < 8) {
-                    seen_sse_num++;
-                } else {
-                    seen_stack_size += 8;
-                }
-            } else if ((type->t & VT_BTYPE) == VT_STRUCT) {
-                size = type_size(type, &align);
-                size = (size + 3) & ~3;
-                seen_stack_size += size;
-            } else if ((type->t & VT_BTYPE) == VT_LDOUBLE) {
-                seen_stack_size += LDOUBLE_SIZE;
-            } else {
-                if (seen_reg_num < 6) {
-                    seen_reg_num++;
-                } else {
-                    seen_stack_size += 8;
-                }
-            }
-        }
-
-        loc -= 16;
-        /* movl $0x????????, -0x10(%rbp) */
-        o(0xf045c7);
-        gen_le32(seen_reg_num * 8);
-        /* movl $0x????????, -0xc(%rbp) */
-        o(0xf445c7);
-        gen_le32(seen_sse_num * 16 + 48);
-        /* movl $0x????????, -0x8(%rbp) */
-        o(0xf845c7);
-        gen_le32(seen_stack_size);
-
-        /* save all register passing arguments */
-        for (i = 0; i < 8; i++) {
-            loc -= 16;
-            o(0xd60f66); /* movq */
-            gen_modrm(7 - i, VT_LOCAL, NULL, loc);
-            /* movq $0, loc+8(%rbp) */
-            o(0x85c748);
-            gen_le32(loc + 8);
-            gen_le32(0);
-        }
-        for (i = 0; i < 6; i++) {
-            push_arg_reg(5 - i);
-        }
-    }
-
-    sym = func_type->ref;
-    param_index = 0;
-    reg_param_index = 0;
-    sse_param_index = 0;
-
-    /* if the function returns a structure, then add an
-       implicit pointer parameter */
-    func_vt = sym->type;
-    if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
-        push_arg_reg(reg_param_index);
-        param_addr = loc;
-
-        func_vc = loc;
-        param_index++;
-        reg_param_index++;
-    }
-    /* define parameters */
-    while ((sym = sym->next) != NULL) {
-        type = &sym->type;
-        size = type_size(type, &align);
-        size = (size + 3) & ~3;
-        if (is_sse_float(type->t)) {
-            if (sse_param_index < 8) {
-                /* save arguments passed by register */
-                loc -= 8;
-                o(0xd60f66); /* movq */
-                gen_modrm(sse_param_index, VT_LOCAL, NULL, loc);
-                param_addr = loc;
-            } else {
-                param_addr = addr;
-                addr += size;
-            }
-            sse_param_index++;
-        } else if ((type->t & VT_BTYPE) == VT_STRUCT ||
-                   (type->t & VT_BTYPE) == VT_LDOUBLE) {
-            param_addr = addr;
-            addr += size;
-        } else {
-            if (reg_param_index < 6) {
-                /* save arguments passed by register */
-                push_arg_reg(reg_param_index);
-                param_addr = loc;
-            } else {
-                param_addr = addr;
-                addr += 8;
-            }
-            reg_param_index++;
-        }
-        sym_push(sym->v & ~SYM_FIELD, type,
-                 VT_LOCAL | VT_LVAL, param_addr);
-        param_index++;
-    }
-}
-
-/* generate function epilog */
-void gfunc_epilog(void)
-{
-    int v, saved_ind;
-
-    o(0xc9); /* leave */
-    if (func_ret_sub == 0) {
-        o(0xc3); /* ret */
-    } else {
-        o(0xc2); /* ret n */
-        g(func_ret_sub);
-        g(func_ret_sub >> 8);
-    }
-    /* align local size to word & save local variables */
-    v = (-loc + 15) & -16;
-    saved_ind = ind;
-    ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
-#ifdef TCC_TARGET_PE
-    if (v >= 4096) {
-        Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
-        oad(0xb8, v); /* mov stacksize, %eax */
-        oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
-        greloc(cur_text_section, sym, ind-4, R_X86_64_PC32);
-    } else
-#endif
-    {
-        o(0xe5894855);  /* push %rbp, mov %rsp, %rbp */
-        o(0xec8148);  /* sub rsp, stacksize */
-        gen_le32(v);
-#if FUNC_PROLOG_SIZE == 12
-        o(0x90);  /* adjust to FUNC_PROLOG_SIZE */
-#endif
-    }
-    ind = saved_ind;
-}
-
-/* generate a jump to a label */
-int gjmp(int t)
-{
-    return psym(0xe9, t);
-}
-
-/* generate a jump to a fixed address */
-void gjmp_addr(int a)
-{
-    int r;
-    r = a - ind - 2;
-    if (r == (char)r) {
-        g(0xeb);
-        g(r);
-    } else {
-        oad(0xe9, a - ind - 5);
-    }
-}
-
-/* generate a test. set 'inv' to invert test. Stack entry is popped */
-int gtst(int inv, int t)
-{
-    int v, *p;
-
-    v = vtop->r & VT_VALMASK;
-    if (v == VT_CMP) {
-        /* fast case : can jump directly since flags are set */
-        g(0x0f);
-        t = psym((vtop->c.i - 16) ^ inv, t);
-    } else if (v == VT_JMP || v == VT_JMPI) {
-        /* && or || optimization */
-        if ((v & 1) == inv) {
-            /* insert vtop->c jump list in t */
-            p = &vtop->c.i;
-            while (*p != 0)
-                p = (int *)(cur_text_section->data + *p);
-            *p = t;
-            t = vtop->c.i;
-        } else {
-            t = gjmp(t);
-            gsym(vtop->c.i);
-        }
-    } else {
-        if (is_float(vtop->type.t) ||
-            (vtop->type.t & VT_BTYPE) == VT_LLONG) {
-            vpushi(0);
-            gen_op(TOK_NE);
-        }
-        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-            /* constant jmp optimization */
-            if ((vtop->c.i != 0) != inv)
-                t = gjmp(t);
-        } else {
-            v = gv(RC_INT);
-            o(0x85);
-            o(0xc0 + v * 9);
-            g(0x0f);
-            t = psym(0x85 ^ inv, t);
-        }
-    }
-    vtop--;
-    return t;
-}
-
-/* generate an integer binary operation */
-void gen_opi(int op)
-{
-    int r, fr, opc, c;
-
-    switch(op) {
-    case '+':
-    case TOK_ADDC1: /* add with carry generation */
-        opc = 0;
-    gen_op8:
-        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST &&
-            !is64_type(vtop->type.t)) {
-            /* constant case */
-            vswap();
-            r = gv(RC_INT);
-            if (is64_type(vtop->type.t)) {
-                o(0x48 | REX_BASE(r));
-            }
-            vswap();
-            c = vtop->c.i;
-            if (c == (char)c) {
-                /* XXX: generate inc and dec for smaller code ? */
-                o(0x83);
-                o(0xc0 | (opc << 3) | REG_VALUE(r));
-                g(c);
-            } else {
-                o(0x81);
-                oad(0xc0 | (opc << 3) | REG_VALUE(r), c);
-            }
-        } else {
-            gv2(RC_INT, RC_INT);
-            r = vtop[-1].r;
-            fr = vtop[0].r;
-            if (opc != 7 ||
-                is64_type(vtop[0].type.t) || (vtop[0].type.t & VT_UNSIGNED) ||
-                is64_type(vtop[-1].type.t) || (vtop[-1].type.t & VT_UNSIGNED)) {
-                o(0x48 | REX_BASE(r) | (REX_BASE(fr) << 2));
-            }
-            o((opc << 3) | 0x01);
-            o(0xc0 + REG_VALUE(r) + REG_VALUE(fr) * 8);
-        }
-        vtop--;
-        if (op >= TOK_ULT && op <= TOK_GT) {
-            vtop->r = VT_CMP;
-            vtop->c.i = op;
-        }
-        break;
-    case '-':
-    case TOK_SUBC1: /* sub with carry generation */
-        opc = 5;
-        goto gen_op8;
-    case TOK_ADDC2: /* add with carry use */
-        opc = 2;
-        goto gen_op8;
-    case TOK_SUBC2: /* sub with carry use */
-        opc = 3;
-        goto gen_op8;
-    case '&':
-        opc = 4;
-        goto gen_op8;
-    case '^':
-        opc = 6;
-        goto gen_op8;
-    case '|':
-        opc = 1;
-        goto gen_op8;
-    case '*':
-        gv2(RC_INT, RC_INT);
-        r = vtop[-1].r;
-        fr = vtop[0].r;
-        if (is64_type(vtop[0].type.t) || (vtop[0].type.t & VT_UNSIGNED) ||
-            is64_type(vtop[-1].type.t) || (vtop[-1].type.t & VT_UNSIGNED)) {
-            o(0x48 | REX_BASE(fr) | (REX_BASE(r) << 2));
-        }
-        vtop--;
-        o(0xaf0f); /* imul fr, r */
-        o(0xc0 + fr + r * 8);
-        break;
-    case TOK_SHL:
-        opc = 4;
-        goto gen_shift;
-    case TOK_SHR:
-        opc = 5;
-        goto gen_shift;
-    case TOK_SAR:
-        opc = 7;
-    gen_shift:
-        opc = 0xc0 | (opc << 3);
-        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-            /* constant case */
-            vswap();
-            r = gv(RC_INT);
-            if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
-                o(0x48 | REX_BASE(r));
-                c = 0x3f;
-            } else {
-                c = 0x1f;
-            }
-            vswap();
-            c &= vtop->c.i;
-            o(0xc1); /* shl/shr/sar $xxx, r */
-            o(opc | r);
-            g(c);
-        } else {
-            /* we generate the shift in ecx */
-            gv2(RC_INT, RC_RCX);
-            r = vtop[-1].r;
-            if ((vtop[-1].type.t & VT_BTYPE) == VT_LLONG) {
-                o(0x48 | REX_BASE(r));
-            }
-            o(0xd3); /* shl/shr/sar %cl, r */
-            o(opc | r);
-        }
-        vtop--;
-        break;
-    case '/':
-    case TOK_UDIV:
-    case TOK_PDIV:
-    case '%':
-    case TOK_UMOD:
-    case TOK_UMULL:
-        /* first operand must be in eax */
-        /* XXX: need better constraint for second operand */
-        gv2(RC_RAX, RC_RCX);
-        r = vtop[-1].r;
-        fr = vtop[0].r;
-        vtop--;
-        save_reg(TREG_RDX);
-        if (op == TOK_UMULL) {
-            o(0xf7); /* mul fr */
-            o(0xe0 + fr);
-            vtop->r2 = TREG_RDX;
-            r = TREG_RAX;
-        } else {
-            if (op == TOK_UDIV || op == TOK_UMOD) {
-                o(0xf7d231); /* xor %edx, %edx, div fr, %eax */
-                o(0xf0 + fr);
-            } else {
-                if ((vtop->type.t & VT_BTYPE) & VT_LLONG) {
-                    o(0x9948); /* cqto */
-                    o(0x48 + REX_BASE(fr));
-                } else {
-                    o(0x99); /* cltd */
-                }
-                o(0xf7); /* idiv fr, %eax */
-                o(0xf8 + fr);
-            }
-            if (op == '%' || op == TOK_UMOD)
-                r = TREG_RDX;
-            else
-                r = TREG_RAX;
-        }
-        vtop->r = r;
-        break;
-    default:
-        opc = 7;
-        goto gen_op8;
-    }
-}
-
-void gen_opl(int op)
-{
-    gen_opi(op);
-}
-
-/* generate a floating point operation 'v = t1 op t2' instruction. The
-   two operands are guaranted to have the same floating point type */
-/* XXX: need to use ST1 too */
-void gen_opf(int op)
-{
-    int a, ft, fc, swapped, r;
-    int float_type =
-        (vtop->type.t & VT_BTYPE) == VT_LDOUBLE ? RC_ST0 : RC_FLOAT;
-
-    /* convert constants to memory references */
-    if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
-        vswap();
-        gv(float_type);
-        vswap();
-    }
-    if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
-        gv(float_type);
-
-    /* must put at least one value in the floating point register */
-    if ((vtop[-1].r & VT_LVAL) &&
-        (vtop[0].r & VT_LVAL)) {
-        vswap();
-        gv(float_type);
-        vswap();
-    }
-    swapped = 0;
-    /* swap the stack if needed so that t1 is the register and t2 is
-       the memory reference */
-    if (vtop[-1].r & VT_LVAL) {
-        vswap();
-        swapped = 1;
-    }
-    if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
-        if (op >= TOK_ULT && op <= TOK_GT) {
-            /* load on stack second operand */
-            load(TREG_ST0, vtop);
-            save_reg(TREG_RAX); /* eax is used by FP comparison code */
-            if (op == TOK_GE || op == TOK_GT)
-                swapped = !swapped;
-            else if (op == TOK_EQ || op == TOK_NE)
-                swapped = 0;
-            if (swapped)
-                o(0xc9d9); /* fxch %st(1) */
-            o(0xe9da); /* fucompp */
-            o(0xe0df); /* fnstsw %ax */
-            if (op == TOK_EQ) {
-                o(0x45e480); /* and $0x45, %ah */
-                o(0x40fC80); /* cmp $0x40, %ah */
-            } else if (op == TOK_NE) {
-                o(0x45e480); /* and $0x45, %ah */
-                o(0x40f480); /* xor $0x40, %ah */
-                op = TOK_NE;
-            } else if (op == TOK_GE || op == TOK_LE) {
-                o(0x05c4f6); /* test $0x05, %ah */
-                op = TOK_EQ;
-            } else {
-                o(0x45c4f6); /* test $0x45, %ah */
-                op = TOK_EQ;
-            }
-            vtop--;
-            vtop->r = VT_CMP;
-            vtop->c.i = op;
-        } else {
-            /* no memory reference possible for long double operations */
-            load(TREG_ST0, vtop);
-            swapped = !swapped;
-
-            switch(op) {
-            default:
-            case '+':
-                a = 0;
-                break;
-            case '-':
-                a = 4;
-                if (swapped)
-                    a++;
-                break;
-            case '*':
-                a = 1;
-                break;
-            case '/':
-                a = 6;
-                if (swapped)
-                    a++;
-                break;
-            }
-            ft = vtop->type.t;
-            fc = vtop->c.ul;
-            o(0xde); /* fxxxp %st, %st(1) */
-            o(0xc1 + (a << 3));
-            vtop--;
-        }
-    } else {
-        if (op >= TOK_ULT && op <= TOK_GT) {
-            /* if saved lvalue, then we must reload it */
-            r = vtop->r;
-            fc = vtop->c.ul;
-            if ((r & VT_VALMASK) == VT_LLOCAL) {
-                SValue v1;
-                r = get_reg(RC_INT);
-                v1.type.t = VT_INT;
-                v1.r = VT_LOCAL | VT_LVAL;
-                v1.c.ul = fc;
-                load(r, &v1);
-                fc = 0;
-            }
-
-            if (op == TOK_EQ || op == TOK_NE) {
-                swapped = 0;
-            } else {
-                if (op == TOK_LE || op == TOK_LT)
-                    swapped = !swapped;
-                if (op == TOK_LE || op == TOK_GE) {
-                    op = 0x93; /* setae */
-                } else {
-                    op = 0x97; /* seta */
-                }
-            }
-
-            if (swapped) {
-                o(0x7e0ff3); /* movq */
-                gen_modrm(1, r, vtop->sym, fc);
-
-                if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
-                    o(0x66);
-                }
-                o(0x2e0f); /* ucomisd %xmm0, %xmm1 */
-                o(0xc8);
-            } else {
-                if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
-                    o(0x66);
-                }
-                o(0x2e0f); /* ucomisd */
-                gen_modrm(0, r, vtop->sym, fc);
-            }
-
-            vtop--;
-            vtop->r = VT_CMP;
-            vtop->c.i = op;
-        } else {
-            /* no memory reference possible for long double operations */
-            if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
-                load(TREG_XMM0, vtop);
-                swapped = !swapped;
-            }
-            switch(op) {
-            default:
-            case '+':
-                a = 0;
-                break;
-            case '-':
-                a = 4;
-                break;
-            case '*':
-                a = 1;
-                break;
-            case '/':
-                a = 6;
-                break;
-            }
-            ft = vtop->type.t;
-            fc = vtop->c.ul;
-            if ((ft & VT_BTYPE) == VT_LDOUBLE) {
-                o(0xde); /* fxxxp %st, %st(1) */
-                o(0xc1 + (a << 3));
-            } else {
-                /* if saved lvalue, then we must reload it */
-                r = vtop->r;
-                if ((r & VT_VALMASK) == VT_LLOCAL) {
-                    SValue v1;
-                    r = get_reg(RC_INT);
-                    v1.type.t = VT_INT;
-                    v1.r = VT_LOCAL | VT_LVAL;
-                    v1.c.ul = fc;
-                    load(r, &v1);
-                    fc = 0;
-                }
-                if (swapped) {
-                    /* movq %xmm0,%xmm1 */
-                    o(0x7e0ff3);
-                    o(0xc8);
-                    load(TREG_XMM0, vtop);
-                    /* subsd  %xmm1,%xmm0 (f2 0f 5c c1) */
-                    if ((ft & VT_BTYPE) == VT_DOUBLE) {
-                        o(0xf2);
-                    } else {
-                        o(0xf3);
-                    }
-                    o(0x0f);
-                    o(0x58 + a);
-                    o(0xc1);
-                } else {
-                    if ((ft & VT_BTYPE) == VT_DOUBLE) {
-                        o(0xf2);
-                    } else {
-                        o(0xf3);
-                    }
-                    o(0x0f);
-                    o(0x58 + a);
-                    gen_modrm(0, r, vtop->sym, fc);
-                }
-            }
-            vtop--;
-        }
-    }
-}
-
-/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
-   and 'long long' cases. */
-void gen_cvt_itof(int t)
-{
-    if ((t & VT_BTYPE) == VT_LDOUBLE) {
-        save_reg(TREG_ST0);
-        gv(RC_INT);
-        if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
-            /* signed long long to float/double/long double (unsigned case
-               is handled generically) */
-            o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
-            o(0x242cdf); /* fildll (%rsp) */
-            o(0x08c48348); /* add $8, %rsp */
-        } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
-                   (VT_INT | VT_UNSIGNED)) {
-            /* unsigned int to float/double/long double */
-            o(0x6a); /* push $0 */
-            g(0x00);
-            o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
-            o(0x242cdf); /* fildll (%rsp) */
-            o(0x10c48348); /* add $16, %rsp */
-        } else {
-            /* int to float/double/long double */
-            o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
-            o(0x2404db); /* fildl (%rsp) */
-            o(0x08c48348); /* add $8, %rsp */
-        }
-        vtop->r = TREG_ST0;
-    } else {
-        save_reg(TREG_XMM0);
-        gv(RC_INT);
-        o(0xf2 + ((t & VT_BTYPE) == VT_FLOAT));
-        if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
-            (VT_INT | VT_UNSIGNED) ||
-            (vtop->type.t & VT_BTYPE) == VT_LLONG) {
-            o(0x48); /* REX */
-        }
-        o(0x2a0f);
-        o(0xc0 + (vtop->r & VT_VALMASK)); /* cvtsi2sd */
-        vtop->r = TREG_XMM0;
-    }
-}
-
-/* convert from one floating point type to another */
-void gen_cvt_ftof(int t)
-{
-    int ft, bt, tbt;
-
-    ft = vtop->type.t;
-    bt = ft & VT_BTYPE;
-    tbt = t & VT_BTYPE;
-
-    if (bt == VT_FLOAT) {
-        gv(RC_FLOAT);
-        if (tbt == VT_DOUBLE) {
-            o(0xc0140f); /* unpcklps */
-            o(0xc05a0f); /* cvtps2pd */
-        } else if (tbt == VT_LDOUBLE) {
-            /* movss %xmm0,-0x10(%rsp) */
-            o(0x44110ff3);
-            o(0xf024);
-            o(0xf02444d9); /* flds -0x10(%rsp) */
-            vtop->r = TREG_ST0;
-        }
-    } else if (bt == VT_DOUBLE) {
-        gv(RC_FLOAT);
-        if (tbt == VT_FLOAT) {
-            o(0xc0140f66); /* unpcklpd */
-            o(0xc05a0f66); /* cvtpd2ps */
-        } else if (tbt == VT_LDOUBLE) {
-            /* movsd %xmm0,-0x10(%rsp) */
-            o(0x44110ff2);
-            o(0xf024);
-            o(0xf02444dd); /* fldl -0x10(%rsp) */
-            vtop->r = TREG_ST0;
-        }
-    } else {
-        gv(RC_ST0);
-        if (tbt == VT_DOUBLE) {
-            o(0xf0245cdd); /* fstpl -0x10(%rsp) */
-            /* movsd -0x10(%rsp),%xmm0 */
-            o(0x44100ff2);
-            o(0xf024);
-            vtop->r = TREG_XMM0;
-        } else if (tbt == VT_FLOAT) {
-            o(0xf0245cd9); /* fstps -0x10(%rsp) */
-            /* movss -0x10(%rsp),%xmm0 */
-            o(0x44100ff3);
-            o(0xf024);
-            vtop->r = TREG_XMM0;
-        }
-    }
-}
-
-/* convert fp to int 't' type */
-void gen_cvt_ftoi(int t)
-{
-    int ft, bt, size, r;
-    ft = vtop->type.t;
-    bt = ft & VT_BTYPE;
-    if (bt == VT_LDOUBLE) {
-        gen_cvt_ftof(VT_DOUBLE);
-        bt = VT_DOUBLE;
-    }
-
-    gv(RC_FLOAT);
-    if (t != VT_INT)
-        size = 8;
-    else
-        size = 4;
-
-    r = get_reg(RC_INT);
-    if (bt == VT_FLOAT) {
-        o(0xf3);
-    } else if (bt == VT_DOUBLE) {
-        o(0xf2);
-    } else {
-        assert(0);
-    }
-    if (size == 8) {
-        o(0x48 + REX_BASE(r));
-    }
-    o(0x2c0f); /* cvttss2si or cvttsd2si */
-    o(0xc0 + (REG_VALUE(r) << 3));
-    vtop->r = r;
-}
-
-/* computed goto support */
-void ggoto(void)
-{
-    gcall_or_jmp(1);
-    vtop--;
-}
-
-/* end of x86-64 code generator */
-/*************************************************************/

+ 0 - 153
src/modules/native/tcc/wrap_Native.cpp

@@ -1,153 +0,0 @@
-/**
-* Copyright (c) 2006-2009 LOVE Development Team
-* 
-* This software is provided 'as-is', without any express or implied
-* warranty.  In no event will the authors be held liable for any damages
-* arising from the use of this software.
-* 
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-* 
-* 1. The origin of this software must not be misrepresented; you must not
-*    claim that you wrote the original software. If you use this software
-*    in a product, an acknowledgment in the product documentation would be
-*    appreciated but is not required.
-* 2. Altered source versions must be plainly marked as such, and must not be
-*    misrepresented as being the original software.
-* 3. This notice may not be removed or altered from any source distribution.
-**/
-
-// LOVE
-#include "wrap_Native.h"
-
-#include <filesystem/File.h>
-
-#include <cstring>
-
-namespace love
-{
-namespace native
-{
-namespace tcc
-{
-	static Native * instance = 0;
-
-	int w_compile(lua_State * L)
-	{
-		int argn = lua_gettop(L);
-		
-		// We need argn strings.
-		char ** strs = new char*[argn];
-
-		for(int i = 1; i<=argn; i++)
-		{
-			// Convert to File, if necessary.
-			if(lua_isstring(L, 1))
-				luax_convobj(L, 1, "filesystem", "newFile");
-
-			filesystem::File * file = luax_checktype<filesystem::File>(L, 1, "File", FILESYSTEM_FILE_T);
-			
-			int size = file->getSize();
-
-			// Allocate some new data. Need an extra char for the
-			// trailing 0. 
-			char * str = new char[size+1];
-			str[size] = 0;
-			file->read((void*)str, size);
-
-			// Put it in the list of strings.
-			strs[i-1] = str;
-		}
-
-		bool r = instance->compile((const char **)strs, argn);
-
-		luax_pushboolean(L, r);
-
-		// Cleanup.
-		for(int i = 0; i<argn; i++)
-			delete strs[i];
-		delete [] strs;
-
-		return 1;
-	}
-
-	int w_getSymbol(lua_State * L)
-	{
-		const char * sym = luaL_checkstring(L, 1);
-		void * ptr = instance->getSymbol(sym);
-		lua_CFunction fn = (lua_CFunction)ptr;
-
-		if(fn == 0)
-			lua_pushnil(L);
-		else
-			lua_pushcfunction(L, fn);
-
-		return 1;
-	}
-
-	/**
-	* Searcher function for modules compiled with love.native.
-	**/
-	static int searcher(lua_State * L)
-	{
-		const char * src = lua_tostring(L, 1);
-
-		int length = strlen(src);
-
-		// luaopen_ needs 8 chars.
-		char * dst = new char[length+8+1];
-		memcpy(dst, "luaopen_", 8); 
-
-		for(int i = 0; i<=length; i++)
-			dst[i+8] = (src[i] == '.') ? '_' : src[i];
-
-		void * sym = instance->getSymbol(dst);
-
-		if(sym == 0)
-			lua_pushfstring(L, "\tno symbol \"%s\" in love.native.\n", dst);
-		else
-			lua_pushcfunction(L, (lua_CFunction)sym);
-
-		delete [] dst;
-
-		return 1;
-	}
-
-	// List of functions to wrap.
-	static const luaL_Reg functions[] = {
-		{ "compile", w_compile },
-		{ "getSymbol", w_getSymbol },
-		{ 0, 0 }
-	};
-
-	int luaopen_love_native(lua_State * L)
-	{
-		if(instance == 0)
-		{
-			try 
-			{
-				instance = new Native();
-			} 
-			catch(Exception & e)
-			{
-				return luaL_error(L, e.what());
-			}
-		}
-
-		luax_register_searcher(L, searcher);
-
-		WrappedModule w;
-		w.module = instance;
-		w.name = "native";
-		w.flags = MODULE_T;
-		w.functions = functions;
-		w.types = 0;
-		w.constants = 0;
-
-		return luax_register_module(L, w);
-	}
-
-} // tcc
-} // native
-} // love

+ 33 - 19
src/modules/native/tcc/api.h → src/modules/physics/Joint.cpp

@@ -18,23 +18,37 @@
 * 3. This notice may not be removed or altered from any source distribution.
 **/
 
-#ifndef LOVE_NATIVE_TCC_API_H
-#define LOVE_NATIVE_TCC_API_H
+#include "Joint.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct tcc_function_
-{
-	const char * name; 
-	void * fn;
-} tcc_function;
-
-extern const tcc_function tcc_api[];
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LOVE_NATIVE_TCC_API_H */
+namespace love
+{
+namespace physics
+{
+	Joint::~Joint()
+	{
+	}
+
+	bool Joint::getConstant(const char * in, Type & out)
+	{
+		return types.find(in, out);
+	}
+
+	bool Joint::getConstant(Type in, const char *& out)
+	{
+		return types.find(in, out);
+	}
+
+	StringMap<Joint::Type, Joint::JOINT_MAX_ENUM>::Entry Joint::typeEntries[] = 
+	{
+		{"circle", Joint::JOINT_DISTANCE},
+		{"revolute", Joint::JOINT_REVOLUTE},
+		{"prismatic", Joint::JOINT_PRISMATIC},
+		{"mouse", Joint::JOINT_MOUSE},
+		{"pulley", Joint::JOINT_PULLEY},
+		{"gear", Joint::JOINT_GEAR},
+	};
+
+	StringMap<Joint::Type, Joint::JOINT_MAX_ENUM> Joint::types(Joint::typeEntries, sizeof(Joint::typeEntries));
+
+} // physics
+} // love

+ 14 - 3
src/modules/physics/Joint.h

@@ -23,6 +23,7 @@
 
 // LOVE
 #include <common/Object.h>
+#include <common/StringMap.h>
 
 namespace love
 {
@@ -32,18 +33,28 @@ namespace physics
 	{
 	public:
 
-		enum JointType
+		enum Type
 		{
+			JOINT_INVALID,
 			JOINT_DISTANCE,
 			JOINT_REVOLUTE,
 			JOINT_PRISMATIC,
 			JOINT_MOUSE,
 			JOINT_PULLEY,
-			JOINT_GEAR
+			JOINT_GEAR,
+			JOINT_MAX_ENUM
 		};
 
 
-		virtual ~Joint(){}
+		virtual ~Joint();
+
+		static bool getConstant(const char * in, Type & out);
+		static bool getConstant(Type in, const char *& out);
+
+	private:
+
+		static StringMap<Type, JOINT_MAX_ENUM>::Entry typeEntries[];
+		static StringMap<Type, JOINT_MAX_ENUM> types;
 	};
 
 } // physics

+ 50 - 44
src/modules/signal/posix/wrap_Signal.h → src/modules/physics/Shape.cpp

@@ -1,44 +1,50 @@
-/**
-* Copyright (c) 2006-2009 LOVE Development Team
-* 
-* This software is provided 'as-is', without any express or implied
-* warranty.  In no event will the authors be held liable for any damages
-* arising from the use of this software.
-* 
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-* 
-* 1. The origin of this software must not be misrepresented; you must not
-*    claim that you wrote the original software. If you use this software
-*    in a product, an acknowledgment in the product documentation would be
-*    appreciated but is not required.
-* 2. Altered source versions must be plainly marked as such, and must not be
-*    misrepresented as being the original software.
-* 3. This notice may not be removed or altered from any source distribution.
-**/
-
-#ifndef LOVE_SIGNAL_POSIX_WRAP_SIGNAL_H
-#define LOVE_SIGNAL_POSIX_WRAP_SIGNAL_H
-
-// LOVE
-#include <common/config.h>
-#include "Signal.h"
-
-namespace love
-{
-namespace signal
-{
-namespace posix
-{
-	int w_hook(lua_State *L);
-	int w_setCallback(lua_State *L);
-	int w_raise(lua_State *L);
-
-	extern "C" LOVE_EXPORT int luaopen_love_signal(lua_State * L);
-
-} // posix
-} // signal
-} // love
-
-#endif // LOVE_SIGNAL_POSIX_WRAP_SIGNAL_H
+/**
+* Copyright (c) 2006-2009 LOVE Development Team
+* 
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* 
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#include "Shape.h"
+
+namespace love
+{
+namespace physics
+{
+	Shape::~Shape()
+	{
+	}
+
+	bool Shape::getConstant(const char * in, Type & out)
+	{
+		return types.find(in, out);
+	}
+
+	bool Shape::getConstant(Type in, const char *& out)
+	{
+		return types.find(in, out);
+	}
+
+	StringMap<Shape::Type, Shape::SHAPE_MAX_ENUM>::Entry Shape::typeEntries[] = 
+	{
+		{"circle", Shape::SHAPE_CIRCLE},
+		{"polygon", Shape::SHAPE_POLYGON},
+	};
+
+	StringMap<Shape::Type, Shape::SHAPE_MAX_ENUM> Shape::types(Shape::typeEntries, sizeof(Shape::typeEntries));
+
+} // physics
+} // love

+ 13 - 2
src/modules/physics/Shape.h

@@ -23,6 +23,7 @@
 
 // LOVE
 #include <common/Object.h>
+#include <common/StringMap.h>
 
 namespace love
 {
@@ -32,13 +33,23 @@ namespace physics
 	{
 	public:
 
-		enum ShapeType
+		enum Type
 		{
+			SHAPE_INVALID,
 			SHAPE_CIRCLE, 
 			SHAPE_POLYGON,
+			SHAPE_MAX_ENUM
 		};
 
-		virtual ~Shape(){}
+		virtual ~Shape();
+
+		static bool getConstant(const char * in, Type & out);
+		static bool getConstant(Type in, const char *& out);
+
+	private:
+
+		static StringMap<Type, SHAPE_MAX_ENUM>::Entry typeEntries[];
+		static StringMap<Type, SHAPE_MAX_ENUM> types;
 	};
 
 } // physics

+ 2 - 2
src/modules/physics/box2d/Joint.cpp

@@ -56,7 +56,7 @@ namespace box2d
 		joint = 0;
 	}
 
-	int Joint::getType() const
+	Joint::Type Joint::getType() const
 	{
 		switch(joint->GetType())
 		{
@@ -73,7 +73,7 @@ namespace box2d
 		case e_gearJoint: 
 			return JOINT_GEAR;
 		default:
-			return -1;
+			return JOINT_INVALID;
 		}
 	}
 

+ 1 - 1
src/modules/physics/box2d/Joint.h

@@ -81,7 +81,7 @@ namespace box2d
 		/**
 		* Gets the type of joint.
 		**/
-		int getType() const;
+		Type getType() const;
 
 		/**
 		* Gets the anchor positions of the Joint in world

+ 2 - 2
src/modules/physics/box2d/Shape.cpp

@@ -50,7 +50,7 @@ namespace box2d
 		data = 0;
 	}
 
-	int Shape::getType() const
+	Shape::Type Shape::getType() const
 	{
 		switch(shape->GetType())
 		{
@@ -59,7 +59,7 @@ namespace box2d
 		case e_polygonShape:
 			return SHAPE_POLYGON;
 		default:
-			return -1;
+			return SHAPE_INVALID;
 		}
 	}
 

+ 1 - 1
src/modules/physics/box2d/Shape.h

@@ -86,7 +86,7 @@ namespace box2d
 		* Gets the type of Shape. Useful for 
 		* debug drawing.
 		**/
-		int getType() const;
+		Type getType() const;
 
 		/**
 		* Sets the friction of the Shape.

+ 4 - 1
src/modules/physics/box2d/wrap_Joint.cpp

@@ -20,6 +20,7 @@
 
 // LOVE
 #include "wrap_Joint.h"
+#include <common/StringMap.h>
 
 namespace love
 {
@@ -35,7 +36,9 @@ namespace box2d
 	int w_Joint_getType(lua_State * L)
 	{
 		Joint * t = luax_checkjoint(L, 1);
-		lua_pushinteger(L, t->getType());
+		const char * type = "";
+		Joint::getConstant(t->getType(), type);
+		lua_pushstring(L, type);
 		return 1;
 	}
 

+ 0 - 15
src/modules/physics/box2d/wrap_Physics.cpp

@@ -236,20 +236,6 @@ namespace box2d
 		0
 	};
 
-	// List of constants.
-	static const Constant constants[] = {
-		{ "shape_circle", Shape::SHAPE_CIRCLE },
-		{ "shape_polygon", Shape::SHAPE_POLYGON },
-
-		{ "joint_distance", Joint::JOINT_DISTANCE },
-		{ "joint_revolute", Joint::JOINT_REVOLUTE },
-		{ "joint_prismatic", Joint::JOINT_PRISMATIC },
-		{ "joint_mouse", Joint::JOINT_MOUSE },	
-		{ "joint_pulley", Joint::JOINT_PULLEY },	
-		{ "joint_gear", Joint::JOINT_GEAR },
-		{ 0, 0 }
-	};
-
 	int luaopen_love_physics(lua_State * L)
 	{
 		if(instance == 0)
@@ -270,7 +256,6 @@ namespace box2d
 		w.flags = MODULE_T;
 		w.functions = functions;
 		w.types = types;
-		w.constants = constants;
 
 		return luax_register_module(L, w);
 	}

+ 4 - 1
src/modules/physics/box2d/wrap_Shape.cpp

@@ -19,6 +19,7 @@
 **/
 
 #include "wrap_Shape.h"
+#include <common/StringMap.h>
 
 namespace love
 {
@@ -34,7 +35,9 @@ namespace box2d
 	int w_Shape_getType(lua_State * L)
 	{
 		Shape * t = luax_checkshape(L, 1);
-		lua_pushinteger(L, t->getType());
+		const char * type = "";
+		Shape::getConstant(t->getType(), type);
+		lua_pushstring(L, type);
 		return 1;
 	}
 

+ 0 - 103
src/modules/signal/posix/wrap_Signal.cpp

@@ -1,103 +0,0 @@
-/**
-* Copyright (c) 2006-2009 LOVE Development Team
-* 
-* This software is provided 'as-is', without any express or implied
-* warranty.  In no event will the authors be held liable for any damages
-* arising from the use of this software.
-* 
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-* 
-* 1. The origin of this software must not be misrepresented; you must not
-*    claim that you wrote the original software. If you use this software
-*    in a product, an acknowledgment in the product documentation would be
-*    appreciated but is not required.
-* 2. Altered source versions must be plainly marked as such, and must not be
-*    misrepresented as being the original software.
-* 3. This notice may not be removed or altered from any source distribution.
-**/
-
-#include "wrap_Signal.h"
-
-// LOVE
-#include <common/runtime.h>
-
-#include "Signal.h"
-
-namespace love
-{
-namespace signal
-{
-namespace posix
-{
-	static Signal * instance = 0;
-	
-	int w_hook(lua_State *L)
-	{
-		luaL_argcheck(L, lua_isnumber(L, 1), 1, "Expected number");
-		lua_pushboolean(L, instance->hook(lua_tointeger(L, 1)));
-		return 1;
-	}
-	
-	int w_setCallback(lua_State *L)
-	{
-		luaL_argcheck(L, lua_isfunction(L, 1), 1, "Expected function");
-		instance->setCallback(L);
-		return 0;
-	}
-	
-	int w_raise(lua_State *L)
-	{
-		luaL_argcheck(L, lua_isnumber(L, 1), 1, "Expected number");
-		lua_pushboolean(L, instance->raise(lua_tointeger(L, 1)));
-		return 1;
-	}
-
-	// List of functions to wrap.
-	static const luaL_Reg functions[] = {
-		{ "hook", w_hook },
-		{ "setCallback", w_setCallback }, 
-		{ "raise", w_raise },
-		{ 0, 0 }
-	};
-	
-	static const Constant constants[] = {
-		{ "signal_abrt", SIGABRT },
-		{ "signal_fpe", SIGFPE },
-		{ "signal_ill", SIGILL },
-		{ "signal_int", SIGINT },
-		{ "signal_segv", SIGSEGV },
-		{ "signal_term", SIGTERM },
-		{ 0, 0 }
-	};
-
-	int luaopen_love_signal(lua_State * L)
-	{
-		if(instance == 0)
-		{
-			try 
-			{
-				instance = new Signal();
-			} 
-			catch(Exception & e)
-			{
-				return luaL_error(L, e.what());
-			}
-		}
-
-
-		WrappedModule w;
-		w.module = instance;
-		w.name = "signal";
-		w.flags = MODULE_T;
-		w.functions = functions;
-		w.types = 0;
-		w.constants = constants;
-
-		return luax_register_module(L, w);
-	}
-
-} // posix
-} // signal
-} // love

+ 0 - 1
src/modules/sound/wrap_Sound.cpp

@@ -135,7 +135,6 @@ namespace sound
 		w.flags = MODULE_SOUND_T;
 		w.functions = functions;
 		w.types = types;
-		w.constants = 0;
 
 		return luax_register_module(L, w);
 	}

+ 0 - 1
src/modules/timer/sdl/wrap_Timer.cpp

@@ -91,7 +91,6 @@ namespace sdl
 		w.flags = MODULE_T;
 		w.functions = functions;
 		w.types = 0;
-		w.constants = 0;
 
 		return luax_register_module(L, w);
 	}

+ 10 - 13
src/scripts/boot.lua

@@ -79,25 +79,25 @@ function love.createhandlers()
 
 	-- Standard callback handlers.
 	love.handlers = {
-		[love.event_keypressed] = function (b, u)
+		kp = function (b, u)
 			if love.keypressed then love.keypressed(b, u) end
 		end,
-		[love.event_keyreleased] = function (b)
+		kr = function (b)
 			if love.keyreleased then love.keyreleased(b) end
 		end,
-		[love.event_mousepressed] = function (x,y,b)
+		mp = function (x,y,b)
 			if love.mousepressed then love.mousepressed(x,y,b) end
 		end,
-		[love.event_mousereleased] = function (x,y,b)
+		mr = function (x,y,b)
 			if love.mousereleased then love.mousereleased(x,y,b) end
 		end,
-		[love.event_joystickpressed] = function (j,b)
+		jp = function (j,b)
 			if love.joystickpressed then love.joystickpressed(j,b) end
 		end,
-		[love.event_joystickreleased] = function (j,b)
+		jr = function (j,b)
 			if love.joystickreleased then love.joystickreleased(j,b) end
 		end,
-		[love.event_quit] = function ()
+		q = function ()
 			return
 		end,
 	}
@@ -147,9 +147,6 @@ function love.init()
 			audio = true,
 			physics = true,
 			sound = true,
-			native = true,
-			font = true,
-			signal = true,
 		},
 	}
 
@@ -200,7 +197,7 @@ function love.run()
 
 		-- Process events.
 		for e,a,b,c in love.event.poll() do
-			if e == love.event_quit then return end
+			if e == "q" then return end
 			love.handlers[e](a,b,c)
 		end
 
@@ -674,8 +671,8 @@ function love.errhand(msg)
 	while true do
 		e, a, b, c = love.event.wait()
 		
-		if e == love.event_quit then return end
-		if e == love.event_keypressed and a == love.key_escape then
+		if e == "q" then return end
+		if e == "kp" and a == "escape" then
 			return
 		end
 

Some files were not shown because too many files changed in this diff