01085 :
01086
01087 This function virtually unwinds
the specfified function by executing its
01088 prologue code backwards.
01089
01090 If
the function
is a leaf function, then
the address where
control left
01091
the previous frame
is obtained from
the context record. If
the function
01092
is a nested function, but not an exception or interrupt frame, then
the
01093 prologue code
is executed backwards and
the address where
control left
01094
the previous frame
is obtained from
the updated context record.
01095
01096 Otherwise, an exception or interrupt entry to
the system
is being unwound
01097 and a specially coded prologue restores
the return address twice. Once
01098 from
the fault instruction address and once from
the saved
return address
01099
register. The first restore
is returned as
the function value and
the
01100 second restore
is place in
the updated context record.
01101
01102 If a context pointers record
is specified, then
the address where each
01103 nonvolatile registers
is restored from
is recorded in
the appropriate
01104 element of
the context pointers record.
01105
01106 N.B. This routine handles 64-bit context records.
01107
01108 Arguments:
01109
01110 ControlPc - Supplies
the address where
control left
the specified
01111 function.
01112
01113 N.B. The
low order bit of
this argument
is used to denote
the
01114 context record
type. If
the low order bit
is clear, then
01115
the context record contains 32-bit information. Otherwise,
01116
it contains 64-bit information.
01117
01118 FunctionEntry - Supplies
the address of
the function table entry
for the
01119 specified function.
01120
01121 ContextRecord - Supplies
the address of a context record.
01122
01123 InFunction - Supplies a pointer to a variable that receives whether
the
01124
control PC
is within
the current function.
01125
01126 EstablisherFrame - Supplies a pointer to a variable that receives
the
01127
the establisher frame pointer value.
01128
01129 ContextPointers - Supplies an optional pointer to a context pointers
01130 record.
01131
01132 Return Value:
01133
01134 The address where
control left
the previous frame
is returned as
the
01135 function value.
01136
01137 --*/
01138
01139 {
01140
01141 ULONG Address;
01142 ULONG DecrementOffset;
01143 ULONG DecrementRegister;
01144 PULONG FloatingRegister;
01145 ULONG Function;
01146 MIPS_INSTRUCTION Instruction;
01147 PULONGLONG IntegerRegister;
01148 ULONG NextPc;
01149 LONG
Offset;
01150 ULONG Opcode;
01151 ULONG Rd;
01152 BOOLEAN RestoredRa;
01153 BOOLEAN RestoredSp;
01154 ULONG Rs;
01155 ULONG Rt;
01156
01157
01158
01159
01160
01161
01162
01163
if ((ControlPc & 1) == 0) {
01164
return RtlpVirtualUnwind32(ControlPc,
01165 FunctionEntry,
01166 ContextRecord,
01167 InFunction,
01168 EstablisherFrame,
01169 ContextPointers);
01170
01171 }
else {
01172
01173
01174
01175
01176
01177 FloatingRegister = &ContextRecord->FltF0;
01178 IntegerRegister = &ContextRecord->XIntZero;
01179
01180
01181
01182
01183
01184
01185
01186
01187 ControlPc &= ~1;
01188
if (*((PULONG)ControlPc) == JUMP_RA) {
01189 *InFunction =
FALSE;
01190 Instruction.Long = *((PULONG)ControlPc + 1);
01191 Opcode = Instruction.i_format.Opcode;
01192
Offset = Instruction.i_format.Simmediate;
01193 Rd = Instruction.r_format.Rd;
01194 Rs = Instruction.i_format.Rs;
01195 Rt = Instruction.i_format.Rt;
01196 Function = Instruction.r_format.Function;
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
if ((Opcode == ADDIU_OP) && (Rt ==
SP) && (Rs ==
SP)) {
01208 IntegerRegister[
SP] +=
Offset;
01209
01210 }
else if ((Opcode == SPEC_OP) && (Function == ADDU_OP) &&
01211 (Rd ==
SP) && (Rs ==
SP)) {
01212 IntegerRegister[
SP] += IntegerRegister[Rt];
01213 }
01214
01215 *EstablisherFrame = (ULONG)ContextRecord->XIntSp;
01216
return (ULONG)ContextRecord->XIntRa;
01217 }
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
if ((ControlPc < FunctionEntry->BeginAddress) ||
01228 (ControlPc >= FunctionEntry->PrologEndAddress)) {
01229 *InFunction =
TRUE;
01230 ControlPc = FunctionEntry->PrologEndAddress;
01231
01232 }
else {
01233 *InFunction =
FALSE;
01234 }
01235
01236
01237
01238
01239
01240
01241 DecrementRegister = 0;
01242 *EstablisherFrame = (ULONG)ContextRecord->XIntSp;
01243 NextPc = (ULONG)(ContextRecord->XIntRa - 4);
01244 RestoredRa =
FALSE;
01245 RestoredSp =
FALSE;
01246
while (ControlPc > FunctionEntry->BeginAddress) {
01247
01248
01249
01250
01251
01252
01253 ControlPc -= 4;
01254 Instruction.Long = *((PULONG)ControlPc);
01255 Opcode = Instruction.i_format.Opcode;
01256
Offset = Instruction.i_format.Simmediate;
01257 Rd = Instruction.r_format.Rd;
01258 Rs = Instruction.i_format.Rs;
01259 Rt = Instruction.i_format.Rt;
01260 Address = (ULONG)(
Offset + IntegerRegister[Rs]);
01261
if (Opcode == SW_OP) {
01262
01263
01264
01265
01266
01267
01268
01269
01270
if (Rs ==
SP) {
01271 IntegerRegister[Rt] = *((PLONG)Address);
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
if (Rt ==
RA) {
01284
if (RestoredRa ==
FALSE) {
01285 NextPc = (ULONG)(ContextRecord->XIntRa - 4);
01286 RestoredRa =
TRUE;
01287
01288 }
else {
01289 NextPc += 4;
01290 }
01291
01292 }
else if (Rt ==
SP) {
01293
if (RestoredSp ==
FALSE) {
01294 *EstablisherFrame = (ULONG)ContextRecord->XIntSp;
01295 RestoredSp =
TRUE;
01296 }
01297 }
01298
01299
01300
01301
01302
01303
01304
01305
if (ARGUMENT_PRESENT(ContextPointers)) {
01306 ContextPointers->XIntegerContext[Rt] = (PULONGLONG)Address;
01307 }
01308 }
01309
01310 }
else if (Opcode == SD_OP) {
01311
01312
01313
01314
01315
01316
01317
01318
01319
if (Rs ==
SP) {
01320 IntegerRegister[Rt] = *((PULONGLONG)Address);
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
if (Rt ==
RA) {
01333
if (RestoredRa ==
FALSE) {
01334 NextPc = (ULONG)(ContextRecord->XIntRa - 4);
01335 RestoredRa =
TRUE;
01336
01337 }
else {
01338 NextPc += 4;
01339 }
01340
01341 }
else if (Rt ==
SP) {
01342
if (RestoredSp ==
FALSE) {
01343 *EstablisherFrame = (ULONG)ContextRecord->XIntSp;
01344 RestoredSp =
TRUE;
01345 }
01346 }
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
if (ARGUMENT_PRESENT(ContextPointers)) {
01358 ContextPointers->XIntegerContext[Rt] = (PLONGLONG)((ULONG)Address | 1);
01359 }
01360 }
01361
01362 }
else if (Opcode == SWC1_OP) {
01363
01364
01365
01366
01367
01368
01369
01370
01371
if (Rs ==
SP) {
01372 FloatingRegister[Rt] = *((PULONG)Address);
01373
01374
01375
01376
01377
01378
01379
01380
if (ARGUMENT_PRESENT(ContextPointers)) {
01381 ContextPointers->FloatingContext[Rt] = (PULONG)Address;
01382 }
01383 }
01384
01385 }
else if (Opcode == SDC1_OP) {
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
if (Rs ==
SP) {
01396 FloatingRegister[Rt] = *((PULONG)Address);
01397 FloatingRegister[Rt + 1] = *((PULONG)(Address + 4));
01398
01399
01400
01401
01402
01403
01404
01405
if (ARGUMENT_PRESENT(ContextPointers)) {
01406 ContextPointers->FloatingContext[Rt] = (PULONG)Address;
01407 ContextPointers->FloatingContext[Rt + 1] = (PULONG)(Address + 4);
01408 }
01409 }
01410
01411 }
else if (Opcode == ADDIU_OP) {
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
if ((Rs ==
SP) && (Rt ==
SP)) {
01425 IntegerRegister[
SP] -=
Offset;
01426
if (RestoredSp ==
FALSE) {
01427 *EstablisherFrame = (ULONG)ContextRecord->XIntSp;
01428 RestoredSp =
TRUE;
01429 }
01430
01431 }
else if ((Rt == DecrementRegister) && (Rs ==
ZERO)) {
01432 IntegerRegister[
SP] +=
Offset;
01433
if (RestoredSp ==
FALSE) {
01434 *EstablisherFrame = (ULONG)ContextRecord->XIntSp;
01435 RestoredSp =
TRUE;
01436 }
01437 }
01438
01439 }
else if (Opcode == ORI_OP) {
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
if ((Rs == DecrementRegister) && (Rt == DecrementRegister)) {
01451 DecrementOffset = (
Offset & 0xffff);
01452
01453 }
else if ((Rt == DecrementRegister) && (Rs ==
ZERO)) {
01454 IntegerRegister[
SP] += (
Offset & 0xffff);
01455
if (RestoredSp ==
FALSE) {
01456 *EstablisherFrame = (ULONG)ContextRecord->XIntSp;
01457 RestoredSp =
TRUE;
01458 }
01459 }
01460
01461 }
else if (Opcode == SPEC_OP) {
01462
01463
01464
01465
01466
01467
01468
01469
01470 Function = Instruction.r_format.Function;
01471
if ((Function == ADDU_OP) || (Function == OR_OP)) {
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
if (Rt ==
ZERO) {
01483 IntegerRegister[Rs] = IntegerRegister[Rd];
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
if (Rs ==
RA) {
01494
if (RestoredRa ==
FALSE) {
01495 NextPc = (ULONG)(ContextRecord->XIntRa - 4);
01496 RestoredRa =
TRUE;
01497
01498 }
else {
01499 NextPc += 4;
01500 }
01501 }
01502
01503 }
else if (Rs ==
ZERO) {
01504 IntegerRegister[Rt] = IntegerRegister[Rd];
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
if (Rt ==
RA) {
01515
if (RestoredRa ==
FALSE) {
01516 NextPc = (ULONG)(ContextRecord->XIntRa - 4);
01517 RestoredRa =
TRUE;
01518
01519 }
else {
01520 NextPc += 4;
01521 }
01522 }
01523 }
01524
01525 }
else if (Function == SUBU_OP) {
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
if ((Rd ==
SP) && (Rs ==
SP)) {
01537 DecrementRegister = Rt;
01538 }
01539 }
01540
01541 }
else if (Opcode == LUI_OP) {
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
if (Rt == DecrementRegister) {
01552 DecrementRegister = 0;
01553 IntegerRegister[
SP] += (LONG)(DecrementOffset + (
Offset << 16));
01554
if (RestoredSp ==
FALSE) {
01555 *EstablisherFrame = (ULONG)(ContextRecord->XIntSp);
01556 RestoredSp =
TRUE;
01557 }
01558 }
01559 }
01560 }
01561
01562
01563
01564
01565
01566 ContextRecord->XIntZero = 0;
01567
return NextPc;
01568 }
01569 }