File: EmSubroutine.h

package info (click to toggle)
pose 3.5-7
  • links: PTS
  • area: contrib
  • in suites: sarge
  • size: 14,136 kB
  • ctags: 29,490
  • sloc: cpp: 93,990; ansic: 62,838; sh: 27,519; perl: 1,891; python: 1,242; makefile: 652
file content (377 lines) | stat: -rw-r--r-- 11,101 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
/* -*- mode: C++; tab-width: 4 -*- */
/* ===================================================================== *\
	Copyright (c) 2001 Palm, Inc. or its subsidiaries.
	All rights reserved.

	This file is part of the Palm OS Emulator.

	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.
\* ===================================================================== */

#ifndef EmSubroutine_h
#define EmSubroutine_h

#include <string>
#include <vector>

/*
	Overview:
	---------

		From time to time, Poser needs to interfere with emulated code
		as it calls from one subroutine to another.  In some cases, Poser
		needs to intercept the call on entry or exit and perform some
		actions.  On rarer occasions, Poser needs to completely replace
		the called subroutine, prohibiting from executing entirely.  And
		on other occasions, Poser needs to be able to call a subroutine
		in the emulated environment.

		The EmSubroutine class helps in these activities.  For the cases
		where it is patching a called subroutine (possibly replacing it
		entirely), Poser needs to read the parameters passed to the subroutine,
		and possibly even provide a function result.  For the cases where
		is calling an emulated subroutine, Poser needs to push parameters
		onto the emulated stack, and then read back any function result
		when the subroutine returns.

		Both of these activities (calling an emulated function, and being
		called from an emulated function) require that Poser know the
		format of the stack (that is, the number, order, and type of the
		parameters pushed or to be pushed onto the stack).

		The EmSubroutine class has methods used to define the stack format.
		When defining the stack format, the EmSubroutine class needs to
		provide one to three pieces of information for each parameter:

			*	The parameter type.
			*	An optional parameter name.
			*	An optional parameter value.


	Calling an emulated function:
	-----------------------------

		When Poser needs to call an emulated function, it takes the following
		steps:

			*	Creates an EmSubroutine object.

			*	Specifies the types and values of the parameters with a
				specification string passed to the object's constructor.

			*	Sets the values of the parameters with multiple calls
				to SetParamVal.

			*	Calls the function by calling Call.

			*	Reads any return value by calling GetReturnVal.

		For example:

			Err DmCreateDatabase (UInt16 cardNo, const Char * const nameP, 
								UInt32 creator, UInt32 type, Boolean resDB)
			{
				// Create subroutine object.

				EmSubroutine	sub (	"Err",
										"UInt16 cardNo,"
										"const Char * const nameP,"
										"UInt32 creator,"
										"UInt32 type,"
										"Boolean resDB",
										true);

				// Set parameter values.

				sub.SetParamVal ("cardNo", cardNo);
				sub.SetParamVal ("nameP", nameP);
				sub.SetParamVal ("creator", creator);
				sub.SetParamVal ("type", type);
				sub.SetParamVal ("resDB", resDB);

				// Call the subroutine.

				sub.Call (sysTrapDmCreateDatabase);

				// Get and return subroutine result.

				Err result;
				sub.GetReturnVal (result);
				return result;
			}


	Being called by an emulated function:
	-------------------------------------

		When Poser needs to respond to an emulated function making a
		subroutine call, it takes the following steps:

			*	Creates an EmSubroutine object.

			*	Specifies the types and values of the parameters with a
				specification string passed to the object's constructor.

			*	Retrieves the values on the stack with multple calls
				to GetParamVal.

			*	Optionally specifies a function return value by calling
				SetReturnVal.

		For example:

			CallROMType SysHeadpatch::ExgDoDialog (void)
			{
				// Boolean ExgDoDialog (ExgSocketPtr socketP,
				//						ExgDialogInfoType* infoP,
				//						Err* errP)

				// If this patch is not supposed to do anything special
				// right now, just return, saying that the ROM version
				// should be executed as normal.

				if (!gAutoAcceptBeamDialogs)
					return kExecuteROM;

				// Create subroutine object.

				EmSubroutine	sub (	"Boolean",
										"ExgSocketPtr socketP,"
										"ExgDialogInfoType* infoP,"
										"Err* errP",
										false);

				// Read the parameter values.

				void*	socketP;
				void*	infoP;
				void*	errP;

				sub.GetParamVal ("socketP", socketP);
				sub.GetParamVal ("infoP", infoP);
				sub.GetParamVal ("errP", errP);

				// If no socket, just return, saying that the ROM version
				// should be executed as normal.

				if (!socketP)
					return kExecuteROM;

				// Set the "errP" parameter to zero.

				sub.SetParamRef ("errP", (Err) errNone);

				// Set the function result to "true".

				sub.SetReturnVal ((Bool) true);

				// Return, saying that we completely implemented the
				// function and that the ROM version should not be
				// executed at all.

				return kSkipROM;
			}
*/


typedef string		EmParamName;
typedef const char*	EmParamNameArg;
typedef const char*	EmParamDecl;
typedef const char*	EmParamListDecl;


enum EmParamType
{
	kEm_Unknown,	// Unknown type.
	kEm_Void,		// Return type, and generic pointer type

	kEm_SI1,		// 1-byte signed integer
	kEm_SI2,		// 2-byte signed integer
	kEm_SI4,		// 4-byte signed integer
	kEm_SI8,		// 8-byte signed integer

	kEm_UI1,		// 1-byte unsigned integer
	kEm_UI2,		// 2-byte unsigned integer
	kEm_UI4,		// 4-byte unsigned integer
	kEm_UI8,		// 8-byte unsigned integer

	kEm_FP4,		// 4-byte floating point
	kEm_FP8,		// 8-byte floating point
	kEm_FP16		// 16-byte floating point
};


struct EmParamInfo
{
	const char*	fTypeName;

	// If the parameter is passed by value, this holds the type of
	// the value.  If the parameter is pass by reference, this holds
	// the type pointed to.

	EmParamType	fType;

	// If this is false, the parameter is passed by value, and pushed
	// directly onto the stack.  If this is true, the parameter is
	// passed by reference, and a pointer to the value is pushed onto
	// the stack.
	//
	// If the EmParamInfo is used to record information about a function's
	// return value, fByRef can indicate where the return value is stored.
	// On 68K platforms, pointers are stored in A0, while directly scalar
	// values are stored in D0.

	Bool		fByRef;
}; 

struct EmParam
{
	EmParam (void) :
		fName (),
		fType (kEm_Void),
		fStackOffset (0),
		fByRef (false)
	{
	}

	EmParamName	fName;

	EmParamType	fType;
	long		fStackOffset;
	Bool		fByRef;
};

typedef vector<EmParam>	EmParamList;

class EmSubroutineCPU;

#define kForCalling true
#define kForBeingCalled false

enum
{
	kEmErrUnsupportedType = 1,
	kEmErrUnknownParameter,
	kEmErrTypeMismatch
};



#define VIRTUAL

class EmSubroutine
{
	public:
								EmSubroutine	(void);
		VIRTUAL					~EmSubroutine	(void);

		VIRTUAL Err				DescribeDecl	(EmParamDecl, EmParamListDecl);
		VIRTUAL Err				AddParam		(EmParamDecl);
		VIRTUAL Err				PrepareStack	(Bool forCalling, Bool forStdArgs);
		VIRTUAL Err				PrepareStack	(emuptr);
		VIRTUAL Err				Reset			(void);

		// Read the parameter indicated by the given parameter name
		// and return it as the given type.
		//
		// !!! What to do if the given parameter type is not the same
		// as the return parameter type?

		VIRTUAL Err				GetParamVal		(EmParamNameArg, int8&);
		VIRTUAL Err				GetParamVal		(EmParamNameArg, int16&);
		VIRTUAL Err				GetParamVal		(EmParamNameArg, int32&);
		VIRTUAL Err				GetParamVal		(EmParamNameArg, int64&);
		VIRTUAL Err				GetParamVal		(EmParamNameArg, uint8&);
		VIRTUAL Err				GetParamVal		(EmParamNameArg, uint16&);
		VIRTUAL Err				GetParamVal		(EmParamNameArg, uint32&);
		VIRTUAL Err				GetParamVal		(EmParamNameArg, uint64&);
		VIRTUAL Err				GetParamVal		(EmParamNameArg, float&);
		VIRTUAL Err				GetParamVal		(EmParamNameArg, double&);
		VIRTUAL Err				GetParamVal		(EmParamNameArg, long double&);

		// Get the value returned by the function.

		VIRTUAL Err				GetReturnVal	(int8&);
		VIRTUAL Err				GetReturnVal	(int16&);
		VIRTUAL Err				GetReturnVal	(int32&);
		VIRTUAL Err				GetReturnVal	(int64&);
		VIRTUAL Err				GetReturnVal	(uint8&);
		VIRTUAL Err				GetReturnVal	(uint16&);
		VIRTUAL Err				GetReturnVal	(uint32&);
		VIRTUAL Err				GetReturnVal	(uint64&);
		VIRTUAL Err				GetReturnVal	(float&);
		VIRTUAL Err				GetReturnVal	(double&);
		VIRTUAL Err				GetReturnVal	(long double&);

		// Store the given value into the memory pointed to by the
		// pointer parameter indicated by the given parameter name.
		// These functions are useful for returning results in "pass
		// by reference" parameters.
		//
		// !!! What to do if the specified parameter is not a pointer
		// type.  Of less concern, what if it is not the right type?

		VIRTUAL Err				SetParamVal		(EmParamNameArg, int8);
		VIRTUAL Err				SetParamVal		(EmParamNameArg, int16);
		VIRTUAL Err				SetParamVal		(EmParamNameArg, int32);
		VIRTUAL Err				SetParamVal		(EmParamNameArg, int64);
		VIRTUAL Err				SetParamVal		(EmParamNameArg, uint8);
		VIRTUAL Err				SetParamVal		(EmParamNameArg, uint16);
		VIRTUAL Err				SetParamVal		(EmParamNameArg, uint32);
		VIRTUAL Err				SetParamVal		(EmParamNameArg, uint64);
		VIRTUAL Err				SetParamVal		(EmParamNameArg, float);
		VIRTUAL Err				SetParamVal		(EmParamNameArg, double);
		VIRTUAL Err				SetParamVal		(EmParamNameArg, long double);

		// Set the value to be returned by the function.

		VIRTUAL Err				SetReturnVal	(int8);
		VIRTUAL Err				SetReturnVal	(int16);
		VIRTUAL Err				SetReturnVal	(int32);
		VIRTUAL Err				SetReturnVal	(int64);
		VIRTUAL Err				SetReturnVal	(uint8);
		VIRTUAL Err				SetReturnVal	(uint16);
		VIRTUAL Err				SetReturnVal	(uint32);
		VIRTUAL Err				SetReturnVal	(uint64);
		VIRTUAL Err				SetReturnVal	(float);
		VIRTUAL Err				SetReturnVal	(double);
		VIRTUAL Err				SetReturnVal	(long double);

		// Call the given system function.  The first form merely
		// calls the indicated function.  The second stores the
		// selector in D2 and then calls the function.
		//
		// !!! Needs to be extended for calling library functions,
		// calling HostControl functions (which take the selector
		// on the stack), and may need to be adjusted according to
		// however ARM functions will be specified.

		VIRTUAL Err				Call			(uint16 trapWord);
		VIRTUAL Err				CallSelector	(uint16 trapWord, uint16 selector);

	private:
		uint32					GetReturnRegInteger	(void);
		emuptr					GetReturnRegPointer	(void);

		void					SetReturnRegInteger	(uint32);
		void					SetReturnRegPointer	(void*);

		EmSubroutineCPU*		GetCPU			(void);
		Bool					Is68K			(void);
		Bool					IsARM			(void);

		Err						ParseParamDecl	(EmParamDecl, EmParam&);
		string					GetToken		(EmParamDecl, string::size_type& offset);
		EmParamList::iterator	FindParam		(EmParamNameArg);

	private:
		EmSubroutineCPU*		fCPU;
		EmParamList				fParams;
		EmParam					fReturnType;
		long					fStackSize;
};

#endif	// EmSubroutine_h