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
|