/*** ia64_reg.c - processor-specific register structures
*
*   Copyright <C> 1990-2001, Microsoft Corporation
*   Copyright <C> 1995, Intel Corporation
*
*   Purpose:
*       Structures used to parse and access register and flag
*       fields.
*
*   Revision History:
*
*   [-]  10-Jan-1995 HC         Modified for IA64. All registers are 64-bit
*                                except floating point registers are 128-bit.
*   [-]  01-Jul-1990 Richk      Created.
*
*************************************************************************/

#include "ntsdp.hpp"
#include "ia64_dis.h"

// See Get/SetRegVal comments in machine.hpp.
#define RegValError Do_not_use_GetSetRegVal_in_machine_implementations
#define GetRegVal(index, val)   RegValError
#define GetRegVal32(index)      RegValError
#define GetRegVal64(index)      RegValError
#define SetRegVal(index, val)   RegValError
#define SetRegVal32(index, val) RegValError
#define SetRegVal64(index, val) RegValError

// TBD
#define IS_FLOATING_SAVED(Register) ((SAVED_FLOATING_MASK >> Register) & 1L)
#define IS_INTEGER_SAVED(Register) ((SAVED_INTEGER_MASK >> Register) & 1L)


//
// Define saved register masks.
//
#define SAVED_FLOATING_MASK 0xfff00000  // saved floating registers
#define SAVED_INTEGER_MASK 0xf3ffff02   // saved integer registers


//
// Number of Data Breakpoints available under IA64 
//
// XXX olegk - increase to 4 in future 
// (and then remove appropriate check at MapDbgSlotIa64ToX86)
#define IA64_REG_MAX_DATA_BREAKPOINTS 2

//
// This parallels ntreg.h. Symbol assignment models ksia64.h
//

CHAR    szDBI0[] = "dbi0";
CHAR    szDBI1[] = "dbi1";
CHAR    szDBI2[] = "dbi2";
CHAR    szDBI3[] = "dbi3";
CHAR    szDBI4[] = "dbi4";
CHAR    szDBI5[] = "dbi5";
CHAR    szDBI6[] = "dbi6";
CHAR    szDBI7[] = "dbi7";

CHAR    szDBD0[] = "dbd0";
CHAR    szDBD1[] = "dbd1";
CHAR    szDBD2[] = "dbd2";
CHAR    szDBD3[] = "dbd3";
CHAR    szDBD4[] = "dbd4";
CHAR    szDBD5[] = "dbd5";
CHAR    szDBD6[] = "dbd6";
CHAR    szDBD7[] = "dbd7";

CHAR    szF32[] = "f32";    // High floating point temporary (scratch) registers
CHAR    szF33[] = "f33";
CHAR    szF34[] = "f34";
CHAR    szF35[] = "f35";
CHAR    szF36[] = "f36";
CHAR    szF37[] = "f37";
CHAR    szF38[] = "f38";
CHAR    szF39[] = "f39";
CHAR    szF40[] = "f40";
CHAR    szF41[] = "f41";
CHAR    szF42[] = "f42";
CHAR    szF43[] = "f43";
CHAR    szF44[] = "f44";
CHAR    szF45[] = "f45";
CHAR    szF46[] = "f46";
CHAR    szF47[] = "f47";
CHAR    szF48[] = "f48";
CHAR    szF49[] = "f49";

CHAR    szF50[] = "f50";
CHAR    szF51[] = "f51";
CHAR    szF52[] = "f52";
CHAR    szF53[] = "f53";
CHAR    szF54[] = "f54";
CHAR    szF55[] = "f55";
CHAR    szF56[] = "f56";
CHAR    szF57[] = "f57";
CHAR    szF58[] = "f58";
CHAR    szF59[] = "f59";
CHAR    szF60[] = "f60";
CHAR    szF61[] = "f61";
CHAR    szF62[] = "f62";
CHAR    szF63[] = "f63";
CHAR    szF64[] = "f64";
CHAR    szF65[] = "f65";
CHAR    szF66[] = "f66";
CHAR    szF67[] = "f67";
CHAR    szF68[] = "f68";
CHAR    szF69[] = "f69";
CHAR    szF70[] = "f70";
CHAR    szF71[] = "f71";
CHAR    szF72[] = "f72";
CHAR    szF73[] = "f73";
CHAR    szF74[] = "f74";
CHAR    szF75[] = "f75";
CHAR    szF76[] = "f76";
CHAR    szF77[] = "f77";
CHAR    szF78[] = "f78";
CHAR    szF79[] = "f79";
CHAR    szF80[] = "f80";
CHAR    szF81[] = "f81";
CHAR    szF82[] = "f82";
CHAR    szF83[] = "f83";
CHAR    szF84[] = "f84";
CHAR    szF85[] = "f85";
CHAR    szF86[] = "f86";
CHAR    szF87[] = "f87";
CHAR    szF88[] = "f88";
CHAR    szF89[] = "f89";
CHAR    szF90[] = "f90";
CHAR    szF91[] = "f91";
CHAR    szF92[] = "f92";
CHAR    szF93[] = "f93";
CHAR    szF94[] = "f94";
CHAR    szF95[] = "f95";
CHAR    szF96[] = "f96";
CHAR    szF97[] = "f97";
CHAR    szF98[] = "f98";
CHAR    szF99[] = "f99";

CHAR    szF100[] = "f100";
CHAR    szF101[] = "f101";
CHAR    szF102[] = "f102";
CHAR    szF103[] = "f103";
CHAR    szF104[] = "f104";
CHAR    szF105[] = "f105";
CHAR    szF106[] = "f106";
CHAR    szF107[] = "f107";
CHAR    szF108[] = "f108";
CHAR    szF109[] = "f109";
CHAR    szF110[] = "f110";
CHAR    szF111[] = "f111";
CHAR    szF112[] = "f112";
CHAR    szF113[] = "f113";
CHAR    szF114[] = "f114";
CHAR    szF115[] = "f115";
CHAR    szF116[] = "f116";
CHAR    szF117[] = "f117";
CHAR    szF118[] = "f118";
CHAR    szF119[] = "f119";
CHAR    szF120[] = "f120";
CHAR    szF121[] = "f121";
CHAR    szF122[] = "f122";
CHAR    szF123[] = "f123";
CHAR    szF124[] = "f124";
CHAR    szF125[] = "f125";
CHAR    szF126[] = "f126";
CHAR    szF127[] = "f127";

CHAR    szFPSR[] = "fpsr";
CHAR    szFSR[] = "fsr";
CHAR    szFIR[] = "fir";
CHAR    szFDR[] = "fdr";
CHAR    szFCR[] = "fcr"; 

CHAR    szGP[]  = "gp";        // global pointer
CHAR    szSP[] = "sp";         // stack pointer
CHAR    szR32[] = "r32";
CHAR    szR33[] = "r33";
CHAR    szR34[] = "r34";
CHAR    szR35[] = "r35";
CHAR    szR36[] = "r36";
CHAR    szR37[] = "r37";
CHAR    szR38[] = "r38";
CHAR    szR39[] = "r39";
CHAR    szR40[] = "r40";
CHAR    szR41[] = "r41";
CHAR    szR42[] = "r42";
CHAR    szR43[] = "r43";
CHAR    szR44[] = "r44";
CHAR    szR45[] = "r45";
CHAR    szR46[] = "r46";
CHAR    szR47[] = "r47";
CHAR    szR48[] = "r48";
CHAR    szR49[] = "r49";
CHAR    szR50[] = "r50";
CHAR    szR51[] = "r51";
CHAR    szR52[] = "r52";
CHAR    szR53[] = "r53";
CHAR    szR54[] = "r54";
CHAR    szR55[] = "r55";
CHAR    szR56[] = "r56";
CHAR    szR57[] = "r57";
CHAR    szR58[] = "r58";
CHAR    szR59[] = "r59";
CHAR    szR60[] = "r60";
CHAR    szR61[] = "r61";
CHAR    szR62[] = "r62";
CHAR    szR63[] = "r63";
CHAR    szR64[] = "r64";
CHAR    szR65[] = "r65";
CHAR    szR66[] = "r66";
CHAR    szR67[] = "r67";
CHAR    szR68[] = "r68";
CHAR    szR69[] = "r69";
CHAR    szR70[] = "r70";
CHAR    szR71[] = "r71";
CHAR    szR72[] = "r72";
CHAR    szR73[] = "r73";
CHAR    szR74[] = "r74";
CHAR    szR75[] = "r75";
CHAR    szR76[] = "r76";
CHAR    szR77[] = "r77";
CHAR    szR78[] = "r78";
CHAR    szR79[] = "r79";
CHAR    szR80[] = "r80";
CHAR    szR81[] = "r81";
CHAR    szR82[] = "r82";
CHAR    szR83[] = "r83";
CHAR    szR84[] = "r84";
CHAR    szR85[] = "r85";
CHAR    szR86[] = "r86";
CHAR    szR87[] = "r87";
CHAR    szR88[] = "r88";
CHAR    szR89[] = "r89";
CHAR    szR90[] = "r90";
CHAR    szR91[] = "r91";
CHAR    szR92[] = "r92";
CHAR    szR93[] = "r93";
CHAR    szR94[] = "r94";
CHAR    szR95[] = "r95";
CHAR    szR96[] = "r96";
CHAR    szR97[] = "r97";
CHAR    szR98[] = "r98";
CHAR    szR99[] = "r99";
CHAR    szR100[] = "r100";
CHAR    szR101[] = "r101";
CHAR    szR102[] = "r102";
CHAR    szR103[] = "r103";
CHAR    szR104[] = "r104";
CHAR    szR105[] = "r105";
CHAR    szR106[] = "r106";
CHAR    szR107[] = "r107";
CHAR    szR108[] = "r108";
CHAR    szR109[] = "r109";
CHAR    szR110[] = "r110";
CHAR    szR111[] = "r111";
CHAR    szR112[] = "r112";
CHAR    szR113[] = "r113";
CHAR    szR114[] = "r114";
CHAR    szR115[] = "r115";
CHAR    szR116[] = "r116";
CHAR    szR117[] = "r117";
CHAR    szR118[] = "r118";
CHAR    szR119[] = "r119";
CHAR    szR120[] = "r120";
CHAR    szR121[] = "r121";
CHAR    szR122[] = "r122";
CHAR    szR123[] = "r123";
CHAR    szR124[] = "r124";
CHAR    szR125[] = "r125";
CHAR    szR126[] = "r126";
CHAR    szR127[] = "r127";


CHAR    szINTNATS[] = "intnats";
CHAR    szPREDS[] = "preds";

CHAR    szB0[] = "b0";          // branch return pointer
CHAR    szB1[] = "b1";          // branch saved (preserved)
CHAR    szB2[] = "b2";
CHAR    szB3[] = "b3";
CHAR    szB4[] = "b4";
CHAR    szB5[] = "b5";
CHAR    szB6[] = "b6";          // branch temporary (scratch) registers
CHAR    szB7[] = "b7";

CHAR    szCSD[] = "csd";        // iA32 CS descriptor
CHAR    szSSD[] = "ssd";        // iA32 SS descriptor

CHAR    szAPUNAT[] = "unat";
CHAR    szAPLC[] = "lc";
CHAR    szAPEC[] = "ec";
CHAR    szAPCCV[] = "ccv";
CHAR    szAPDCR[] = "dcr";
CHAR    szRSPFS[] = "pfs";
CHAR    szRSBSP[] = "bsp";
CHAR    szRSBSPSTORE[] = "bspstore";
CHAR    szRSRSC[] = "rsc";
CHAR    szRSRNAT[] = "rnat";

CHAR    szEFLAG[] = "eflag";    // iA32 Eflag
CHAR    szCFLAG[] = "cflag";    // iA32 Cflag

CHAR    szSTIPSR[] = "ipsr";
CHAR    szSTIIP[] = "iip";
CHAR    szSTIFS[] = "ifs";

CHAR    szKDBI0[] = "kdbi0";
CHAR    szKDBI1[] = "kdbi1";
CHAR    szKDBI2[] = "kdbi2";
CHAR    szKDBI3[] = "kdbi3";
CHAR    szKDBI4[] = "kdbi4";
CHAR    szKDBI5[] = "kdbi5";
CHAR    szKDBI6[] = "kdbi6";
CHAR    szKDBI7[] = "kdbi7";

CHAR    szKDBD0[] = "kdbd0";
CHAR    szKDBD1[] = "kdbd1";
CHAR    szKDBD2[] = "kdbd2";
CHAR    szKDBD3[] = "kdbd3";
CHAR    szKDBD4[] = "kdbd4";
CHAR    szKDBD5[] = "kdbd5";
CHAR    szKDBD6[] = "kdbd6";
CHAR    szKDBD7[] = "kdbd7";

CHAR    szKPFC0[] = "kpfc0";
CHAR    szKPFC1[] = "kpfc1";
CHAR    szKPFC2[] = "kpfc2";
CHAR    szKPFC3[] = "kpfc3";
CHAR    szKPFC4[] = "kpfc4";
CHAR    szKPFC5[] = "kpfc5";
CHAR    szKPFC6[] = "kpfc6";
CHAR    szKPFC7[] = "kpfc7";

CHAR    szKPFD0[] = "kpfd0";
CHAR    szKPFD1[] = "kpfd1";
CHAR    szKPFD2[] = "kpfd2";
CHAR    szKPFD3[] = "kpfd3";
CHAR    szKPFD4[] = "kpfd4";
CHAR    szKPFD5[] = "kpfd5";
CHAR    szKPFD6[] = "kpfd6";
CHAR    szKPFD7[] = "kpfd7";

CHAR    szH16[] = "h16";          // kernel bank shadow (hidden) registers
CHAR    szH17[] = "h17";
CHAR    szH18[] = "h18";
CHAR    szH19[] = "h19";
CHAR    szH20[] = "h20";
CHAR    szH21[] = "h21";
CHAR    szH22[] = "h22";
CHAR    szH23[] = "h23";
CHAR    szH24[] = "h24";
CHAR    szH25[] = "h25";
CHAR    szH26[] = "h26";
CHAR    szH27[] = "h27";
CHAR    szH28[] = "h28";
CHAR    szH29[] = "h29";
CHAR    szH30[] = "h30";
CHAR    szH31[] = "h31";

CHAR    szACPUID0[] = "cpuid0";
CHAR    szACPUID1[] = "cpuid1";
CHAR    szACPUID2[] = "cpuid2";
CHAR    szACPUID3[] = "cpuid3";
CHAR    szACPUID4[] = "cpuid4";
CHAR    szACPUID5[] = "cpuid5";
CHAR    szACPUID6[] = "cpuid6";
CHAR    szACPUID7[] = "cpuid7";


CHAR    szAPKR0[] = "kr0";
CHAR    szAPKR1[] = "kr1";
CHAR    szAPKR2[] = "kr2";
CHAR    szAPKR3[] = "kr3";
CHAR    szAPKR4[] = "kr4";
CHAR    szAPKR5[] = "kr5";
CHAR    szAPKR6[] = "kr6";
CHAR    szAPKR7[] = "kr7";

CHAR    szAPITC[] = "itc";
CHAR    szAPITM[] = "itm";
CHAR    szAPIVA[] = "iva";
CHAR    szAPPTA[] = "pta";
CHAR    szAPGPTA[] = "apgta";
CHAR    szSTISR[] = "isr";
CHAR    szSTIDA[] = "ifa";
CHAR    szSTIDTR[] = "idtr";
CHAR    szSTIITR[] = "itir";
CHAR    szSTIIPA[] = "iipa";
CHAR    szSTIIM[] = "iim";
CHAR    szSTIHA[] = "iha";

CHAR    szSALID[] = "lid";
CHAR    szSAIVR[] = "ivr";
CHAR    szSATPR[] = "tpr";
CHAR    szSAEOI[] = "eoi";
CHAR    szSAIRR0[] = "irr0";
CHAR    szSAIRR1[] = "irr1";
CHAR    szSAIRR2[] = "irr2";
CHAR    szSAIRR3[] = "irr3";
CHAR    szSAITV[] = "itv";
CHAR    szSAPMV[] = "pmv";
CHAR    szSALRR0[] = "lrr0";
CHAR    szSALRR1[] = "lrr1";
CHAR    szSACMCV[] = "cmcv";

CHAR    szRR0[] = "rr0";
CHAR    szRR1[] = "rr1";
CHAR    szRR2[] = "rr2";
CHAR    szRR3[] = "rr3";
CHAR    szRR4[] = "rr4";
CHAR    szRR5[] = "rr5";
CHAR    szRR6[] = "rr6";
CHAR    szRR7[] = "rr7";

CHAR    szPKR0[] = "pkr0";
CHAR    szPKR1[] = "pkr1";
CHAR    szPKR2[] = "pkr2";
CHAR    szPKR3[] = "pkr3";
CHAR    szPKR4[] = "pkr4";
CHAR    szPKR5[] = "pkr5";
CHAR    szPKR6[] = "pkr6";
CHAR    szPKR7[] = "pkr7";
CHAR    szPKR8[] = "pkr8";
CHAR    szPKR9[] = "pkr9";
CHAR    szPKR10[] = "pkr10";
CHAR    szPKR11[] = "pkr11";
CHAR    szPKR12[] = "pkr12";
CHAR    szPKR13[] = "pkr13";
CHAR    szPKR14[] = "pkr14";
CHAR    szPKR15[] = "pkr15";

CHAR    szTRI0[] = "tri0";
CHAR    szTRI1[] = "tri1";
CHAR    szTRI2[] = "tri2";
CHAR    szTRI3[] = "tri3";
CHAR    szTRI4[] = "tri4";
CHAR    szTRI5[] = "tri5";
CHAR    szTRI6[] = "tri6";
CHAR    szTRI7[] = "tri7";
CHAR    szTRD0[] = "trd0";
CHAR    szTRD1[] = "trd1";
CHAR    szTRD2[] = "trd2";
CHAR    szTRD3[] = "trd3";
CHAR    szTRD4[] = "trd4";
CHAR    szTRD5[] = "trd5";
CHAR    szTRD6[] = "trd6";
CHAR    szTRD7[] = "trd7";

CHAR    szSMSR0[] = "SMSR0";
CHAR    szSMSR1[] = "SMSR1";
CHAR    szSMSR2[] = "SMSR2";
CHAR    szSMSR3[] = "SMSR3";
CHAR    szSMSR4[] = "SMSR4";
CHAR    szSMSR5[] = "SMSR5";
CHAR    szSMSR6[] = "SMSR6";
CHAR    szSMSR7[] = "SMSR7";


// IPSR flags

CHAR    szIPSRBN[] =  "ipsr.bn";
CHAR    szIPSRED[] =  "ipsr.ed";
CHAR    szIPSRRI[] =  "ipsr.ri";
CHAR    szIPSRSS[] =  "ipsr.ss";
CHAR    szIPSRDD[] =  "ipsr.dd";
CHAR    szIPSRDA[] =  "ipsr.da";
CHAR    szIPSRID[] =  "ipsr.id";
CHAR    szIPSRIT[] =  "ipsr.it";
CHAR    szIPSRME[] =  "ipsr.me";
CHAR    szIPSRIS[] =  "ipsr.is";
CHAR    szIPSRCPL[] = "ipsr.cpl";
CHAR    szIPSRRT[] =  "ipsr.rt";
CHAR    szIPSRTB[] =  "ipsr.tb";
CHAR    szIPSRLP[] =  "ipsr.lp";
CHAR    szIPSRDB[] =  "ipsr.db";
CHAR    szIPSRSI[] =  "ipsr.si";
CHAR    szIPSRDI[] =  "ipsr.di";
CHAR    szIPSRPP[] =  "ipsr.pp";
CHAR    szIPSRSP[] =  "ipsr.sp";
CHAR    szIPSRDFH[] = "ipsr.dfh";
CHAR    szIPSRDFL[] = "ipsr.dfl";
CHAR    szIPSRDT[] =  "ipsr.dt";
CHAR    szIPSRPK[] =  "ipsr.pk";
CHAR    szIPSRI[]  =  "ipsr.i";
CHAR    szIPSRIC[] =  "ipsr.ic";
CHAR    szIPSRAC[] =  "ipsr.ac";
CHAR    szIPSRUP[] =  "ipsr.up";
CHAR    szIPSRBE[] =  "ipsr.be";
CHAR    szIPSROR[] =  "ipsr.or";

// FPSR flags

CHAR    szFPSRMDH[] =    "fpsr.mdh";
CHAR    szFPSRMDL[] =    "fpsr.mdl";
CHAR    szFPSRSF3[] =    "fpsr.sf3";
CHAR    szFPSRSF2[] =    "fpsr.sf2";
CHAR    szFPSRSF1[] =    "fpsr.sf1";
CHAR    szFPSRSF0[] =    "fpsr.sf0";
CHAR    szFPSRTRAPID[] = "fpsr.id";
CHAR    szFPSRTRAPUD[] = "fpsr.ud";
CHAR    szFPSRTRAPOD[] = "fpsr.od";
CHAR    szFPSRTRAPZD[] = "fpsr.zd";
CHAR    szFPSRTRAPDD[] = "fpsr.dd";
CHAR    szFPSRTRAPVD[] = "fpsr.vd";

// Predicate registers
//CHAR    szPR0[] = "p0";
CHAR szPR1[]  = "p1";
CHAR szPR2[]  = "p2";
CHAR szPR3[]  = "p3";
CHAR szPR4[]  = "p4";
CHAR szPR5[]  = "p5";
CHAR szPR6[]  = "p6";
CHAR szPR7[]  = "p7";
CHAR szPR8[]  = "p8";
CHAR szPR9[]  = "p9";
CHAR szPR10[] = "p10";
CHAR szPR11[] = "p11";
CHAR szPR12[] = "p12";
CHAR szPR13[] = "p13";
CHAR szPR14[] = "p14";
CHAR szPR15[] = "p15";
CHAR szPR16[] = "p16";
CHAR szPR17[] = "p17";
CHAR szPR18[] = "p18";
CHAR szPR19[] = "p19";
CHAR szPR20[] = "p20";
CHAR szPR21[] = "p21";
CHAR szPR22[] = "p22";
CHAR szPR23[] = "p23";
CHAR szPR24[] = "p24";
CHAR szPR25[] = "p25";
CHAR szPR26[] = "p26";
CHAR szPR27[] = "p27";
CHAR szPR28[] = "p28";
CHAR szPR29[] = "p29";
CHAR szPR30[] = "p30";
CHAR szPR31[] = "p31";
CHAR szPR32[] = "p32";
CHAR szPR33[] = "p33";
CHAR szPR34[] = "p34";
CHAR szPR35[] = "p35";
CHAR szPR36[] = "p36";
CHAR szPR37[] = "p37";
CHAR szPR38[] = "p38";
CHAR szPR39[] = "p39";
CHAR szPR40[] = "p40";
CHAR szPR41[] = "p41";
CHAR szPR42[] = "p42";
CHAR szPR43[] = "p43";
CHAR szPR44[] = "p44";
CHAR szPR45[] = "p45";
CHAR szPR46[] = "p46";
CHAR szPR47[] = "p47";
CHAR szPR48[] = "p48";
CHAR szPR49[] = "p49";
CHAR szPR50[] = "p50";
CHAR szPR51[] = "p51";
CHAR szPR52[] = "p52";
CHAR szPR53[] = "p53";
CHAR szPR54[] = "p54";
CHAR szPR55[] = "p55";
CHAR szPR56[] = "p56";
CHAR szPR57[] = "p57";
CHAR szPR58[] = "p58";
CHAR szPR59[] = "p59";
CHAR szPR60[] = "p60";
CHAR szPR61[] = "p61";
CHAR szPR62[] = "p62";
CHAR szPR63[] = "p63";

// Aliases: allow aliases to general purpose registers that are
// known by more than one name, eg r12 = rsp.

CHAR    szR1GP[]  =      "r1";
CHAR    szR12SP[] =      "r12";
CHAR    szRA[]    =      "ra";
CHAR    szRP[]    =      "rp";
CHAR    szRET0[]  =      "ret0";
CHAR    szRET1[]  =      "ret1";
CHAR    szRET2[]  =      "ret2";
CHAR    szRET3[]  =      "ret3";



REGDEF IA64Regs[] =
{
    
    szDBI0, REGDBI0, szDBI1, REGDBI1, szDBI2, REGDBI2, szDBI3, REGDBI3,
    szDBI4, REGDBI4, szDBI5, REGDBI5, szDBI6, REGDBI6, szDBI7, REGDBI7,
    szDBD0, REGDBD0, szDBD1, REGDBD1, szDBD2, REGDBD2, szDBD3, REGDBD3,
    szDBD4, REGDBD4, szDBD5, REGDBD5, szDBD6, REGDBD6, szDBD7, REGDBD7,

//    g_F0, FLTZERO, g_F1, FLTONE,
    g_F2, FLTS0, g_F3, FLTS1,
    g_F4, FLTS2, g_F5, FLTS3, g_F6, FLTT0, g_F7, FLTT1,
    g_F8, FLTT2, g_F9, FLTT3, g_F10, FLTT4, g_F11, FLTT5,
    g_F12, FLTT6, g_F13, FLTT7, g_F14, FLTT8, g_F15, FLTT9,
    g_F16, FLTS4, g_F17, FLTS5, g_F18, FLTS6, g_F19, FLTS7,
    g_F20, FLTS8, g_F21, FLTS9, g_F22, FLTS10, g_F23, FLTS11,
    g_F24, FLTS12, g_F25, FLTS13, g_F26, FLTS14, g_F27, FLTS15,
    g_F28, FLTS16, g_F29, FLTS17, g_F30, FLTS18, g_F31, FLTS19,
    szF32, FLTF32, szF33, FLTF33, szF34, FLTF34, szF35, FLTF35,
    szF36, FLTF36, szF37, FLTF37, szF38, FLTF38, szF39, FLTF39,
    szF40, FLTF40, szF41, FLTF41, szF42, FLTF42, szF43, FLTF43,
    szF44, FLTF44, szF45, FLTF45, szF46, FLTF46, szF47, FLTF47,
    szF48, FLTF48, szF49, FLTF49, szF50, FLTF50, szF51, FLTF51,
    szF52, FLTF52, szF53, FLTF53, szF54, FLTF54, szF55, FLTF55,
    szF56, FLTF56, szF57, FLTF57, szF58, FLTF58, szF59, FLTF59,
    szF60, FLTF60, szF61, FLTF61, szF62, FLTF62, szF63, FLTF63,
    szF64, FLTF64, szF65, FLTF65, szF66, FLTF66, szF67, FLTF67,
    szF68, FLTF68, szF69, FLTF69, szF70, FLTF70, szF71, FLTF71,
    szF72, FLTF72, szF73, FLTF73, szF74, FLTF74, szF75, FLTF75,
    szF76, FLTF76, szF77, FLTF77, szF78, FLTF78, szF79, FLTF79,
    szF80, FLTF80, szF81, FLTF81, szF82, FLTF82, szF83, FLTF83,
    szF84, FLTF84, szF85, FLTF85, szF86, FLTF86, szF87, FLTF87,
    szF88, FLTF88, szF89, FLTF89, szF90, FLTF90, szF91, FLTF91,
    szF92, FLTF92, szF93, FLTF93, szF94, FLTF94, szF95, FLTF95,
    szF96, FLTF96, szF97, FLTF97, szF98, FLTF98, szF99, FLTF99,
    szF100, FLTF100, szF101, FLTF101, szF102, FLTF102, szF103, FLTF103,
    szF104, FLTF104, szF105, FLTF105, szF106, FLTF106, szF107, FLTF107,
    szF108, FLTF108, szF109, FLTF109, szF110, FLTF110, szF111, FLTF111,
    szF112, FLTF112, szF113, FLTF113, szF114, FLTF114, szF115, FLTF115,
    szF116, FLTF116, szF117, FLTF117, szF118, FLTF118, szF119, FLTF119,
    szF120, FLTF120, szF121, FLTF121, szF122, FLTF122, szF123, FLTF123,
    szF124, FLTF124, szF125, FLTF125, szF126, FLTF126, szF127, FLTF127,

    szFPSR, STFPSR, 

//    g_R0, INTZERO,
    szGP, INTGP, g_R2, INTT0, g_R3, INTT1,
    g_R4, INTS0, g_R5, INTS1, g_R6, INTS2, g_R7, INTS3,
    g_R8, INTV0, g_R9, INTT2, g_R10, INTT3, g_R11, INTT4,
    szSP, INTSP, g_R13, INTTEB, g_R14, INTT5, g_R15, INTT6,
    g_R16, INTT7, g_R17, INTT8, g_R18, INTT9, g_R19, INTT10,
    g_R20, INTT11, g_R21, INTT12, g_R22, INTT13, g_R23, INTT14,
    g_R24, INTT15, g_R25, INTT16, g_R26, INTT17, g_R27, INTT18,
    g_R28, INTT19, g_R29, INTT20, g_R30, INTT21, g_R31, INTT22,

    szINTNATS, INTNATS, 

    szR32, INTR32, szR33, INTR33, szR34, INTR34, szR35, INTR35,
    szR36, INTR36, szR37, INTR37, szR38, INTR38, szR39, INTR39,
    szR40, INTR40, szR41, INTR41, szR42, INTR42, szR42, INTR42,
    szR43, INTR43, szR44, INTR44, szR45, INTR45, szR46, INTR46,
    szR47, INTR47, szR48, INTR48, szR49, INTR49, szR50, INTR50,
    szR51, INTR51, szR52, INTR52, szR53, INTR53, szR54, INTR54,
    szR55, INTR55, szR56, INTR56, szR57, INTR57, szR58, INTR58,
    szR59, INTR59, szR60, INTR60, szR61, INTR61, szR62, INTR62,
    szR63, INTR63, szR64, INTR64, szR65, INTR65, szR66, INTR66,
    szR67, INTR67, szR68, INTR68, szR69, INTR69, szR70, INTR70,
    szR71, INTR71, szR72, INTR72, szR73, INTR73, szR74, INTR74,
    szR75, INTR75, szR76, INTR76, szR77, INTR77, szR78, INTR78,
    szR79, INTR79, szR80, INTR80, szR81, INTR81, szR82, INTR82,
    szR83, INTR83, szR84, INTR84, szR85, INTR85, szR86, INTR86,
    szR87, INTR87, szR88, INTR88, szR89, INTR89, szR90, INTR90,
    szR91, INTR91, szR92, INTR92, szR93, INTR93, szR94, INTR94,
    szR95, INTR95, szR96, INTR96, szR97, INTR97, szR98, INTR98,
    szR99, INTR99, szR100, INTR100, szR101, INTR101, szR102, INTR102,
    szR103, INTR103, szR104, INTR104, szR105, INTR105, szR106, INTR106,
    szR107, INTR107, szR108, INTR108, szR109, INTR109, szR110, INTR110,
    szR111, INTR111, szR112, INTR112, szR112, INTR113, szR114, INTR114,
    szR115, INTR115, szR116, INTR116, szR117, INTR117, szR118, INTR118,
    szR119, INTR119, szR120, INTR120, szR121, INTR121, szR122, INTR122,
    szR123, INTR123, szR124, INTR124, szR125, INTR125, szR126, INTR126,
    szR127, INTR127,


    szPREDS, PREDS,

    szB0, BRRP, szB1, BRS0, szB2, BRS1, szB3, BRS2,
    szB4, BRS3, szB5, BRS4, szB6, BRT0, szB7, BRT1,

    szAPUNAT, APUNAT, szAPLC, APLC,
    szAPEC, APEC, szAPCCV, APCCV, szAPDCR, APDCR, szRSPFS, RSPFS,
    szRSBSP, RSBSP, szRSBSPSTORE, RSBSPSTORE, szRSRSC, RSRSC, szRSRNAT, RSRNAT,

    szSTIPSR, STIPSR, szSTIIP, STIIP, szSTIFS, STIFS,

    szFCR, StFCR,
    szEFLAG, Eflag, 
    szCSD, SegCSD, 
    szSSD, SegSSD,  
    szCFLAG, Cflag,
    szFSR, STFSR, 
    szFIR, STFIR, 
    szFDR, STFDR,

// IPSR flags

    szIPSRBN, IPSRBN,
    szIPSRED, IPSRED, szIPSRRI, IPSRRI, szIPSRSS, IPSRSS, szIPSRDD, IPSRDD,
    szIPSRDA, IPSRDA, szIPSRID, IPSRID, szIPSRIT, IPSRIT, szIPSRME, IPSRME,
    szIPSRIS, IPSRIS, szIPSRCPL, IPSRCPL, szIPSRRT, IPSRRT, szIPSRTB, IPSRTB,
    szIPSRLP, IPSRLP, szIPSRDB, IPSRDB, szIPSRSI, IPSRSI, szIPSRDI, IPSRDI,
    szIPSRPP, IPSRPP, szIPSRSP, IPSRSP, szIPSRDFH, IPSRDFH, szIPSRDFL, IPSRDFL,
    szIPSRDT, IPSRDT, szIPSRPK, IPSRPK, szIPSRI, IPSRI, szIPSRIC, IPSRIC,
    szIPSRAC, IPSRAC, szIPSRUP, IPSRUP, szIPSRBE, IPSRBE, szIPSROR, IPSROR,

// FPSR flags

    szFPSRMDH, FPSRMDH, szFPSRMDL, FPSRMDL,
    szFPSRSF3, FPSRSF3, szFPSRSF2, FPSRSF2,
    szFPSRSF1, FPSRSF1, szFPSRSF0, FPSRSF0,
    szFPSRTRAPID, FPSRTRAPID, szFPSRTRAPUD, FPSRTRAPUD,
    szFPSRTRAPOD, FPSRTRAPOD, szFPSRTRAPZD, FPSRTRAPZD,
    szFPSRTRAPDD, FPSRTRAPDD, szFPSRTRAPVD, FPSRTRAPVD,

// Predicate registers
//  szPR0, PR0, 
                  szPR1,  PR1,  szPR2,  PR2,  szPR3,  PR3,
    szPR4,  PR4,  szPR5,  PR5,  szPR6,  PR6,  szPR7,  PR7,
    szPR8,  PR8,  szPR9,  PR9,  szPR10, PR10, szPR11, PR11,
    szPR12, PR12, szPR13, PR13, szPR14, PR14, szPR15, PR15,
    szPR16, PR16, szPR17, PR17, szPR18, PR18, szPR19, PR19,
    szPR20, PR20, szPR21, PR21, szPR22, PR22, szPR23, PR23,
    szPR24, PR24, szPR25, PR25, szPR26, PR26, szPR27, PR27,
    szPR28, PR28, szPR29, PR29, szPR30, PR30, szPR31, PR31,
    szPR32, PR32, szPR33, PR33, szPR34, PR34, szPR35, PR35,
    szPR36, PR36, szPR37, PR37, szPR38, PR38, szPR39, PR39,
    szPR40, PR40, szPR41, PR41, szPR42, PR42, szPR43, PR43,
    szPR44, PR44, szPR45, PR45, szPR46, PR46, szPR47, PR47,
    szPR48, PR48, szPR49, PR49, szPR50, PR50, szPR51, PR51,
    szPR52, PR52, szPR53, PR53, szPR54, PR54, szPR55, PR55,
    szPR56, PR56, szPR57, PR57, szPR58, PR58, szPR59, PR59,
    szPR60, PR60, szPR61, PR61, szPR62, PR62, szPR63, PR63,

// Aliases

    szR1GP, INTGP, szR12SP, INTSP, szRA, BRRP, szRP, BRRP,
    szRET0, INTV0, szRET1, INTT2, szRET2, INTT3, szRET3, INTT4,

    NULL, 0,
};

REGDEF g_Ia64KernelRegs[] =
{
    szKDBI0, KRDBI0, szKDBI1, KRDBI1, szKDBI2, KRDBI2, szKDBI3, KRDBI3,
    szKDBI4, KRDBI4, szKDBI5, KRDBI5, szKDBI6, KRDBI6, szKDBI7, KRDBI7,

    szKDBD0, KRDBD0, szKDBD1, KRDBD1, szKDBD2, KRDBD2, szKDBD3, KRDBD3,
    szKDBD4, KRDBD4, szKDBD5, KRDBD5, szKDBD6, KRDBD6, szKDBD7, KRDBD7,

    szKPFC0, KRPFC0, szKPFC1, KRPFC1, szKPFC2, KRPFC2, szKPFC3, KRPFC3,
    szKPFC4, KRPFC4, szKPFC5, KRPFC5, szKPFC6, KRPFC6, szKPFC7, KRPFC7,

    szKPFD0, KRPFD0, szKPFD1, KRPFD1, szKPFD2, KRPFD2, szKPFD3, KRPFD3,
    szKPFD4, KRPFD4, szKPFD5, KRPFD5, szKPFD6, KRPFD6, szKPFD7, KRPFD7,

    szH16, INTH16, szH17, INTH17, szH18, INTH18, szH19, INTH19,
    szH20, INTH20, szH21, INTH21, szH22, INTH22, szH23, INTH23,
    szH24, INTH24, szH25, INTH25, szH26, INTH26, szH27, INTH27,
    szH28, INTH28, szH29, INTH29, szH30, INTH30, szH31, INTH31,

    szACPUID0, ACPUID0, szACPUID1, ACPUID1, szACPUID2, ACPUID2, szACPUID3, ACPUID3, 
    szACPUID4, ACPUID4, szACPUID5, ACPUID5, szACPUID6, ACPUID6, szACPUID7, ACPUID7,

    szAPKR0, APKR0, szAPKR1, APKR1, szAPKR2, APKR2, szAPKR3, APKR3,
    szAPKR4, APKR4, szAPKR5, APKR5, szAPKR6, APKR6, szAPKR7, APKR7,

    szAPITC, APITC, szAPITM, APITM, szAPIVA, APIVA,
    szAPPTA, APPTA, szAPGPTA, APGPTA, 
    szSTISR, STISR, szSTIDA, STIDA,
    szSTIITR, STIITR, szSTIIPA, STIIPA, szSTIIM, STIIM, szSTIHA, STIHA,

    szSALID, SALID,
    szSAIVR, SAIVR, szSATPR, SATPR, szSAEOI, SAEOI, szSAIRR0, SAIRR0,
    szSAIRR1, SAIRR1, szSAIRR2, SAIRR2, szSAIRR3, SAIRR3, szSAITV, SAITV,
    szSAPMV, SAPMV, szSACMCV, SACMCV, szSALRR0, SALRR0, szSALRR1, SALRR1,

    szRR0, SRRR0, szRR1, SRRR1, szRR2, SRRR2, szRR3, SRRR3,
    szRR4, SRRR4, szRR5, SRRR5, szRR6, SRRR6, szRR7, SRRR7,

    szPKR0, SRPKR0, szPKR1, SRPKR1, szPKR2, SRPKR2, szPKR3, SRPKR3,
    szPKR4, SRPKR4, szPKR5, SRPKR5, szPKR6, SRPKR6, szPKR7, SRPKR7,
    szPKR8, SRPKR8, szPKR9, SRPKR9, szPKR10, SRPKR10, szPKR11, SRPKR11,
    szPKR12, SRPKR12, szPKR13, SRPKR13, szPKR14, SRPKR14, szPKR15, SRPKR15,

    szTRI0, SRTRI0, szTRI1, SRTRI1, szTRI2, SRTRI2, szTRI3, SRTRI3,
    szTRI4, SRTRI4, szTRI5, SRTRI5, szTRI6, SRTRI6, szTRI7, SRTRI7,
    szTRD0, SRTRD0, szTRD1, SRTRD1, szTRD2, SRTRD2, szTRD3, SRTRD3,
    szTRD4, SRTRD4, szTRD5, SRTRD5, szTRD6, SRTRD6, szTRD7, SRTRD7,

    szSMSR0, SMSR0, szSMSR1, SMSR1, szSMSR2, SMSR2, szSMSR3, SMSR3, 
    szSMSR4, SMSR4, szSMSR5, SMSR5, szSMSR6, SMSR6, szSMSR7, SMSR7,

    NULL, 0,
};

REGSUBDEF IA64SubRegs[] =
{
    // IPSR flags

    { IPSRBN, STIPSR, 44, 1 },          //  BN Register bank #
    { IPSRED, STIPSR, 43, 1 },          //  ED Exception deferal
    { IPSRRI, STIPSR, 41, 0x3 },        //  RI Restart instruction
    { IPSRSS, STIPSR, 40, 1 },          //  SS Single step enable
    { IPSRDD, STIPSR, 39, 1 },          //  DD Data debug fault disable
    { IPSRDA, STIPSR, 38, 1 },          //  DA Disable access and dirty-bit faults
    { IPSRID, STIPSR, 37, 1 },          //  ID Instruction debug fault disable
    { IPSRIT, STIPSR, 36, 1 },          //  IT Instruction address translation
    { IPSRME, STIPSR, 35, 1 },          //  ME Machine check abort mamsk
    { IPSRIS, STIPSR, 34, 1 },          //  IS Instruction set
    { IPSRCPL,STIPSR, 32, 0x3 },        //  CPL Current privilege level
    { IPSRRT, STIPSR, 27, 1 },          //  RT Rigister stack translation
    { IPSRTB, STIPSR, 26, 1 },          //  TB Taaaaken branch trap
    { IPSRLP, STIPSR, 25, 1 },          //  LP Lower privilege transfer trap
    { IPSRDB, STIPSR, 24, 1 },          //  DB Debug breakpoint fault
    { IPSRSI, STIPSR, 23, 1 },          //  SI Secure interval timer(ITC)
    { IPSRDI, STIPSR, 22, 1 },          //  DI Disable instruction set transition
    { IPSRPP, STIPSR, 21, 1 },          //  PP Privileged performance monitor enable
    { IPSRSP, STIPSR, 20, 1 },          //  SP Secure performance monitors
    { IPSRDFH,STIPSR, 19, 1 },          //  DFH Disabled floating-point high register set, f16-f127
    { IPSRDFL,STIPSR, 18, 1 },          //  DFL Disabled floating-point low register set, f0-f15
    { IPSRDT, STIPSR, 17, 1 },          //  DT Data address translation
//  { ?,      STIPSR, 16, 1 },          //  (reserved)
    { IPSRPK, STIPSR, 15, 1 },          //  PK Protection key enabled
    { IPSRI,  STIPSR, 14, 1 },          //  I  Interrupt unmask
    { IPSRIC, STIPSR, 13, 1 },          //  IC Interruption collection
    { IPSRAC, STIPSR,  3, 1 },          //  AC Alignment check
    { IPSRUP, STIPSR,  2, 1 },          //  UP User performance monitor enabled
    { IPSRBE, STIPSR,  1, 1 },          //  BE Big-Endian
    { IPSROR, STIPSR,  0, 1 },          //  OR Ordered memory reference

    // FPSR flags

    { FPSRMDH,    STFPSR, 63,      1 }, //  MDH Upper floating point register written
    { FPSRMDL,    STFPSR, 62,      1 }, //  MDL Lower floating point register written
    { FPSRSF3,    STFPSR, 45, 0x1fff }, //  SF3 Alternate status field 3
    { FPSRSF2,    STFPSR, 32, 0x1fff }, //  SF2 Alternate status field 2
    { FPSRSF1,    STFPSR, 19, 0x1fff }, //  SF1 Alternate status field 1
    { FPSRSF0,    STFPSR,  6, 0x1fff }, //  SF0 Main status field
    { FPSRTRAPID, STFPSR,  5,      1 }, //  TRAPID Inexact floating point trap
    { FPSRTRAPUD, STFPSR,  4,      1 }, //  TRAPUD Underflow floating point trap
    { FPSRTRAPOD, STFPSR,  3,      1 }, //  TRAPOD Overflow flating point trap
    { FPSRTRAPZD, STFPSR,  2,      1 }, //  TRAPZD Zero devide floating point trap
    { FPSRTRAPDD, STFPSR,  1,      1 }, //  TRAPDD Denormal/Unnormal operand floating point trap
    { FPSRTRAPVD, STFPSR,  0,      1 }, //  TRAPVD Invalid operation floating point trap

    // Predicate registers
//  { PR0,  PREDS,  0, 1 },
    { PR1,  PREDS,  1, 1 },
    { PR2,  PREDS,  2, 1 },
    { PR3,  PREDS,  3, 1 },
    { PR4,  PREDS,  4, 1 },
    { PR5,  PREDS,  5, 1 },
    { PR6,  PREDS,  6, 1 },
    { PR7,  PREDS,  7, 1 },
    { PR8,  PREDS,  8, 1 },
    { PR9,  PREDS,  9, 1 },
    { PR10, PREDS, 10, 1 },
    { PR11, PREDS, 11, 1 },
    { PR12, PREDS, 12, 1 },
    { PR13, PREDS, 13, 1 },
    { PR14, PREDS, 14, 1 },
    { PR15, PREDS, 15, 1 },
    { PR16, PREDS, 16, 1 },
    { PR17, PREDS, 17, 1 },
    { PR18, PREDS, 18, 1 },
    { PR19, PREDS, 19, 1 },
    { PR20, PREDS, 20, 1 },
    { PR21, PREDS, 21, 1 },
    { PR22, PREDS, 22, 1 },
    { PR23, PREDS, 23, 1 },
    { PR24, PREDS, 24, 1 },
    { PR25, PREDS, 25, 1 },
    { PR26, PREDS, 26, 1 },
    { PR27, PREDS, 27, 1 },
    { PR28, PREDS, 28, 1 },
    { PR29, PREDS, 29, 1 },
    { PR30, PREDS, 30, 1 },
    { PR31, PREDS, 31, 1 },
    { PR32, PREDS, 32, 1 },
    { PR33, PREDS, 33, 1 },
    { PR34, PREDS, 34, 1 },
    { PR35, PREDS, 35, 1 },
    { PR36, PREDS, 36, 1 },
    { PR37, PREDS, 37, 1 },
    { PR38, PREDS, 38, 1 },
    { PR39, PREDS, 39, 1 },
    { PR40, PREDS, 40, 1 },
    { PR41, PREDS, 41, 1 },
    { PR42, PREDS, 42, 1 },
    { PR43, PREDS, 43, 1 },
    { PR44, PREDS, 44, 1 },
    { PR45, PREDS, 45, 1 },
    { PR46, PREDS, 46, 1 },
    { PR47, PREDS, 47, 1 },
    { PR48, PREDS, 48, 1 },
    { PR49, PREDS, 49, 1 },
    { PR50, PREDS, 50, 1 },
    { PR51, PREDS, 51, 1 },
    { PR52, PREDS, 52, 1 },
    { PR53, PREDS, 53, 1 },
    { PR54, PREDS, 54, 1 },
    { PR55, PREDS, 55, 1 },
    { PR56, PREDS, 56, 1 },
    { PR57, PREDS, 57, 1 },
    { PR58, PREDS, 58, 1 },
    { PR59, PREDS, 59, 1 },
    { PR60, PREDS, 60, 1 },
    { PR61, PREDS, 61, 1 },
    { PR62, PREDS, 62, 1 },
    { PR63, PREDS, 63, 1 },

    { 0, 0, 0 }
};

#define REGALL_HIGHFLOAT        REGALL_EXTRA0
#define REGALL_DREG             REGALL_EXTRA1
REGALLDESC IA64ExtraDesc[] =
{
    REGALL_HIGHFLOAT,  "High floating pointer registers (f32-f127)",
    REGALL_DREG,       "User debug registers",
    0,                 NULL,
};

#define REGALL_SPECIALREG       REGALL_EXTRA2
REGALLDESC g_Ia64KernelExtraDesc[] =
{
    REGALL_SPECIALREG, "KSPECIAL_REGISTERS",
    0,                 NULL,
};

RegisterGroup g_Ia64BaseGroup =
{
    NULL, 0, IA64Regs, IA64SubRegs, IA64ExtraDesc
};
RegisterGroup g_Ia64KernelGroup =
{
    NULL, 0, g_Ia64KernelRegs, NULL, g_Ia64KernelExtraDesc
};

// First ExecTypes entry must be the actual processor type.
ULONG g_Ia64ExecTypes[] =
{
    IMAGE_FILE_MACHINE_IA64, IMAGE_FILE_MACHINE_I386
};

BOOL 
SplitIa64Pc(ULONG64 Pc, ULONG64* Bundle, ULONG64* Slot)
{
    ULONG64 SlotVal = Pc & 0xf;

    switch (SlotVal) 
    {
    case 0: 
    case 4: 
    case 8:  
        SlotVal >>= 2;
        break;
    default: 
        return FALSE;
    } 

    if (Slot) 
    {
        *Slot = SlotVal;
    }
    if (Bundle) 
    {
        *Bundle = Pc & ~(ULONG64)0xf;
    }

    return TRUE;
}

Ia64MachineInfo g_Ia64Machine;

HRESULT
Ia64MachineInfo::InitializeConstants(void)
{
    m_FullName = "Intel IA64";
    m_AbbrevName = "ia64";
    m_PageSize = IA64_PAGE_SIZE;
    m_PageShift = IA64_PAGE_SHIFT;
    m_NumExecTypes = 2;
    m_ExecTypes = g_Ia64ExecTypes;
    m_Ptr64 = TRUE;
    
    m_AllMask = REGALL_INT64 | REGALL_DREG,
        
    m_MaxDataBreakpoints = IA64_REG_MAX_DATA_BREAKPOINTS;
    m_SymPrefix = NULL;

    m_KernPageDir = 0;
    
    return MachineInfo::InitializeConstants();
}

HRESULT
Ia64MachineInfo::InitializeForTarget(void)
{
    m_Groups = &g_Ia64BaseGroup;
    g_Ia64BaseGroup.Next = NULL;
    if (IS_KERNEL_TARGET())
    {
        g_Ia64BaseGroup.Next = &g_Ia64KernelGroup;
    }

    m_OffsetPrcbProcessorState =
        FIELD_OFFSET(IA64_PARTIAL_KPRCB, ProcessorState);
    m_OffsetPrcbNumber =
        FIELD_OFFSET(IA64_PARTIAL_KPRCB, Number);
    m_TriagePrcbOffset = IA64_TRIAGE_PRCB_ADDRESS;
    m_SizePrcb = IA64_KPRCB_SIZE;
    m_OffsetKThreadApcProcess =
        FIELD_OFFSET(CROSS_PLATFORM_THREAD, IA64Thread.ApcState.Process);
    m_OffsetKThreadTeb =
        FIELD_OFFSET(CROSS_PLATFORM_THREAD, IA64Thread.Teb);
    m_OffsetKThreadInitialStack =
        FIELD_OFFSET(CROSS_PLATFORM_THREAD, IA64Thread.InitialStack);
    m_OffsetKThreadNextProcessor = IA64_KTHREAD_NEXTPROCESSOR_OFFSET;
    m_OffsetEprocessPeb =  (g_TargetBuildNumber < 2264 ) ?
        IA64_PEB_IN_EPROCESS : IA64_2259_PEB_IN_EPROCESS;
    m_OffsetEprocessDirectoryTableBase =
        IA64_DIRECTORY_TABLE_BASE_IN_EPROCESS;
    m_SizeTargetContext = sizeof(IA64_CONTEXT);
    m_OffsetTargetContextFlags = FIELD_OFFSET(IA64_CONTEXT, ContextFlags);
    m_SizeCanonicalContext = sizeof(IA64_CONTEXT);
    m_SverCanonicalContext = NT_SVER_W2K;
    m_SizeControlReport = sizeof(IA64_DBGKD_CONTROL_REPORT);
    m_SizeEThread = IA64_ETHREAD_SIZE;
    m_SizeEProcess = IA64_EPROCESS_SIZE;
    m_OffsetSpecialRegisters = IA64_DEBUG_CONTROL_SPACE_KSPECIAL;
    m_SizeKspecialRegisters = sizeof(IA64_KSPECIAL_REGISTERS);
    m_SizePartialKThread = sizeof(IA64_THREAD);
    m_SharedUserDataOffset = IS_KERNEL_TARGET() ?
        IA64_KI_USER_SHARED_DATA : MM_SHARED_USER_DATA_VA;

    return MachineInfo::InitializeForTarget();
}

void
Ia64MachineInfo::
InitializeContext(ULONG64 Pc,
                  PDBGKD_ANY_CONTROL_REPORT ControlReport)
{
    if (Pc)
    {
        ULONG Slot;

        m_ContextState = MCTX_PC;
        Slot = (ULONG)(Pc & 0xc) >> 2;
        m_Context.IA64Context.StIIP = Pc & ~(0xf);
        m_Context.IA64Context.StIPSR &= ~(IPSR_RI_MASK);
        m_Context.IA64Context.StIPSR |=  (ULONGLONG)Slot << PSR_RI;
    }
    else
    {
        m_Context.IA64Context.StIIP = Pc;
    }

    if (Pc && ControlReport != NULL)
    {
        CacheReportInstructions
            (Pc, ControlReport->IA64ControlReport.InstructionCount,
             ControlReport->IA64ControlReport.InstructionStream);
    }
}

HRESULT
Ia64MachineInfo::KdGetContextState(ULONG State)
{
    HRESULT Status;
        
    if (State >= MCTX_CONTEXT && m_ContextState < MCTX_CONTEXT)
    {
        Status = g_Target->GetContext(g_RegContextThread->Handle, &m_Context);
        if (Status != S_OK)
        {
            return Status;
        }

        m_ContextState = MCTX_CONTEXT;
    }
    
    if (State >= MCTX_FULL && m_ContextState < MCTX_FULL)
    {
        Status = g_Target->GetTargetSpecialRegisters
            (g_RegContextThread->Handle, (PCROSS_PLATFORM_KSPECIAL_REGISTERS)
             &m_SpecialRegContext);
        if (Status != S_OK)
        {
            return Status;
        }

        m_ContextState = MCTX_FULL;
        KdSetSpecialRegistersInContext();
    }

    return S_OK;
}

HRESULT
Ia64MachineInfo::KdSetContext(void)
{
    HRESULT Status;
    
    Status = g_Target->SetContext(g_RegContextThread->Handle, &m_Context);
    if (Status != S_OK)
    {
        return Status;
    }

    KdGetSpecialRegistersFromContext();
    Status = g_Target->SetTargetSpecialRegisters
        (g_RegContextThread->Handle, (PCROSS_PLATFORM_KSPECIAL_REGISTERS)
         &m_SpecialRegContext);
    if (Status != S_OK)
    {
        return Status;
    }

    return S_OK;
}

HRESULT
Ia64MachineInfo::ConvertContextFrom(PCROSS_PLATFORM_CONTEXT Context,
                                    ULONG FromSver, ULONG FromSize, PVOID From)
{
    if (FromSize < sizeof(IA64_CONTEXT))
    {
        return E_INVALIDARG;
    }

    memcpy(Context, From, sizeof(IA64_CONTEXT));
    return S_OK;
}

HRESULT
Ia64MachineInfo::ConvertContextTo(PCROSS_PLATFORM_CONTEXT Context,
                                  ULONG ToSver, ULONG ToSize, PVOID To)
{
    if (ToSize < sizeof(IA64_CONTEXT))
    {
        return E_INVALIDARG;
    }

    memcpy(To, Context, sizeof(IA64_CONTEXT));
    return S_OK;
}

void
Ia64MachineInfo::InitializeContextFlags(PCROSS_PLATFORM_CONTEXT Context,
                                        ULONG Version)
{
    Context->IA64Context.ContextFlags =
        IA64_CONTEXT_FULL | IA64_CONTEXT_DEBUG;
}

HRESULT
Ia64MachineInfo::GetContextFromThreadStack(ULONG64 ThreadBase,
                                           PCROSS_PLATFORM_THREAD Thread,
                                           PCROSS_PLATFORM_CONTEXT Context,
                                           PDEBUG_STACK_FRAME Frame,
                                           PULONG RunningOnProc)
{
    HRESULT Status;
    UCHAR Proc;

    //
    // Check to see if the thread is currently running.
    //
    
    if (Thread->IA64Thread.State == 2)
    {
        if ((Status = g_Target->ReadAllVirtual
             (ThreadBase + m_OffsetKThreadNextProcessor, 
              &Proc, sizeof(Proc))) != S_OK) 
            {
                return Status;
            }

        *RunningOnProc = Proc;
        return S_FALSE;
    }
    
    //
    // The thread isn't running so read its stored context information.
    //
    
    IA64_KSWITCH_FRAME SwitchFrame;

    if ((Status = g_Target->ReadAllVirtual(Thread->IA64Thread.KernelStack + 
                                           IA64_STACK_SCRATCH_AREA, 
                                           &SwitchFrame, 
                                           sizeof(SwitchFrame))) != S_OK)
    {
        return Status;
    }

    Context->IA64Context.IntSp = 
        Thread->IA64Thread.KernelStack;
    Context->IA64Context.Preds = SwitchFrame.SwitchPredicates;
    Context->IA64Context.StIIP = SwitchFrame.SwitchRp;
    Context->IA64Context.StFPSR = SwitchFrame.SwitchFPSR;
    Context->IA64Context.BrRp = SwitchFrame.SwitchRp;
    Context->IA64Context.RsPFS = SwitchFrame.SwitchPFS;
    Context->IA64Context.StIFS = SwitchFrame.SwitchPFS;

    SHORT BsFrameSize = 
        (SHORT)(SwitchFrame.SwitchPFS >> IA64_PFS_SIZE_SHIFT) & 
        IA64_PFS_SIZE_MASK;
    SHORT TempFrameSize = 
        BsFrameSize - (SHORT)((SwitchFrame.SwitchBsp >> 3) & 
                              IA64_NAT_BITS_PER_RNAT_REG);

    while (TempFrameSize > 0) 
    {
        BsFrameSize++;
        TempFrameSize -= IA64_NAT_BITS_PER_RNAT_REG;
    } 

    Context->IA64Context.RsBSP = 
        SwitchFrame.SwitchBsp - (BsFrameSize * sizeof(ULONGLONG));

    Context->IA64Context.FltS0 = SwitchFrame.SwitchExceptionFrame.FltS0;
    Context->IA64Context.FltS1 = SwitchFrame.SwitchExceptionFrame.FltS1;
    Context->IA64Context.FltS2 = SwitchFrame.SwitchExceptionFrame.FltS2;
    Context->IA64Context.FltS3 = SwitchFrame.SwitchExceptionFrame.FltS3;
    Context->IA64Context.FltS4 = SwitchFrame.SwitchExceptionFrame.FltS4;
    Context->IA64Context.FltS5 = SwitchFrame.SwitchExceptionFrame.FltS5;
    Context->IA64Context.FltS6 = SwitchFrame.SwitchExceptionFrame.FltS6;
    Context->IA64Context.FltS7 = SwitchFrame.SwitchExceptionFrame.FltS7;
    Context->IA64Context.FltS8 = SwitchFrame.SwitchExceptionFrame.FltS8;
    Context->IA64Context.FltS9 = SwitchFrame.SwitchExceptionFrame.FltS9;
    Context->IA64Context.FltS10 = SwitchFrame.SwitchExceptionFrame.FltS10;
    Context->IA64Context.FltS11 = SwitchFrame.SwitchExceptionFrame.FltS11;
    Context->IA64Context.FltS12 = SwitchFrame.SwitchExceptionFrame.FltS12;
    Context->IA64Context.FltS13 = SwitchFrame.SwitchExceptionFrame.FltS13;
    Context->IA64Context.FltS14 = SwitchFrame.SwitchExceptionFrame.FltS14;
    Context->IA64Context.FltS15 = SwitchFrame.SwitchExceptionFrame.FltS15;
    Context->IA64Context.FltS16 = SwitchFrame.SwitchExceptionFrame.FltS16;
    Context->IA64Context.FltS17 = SwitchFrame.SwitchExceptionFrame.FltS17;
    Context->IA64Context.FltS18 = SwitchFrame.SwitchExceptionFrame.FltS18;
    Context->IA64Context.FltS19 = SwitchFrame.SwitchExceptionFrame.FltS19;
    Context->IA64Context.IntS0 = SwitchFrame.SwitchExceptionFrame.IntS0;
    Context->IA64Context.IntS1 = SwitchFrame.SwitchExceptionFrame.IntS1;
    Context->IA64Context.IntS2 = SwitchFrame.SwitchExceptionFrame.IntS2;
    Context->IA64Context.IntS3 = SwitchFrame.SwitchExceptionFrame.IntS3;
    Context->IA64Context.IntNats = SwitchFrame.SwitchExceptionFrame.IntNats;
    Context->IA64Context.BrS0 = SwitchFrame.SwitchExceptionFrame.BrS0;
    Context->IA64Context.BrS1 = SwitchFrame.SwitchExceptionFrame.BrS1;
    Context->IA64Context.BrS2 = SwitchFrame.SwitchExceptionFrame.BrS2;
    Context->IA64Context.BrS3 = SwitchFrame.SwitchExceptionFrame.BrS3;
    Context->IA64Context.BrS4 = SwitchFrame.SwitchExceptionFrame.BrS4;
    Context->IA64Context.ApEC = SwitchFrame.SwitchExceptionFrame.ApEC;
    Context->IA64Context.ApLC = SwitchFrame.SwitchExceptionFrame.ApLC;

    Frame->InstructionOffset = Context->IA64Context.StIIP;
    Frame->StackOffset = Context->IA64Context.IntSp;
    Frame->FrameOffset = Context->IA64Context.RsBSP;
        
    return S_OK;
}

int
Ia64MachineInfo::GetType(ULONG index)
{
    if (index >= IA64_FLTBASE && index <= IA64_FLTLAST)
    {
        return REGVAL_FLOAT82;
    }
    else if ((index >= INTGP && index <= INTT22) ||
             (index >= INTR32 && index <= INTR127))
    {
        return REGVAL_INT64N;
    }
    else if (index < IA64_FLAGBASE)
    {
        return REGVAL_INT64;
    }
    else
    {
        return REGVAL_SUB64;
    }
}

/*** RegGetVal - get register value
*
*   Purpose:
*       Returns the value of the register from the processor
*       context structure.
*
*   Input:
*       regnum - register specification
*
*   Returns:
*       value of the register from the context structure
*
*************************************************************************/

BOOL
Ia64MachineInfo::GetVal (ULONG regnum, REGVAL *val)
{
    switch(m_ContextState)
    {
    case MCTX_PC:
        switch (regnum)
        {
        case STIIP:
            val->type = REGVAL_INT64;
            val->i64 = m_Context.IA64Context.StIIP;
            return TRUE;
        }
        goto MctxContext;

    case MCTX_REPORT:
#if 0
        // place holder for Debug/Segment registers manipulation via
        // Control REPORT message
        switch (regnum)
        {
        case KRDBI0:
            val->type = REGVAL_INT64;
            val->i64 = SpecialRegContext.KernelDbi0;
            return TRUE;
        }
#endif

        //
        // Requested register was not in MCTX_REPORT - go get the next
        // context level.
        //

    case MCTX_NONE:
    MctxContext:
        if (GetContextState(MCTX_CONTEXT) != S_OK)
        {
            return FALSE;
        }
        // Fallthrough!
        
    case MCTX_CONTEXT:
        if (regnum >= IA64_FLTBASE && regnum <= IA64_FLTLAST)
        {
            val->type = REGVAL_FLOAT82;
            val->f16Parts.high = 0;
            memcpy(val->f82,
                   (PULONGLONG)&m_Context.IA64Context.DbI0 + regnum,
                   sizeof(val->f82));
            return TRUE;
        }
        else if ((regnum >= INTGP) && (regnum <= INTT22)) 
        {
            val->type = REGVAL_INT64N;
            val->Nat = (UCHAR)((m_Context.IA64Context.IntNats >> (regnum - INTGP + 1)) & 0x1);
            val->i64 = *((PULONGLONG)&m_Context.IA64Context.IntGp + regnum - INTGP);
            return TRUE;
        }
        else if ((regnum >= INTR32) && (regnum <= INTR127))
        {
            USHORT FrameSize;
            
            val->type = REGVAL_INT64N;
            regnum -= INTR32;
            FrameSize = (USHORT)(m_Context.IA64Context.StIFS & 0x7F);
            if (regnum >= FrameSize) {
#if 0
                ErrOut("RegGetVal: out-of-frame register r%ld requested\n",
                       regnum+32);
                return FALSE;
#else
                val->i64 = 0;
                val->Nat = TRUE;
                return TRUE;
#endif
            }
            return GetStackedRegVal(m_Context.IA64Context.RsBSP, FrameSize,
                                    m_Context.IA64Context.RsRNAT, regnum, val);
        }
        else if (regnum < IA64_SRBASE)
        {
            val->type = REGVAL_INT64;
            val->i64 = *((PULONGLONG)&m_Context.IA64Context.DbI0 + regnum);
            return TRUE;
        }

        //
        // The requested register is not in our current context, load up
        // a complete context
        //

        if (GetContextState(MCTX_FULL) != S_OK)
        {
            return FALSE;
        }
    }

    //
    // We must have a complete context...
    //

    if (regnum >= IA64_FLTBASE && regnum <= IA64_FLTLAST)
    {
        val->type = REGVAL_FLOAT82;
        val->f16Parts.high = 0;
        memcpy(val->f82,
               (PULONGLONG)&m_Context.IA64Context.DbI0 + regnum,
               sizeof(val->f82));
        return TRUE;
    }
    else if ((regnum >= INTGP) && (regnum <= INTT22))
    {
        val->type = REGVAL_INT64N;
        val->Nat = (UCHAR)((*((PULONGLONG)&m_Context.IA64Context.DbI0 + INTNATS) >> (regnum - INTGP + 1)) & 0x1);
        val->i64 = *((PULONGLONG)&m_Context.IA64Context.DbI0 + regnum);
        return TRUE;
    }
    else if ((regnum >= INTR32) && (regnum <= INTR127))
    {
        USHORT FrameSize;

        val->type = REGVAL_INT64N;
        regnum -= INTR32;
        FrameSize = (USHORT)(m_Context.IA64Context.StIFS & 0x7F);
        if (regnum >= FrameSize) {
#if 0
            ErrOut("RegGetVal: out-of-frame register r%ld requested\n",
                   regnum+32);
            return FALSE;
#else
            val->i64 = 0;
            val->Nat = TRUE;
            return TRUE;
#endif
        }
        return GetStackedRegVal(m_Context.IA64Context.RsBSP, FrameSize,
                                m_Context.IA64Context.RsRNAT, regnum, val);
    }
    else if (regnum < IA64_SRBASE)
    {
        val->type = REGVAL_INT64;
        val->i64 = *((PULONGLONG)&m_Context.IA64Context.DbI0 + regnum);
        return TRUE;
    }
    else if (IS_KERNEL_TARGET() && regnum <= IA64_SREND)
    {
        val->type = REGVAL_INT64;
        val->i64 = *((PULONGLONG)&m_SpecialRegContext.KernelDbI0 +
                     (regnum - IA64_SRBASE));
        return TRUE;
    }
    else
    {
        ErrOut("Ia64MachineInfo::GetVal: "
               "unknown register %lx requested\n", regnum);
        return FALSE;
    }
}

/*** RegSetVal - set register value
*
*   Purpose:
*       Set the value of the register in the processor context
*       structure.
*
*   Input:
*       regnum - register specification
*       regvalue - new value to set the register
*
*   Output:
*       None.
*
*************************************************************************/

BOOL
Ia64MachineInfo::SetVal (ULONG regnum, REGVAL *val)
{
    if (m_ContextIsReadOnly)
    {
        return FALSE;
    }
    
    BOOL Ia32InstructionSet = IsIA32InstructionSet();

    // Optimize away some common cases where registers are
    // set to their current value.

    if ((regnum == STIIP) && (m_ContextState >= MCTX_PC))
    {
        if (val->type != REGVAL_INT64)
        {
            return FALSE;
        }

        ULONG64 Slot, Bundle;

        if ((Ia32InstructionSet && 
             (m_Context.IA64Context.StIIP == val->i64)) ||
            ((SplitIa64Pc(val->i64, &Bundle, &Slot) &&
             (Bundle == m_Context.IA64Context.StIIP) &&
             (Slot == ((m_Context.IA64Context.StIPSR & IPSR_RI_MASK) >> 
                       PSR_RI)))))
        {
            return TRUE;
        }
    }
         
    if (GetContextState(MCTX_DIRTY) != S_OK)
    {
        return FALSE;
    }
    
    if (regnum == STIIP) 
    {
        ULONG64 Bundle, Slot;

        if ((val->type != REGVAL_INT64) || 
            !(Ia32InstructionSet || SplitIa64Pc(val->i64, &Bundle, &Slot)))
        {
            return FALSE;
        }

        if (Ia32InstructionSet) 
        {
            m_Context.IA64Context.StIIP = val->i64;
        }
        else
        {
            m_Context.IA64Context.StIIP = Bundle;
            (m_Context.IA64Context.StIPSR &= ~(IPSR_RI_MASK)) |= 
                (ULONGLONG)Slot << PSR_RI;
        }
    }
    else if (regnum >= IA64_FLTBASE && regnum <= IA64_FLTLAST)
    {
        memcpy((PULONGLONG)&m_Context.IA64Context.DbI0 + regnum,
               val->f82, sizeof(val->f82));
    }
    else if ((regnum >= INTGP) && (regnum <= INTT22))
    {
        ULONG64 Mask = (0x1i64 << (regnum - INTGP + 1));
        
        if (val->Nat) {
            m_Context.IA64Context.IntNats |= Mask;
        } else  {
            m_Context.IA64Context.IntNats &= ~Mask;
            *((PULONGLONG)&m_Context.IA64Context.DbI0 + regnum) = val->i64;
        }
    }
    else if ((regnum >= INTR32) && (regnum <= INTR127))
    {
        USHORT FrameSize;

        regnum -= INTR32;
        FrameSize = (USHORT)(m_Context.IA64Context.StIFS & 0x7F);
        if (regnum >= FrameSize) {
            ErrOut("RegSetVal: out-of-frame register r%ld requested\n",
                   regnum+32);
            return FALSE;
        }
        if (!SetStackedRegVal(m_Context.IA64Context.RsBSP, FrameSize,
                              &m_Context.IA64Context.RsRNAT, regnum, val))
        {
            return FALSE;
        }
    }
    else if (regnum < IA64_SRBASE)
    {
        *((PULONGLONG)&m_Context.IA64Context.DbI0 + regnum) = val->i64;
    }
    else if (IS_KERNEL_TARGET() && regnum <= IA64_SREND)
    {
        *((PULONGLONG)&m_SpecialRegContext.KernelDbI0 + (regnum - IA64_SRBASE)) =
            val->i64;
    }
    else
    {
        ErrOut("Ia64MachineInfo::SetVal: "
               "unknown register %lx requested\n", regnum);
        return FALSE;
    }

    NotifyChangeDebuggeeState(DEBUG_CDS_REGISTERS,
                              RegCountFromIndex(regnum));
    return TRUE;
}

void
Ia64MachineInfo::GetPC (PADDR Address)
{
    ULONG64 value, slot;

    // get slot# from IPSR.ri and place them in bit(2-3)
    slot = (GetReg64(STIPSR) >> (PSR_RI - 2)) & 0xc;
    // Do not use ISR.ei which does not contain the restart instruction slot.

    value = GetReg64(STIIP) | slot;
    ADDRFLAT(Address, value);
}

void
Ia64MachineInfo::SetPC (PADDR paddr)
{
    SetReg64(STIIP, Flat(*paddr));
}

void
Ia64MachineInfo::GetFP(PADDR Address)
{
    //  IA64 software convention has no frame pointer defined.
    //    FP_REG need to be derived from virtual unwind of stack.

    DEBUG_STACK_FRAME StackFrame;

    StackTrace( 0, 0, 0, &StackFrame, 1, 0, 0, FALSE );
    ADDRFLAT(Address, StackFrame.FrameOffset);
}

void
Ia64MachineInfo::GetSP(PADDR Address)
{
    ADDRFLAT(Address, GetReg64(INTSP));
}

ULONG64
Ia64MachineInfo::GetArgReg(void)
{
    return GetReg64(INTV0);
}

/*** RegOutputAll - output all registers and present instruction
*
*   Purpose:
*       Function of "r" command.
*
*       To output the current register state of the processor.
*       All integer registers are output as well as processor status
*       registers in the _CONTEXT record.  Important flag fields are
*       also output separately. OutDisCurrent is called to output the
*       current instruction(s).
*
*   Input:
*       None.
*
*   Output:
*       None.
*
*************************************************************************/

void
Ia64MachineInfo::OutputAll(ULONG Mask, ULONG OutMask)
{
    int       regindex, col = 0;
    int       lastout;
    USHORT    nStackReg;
    REGVAL    val;
    ULONG     i;

    if (GetContextState(MCTX_FULL) != S_OK)
    {
        ErrOut("Unable to retrieve register information\n");
        return;
    }
    
    // Output user debug registers

    if (Mask & REGALL_DREG)
    {
        for (regindex = IA64_DBBASE;
             regindex <= IA64_DBLAST;
             regindex++)
        {
            MaskOut(OutMask, "%9s = %16I64x", 
                    RegNameFromIndex(regindex),
                    GetReg64(regindex));
            if (regindex % 2 == 1)
            {
                MaskOut(OutMask, "\n");
            }
            else
            {
                MaskOut(OutMask, "\t");
            }
        }
        MaskOut(OutMask, "\n");
    }

    if (Mask & (REGALL_INT32 | REGALL_INT64))
    {
        if (Mask & REGALL_SPECIALREG)
        {
            // + ARs + DBs + SRs
            lastout = IA64_SREND + 1;
        }
        else
        {
            // INTs, PREDS, BRs,
            lastout = IA64_SRBASE;
        }

        nStackReg = (USHORT)(GetReg64(STIFS) & 0x7F);

        //   Output all registers, skip INTZERO and floating point registers

        for (regindex = IA64_REGBASE; regindex < lastout; regindex++)
        {
            if (regindex == BRRP || regindex == PREDS || regindex == APUNAT ||
                regindex == IA64_SRBASE || regindex == INTR32) 
            {
                if (col % 2 == 1)
                {
                    MaskOut(OutMask, "\n");
                }
                MaskOut(OutMask, "\n");
                col = 0;
            }

            if (INTGP <= regindex && regindex <= INTT22)
            {
                if (GetVal(regindex, &val))
                {
                    MaskOut(OutMask, "%9s = %16I64x %1lx",
                            RegNameFromIndex(regindex),
                            val.i64, val.Nat);
                }
                if (col % 2 == 1)
                {
                    MaskOut(OutMask, "\n");
                }
                else
                {
                    MaskOut(OutMask, "\t");
                }
                col++;
            }
            else if (INTR32 <= regindex && regindex <= INTR127)
            {
                if ((nStackReg != 0) && GetVal(regindex, &val))
                {
                    MaskOut(OutMask, "%9s = %16I64x %1lx",
                            RegNameFromIndex(regindex),
                            val.i64, val.Nat);
                    nStackReg--;
                    if (col % 2 == 1)
                    {
                        MaskOut(OutMask, "\n");
                    }
                    else
                    {
                        MaskOut(OutMask, "\t");
                    }
                    col++;
                }
            }
            else
            {
                MaskOut(OutMask, "%9s = %16I64x",
                        RegNameFromIndex(regindex),
                        GetReg64(regindex));
                if (col % 2 == 1)
                {
                    MaskOut(OutMask, "\n");
                }
                else
                {
                    MaskOut(OutMask, "\t");
                }
                col++;
            }
        }
        MaskOut(OutMask, "\n");

/*
        //    Output IPSR flags
        MaskOut(OutMask, "\n\tipsr:\tbn ed ri ss dd da id it tme is cpl rt tb lp db\n");
        MaskOut(OutMask, "\t\t %1lx %1lx  %1lx  %1lx  %1lx  %1lx  %1lx  %1lx  %1lx   %1lx  %1lx   %1lx  %1lx  %1lx  %1lx\n",
                GetSubReg32(IPSRBN),
                GetSubReg32(IPSRED),
                GetSubReg32(IPSRRI),
                GetSubReg32(IPSRSS),
                GetSubReg32(IPSRDD),
                GetSubReg32(IPSRDA),
                GetSubReg32(IPSRID),
                GetSubReg32(IPSRIT),
                GetSubReg32(IPSRME),
                GetSubReg32(IPSRIS),
                GetSubReg32(IPSRCPL),
                GetSubReg32(IPSRRT),
                GetSubReg32(IPSRTB),
                GetSubReg32(IPSRLP),
                GetSubReg32(IPSRDB));
        MaskOut(OutMask, "\t\tsi di pp sp dfh dfl dt bn pk i ic ac up be or\n");
        MaskOut(OutMask, "\t\t %1lx  %1lx  %1lx  %1lx  %1lx   %1lx   %1lx  %1lx  %1lx %1lx  %1lx  %1lx  %1lx  %1lx\n",
                GetSubReg32(IPSRSI),
                GetSubReg32(IPSRDI),
                GetSubReg32(IPSRPP),
                GetSubReg32(IPSRSP),
                GetSubReg32(IPSRDFH),
                GetSubReg32(IPSRDFL),
                GetSubReg32(IPSRDT),
                GetSubReg32(IPSRPK),
                GetSubReg32(IPSRI),
                GetSubReg32(IPSRIC),
                GetSubReg32(IPSRAC),
                GetSubReg32(IPSRUP),
                GetSubReg32(IPSRBE),
                GetSubReg32(IPSROR));
*/
    }

    if (Mask & REGALL_FLOAT)
    {
/*
        //    Output FPSR flags
        MaskOut(OutMask, "\n\tfpsr:\tmdh mdl  sf3  sf2  sf1  sf0  id ud od zd dd vd\n");
        MaskOut(OutMask, "\t\t %1lx   %1lx  %04lx %04lx %04lx %04lx   %1lx  %1lx  %1lx  %1lx  %1lx  %1lx\n",
                GetSubReg32(FPSRMDH),
                GetSubReg32(FPSRMDL),
                GetSubReg32(FPSRSF3),
                GetSubReg32(FPSRSF2),
                GetSubReg32(FPSRSF1),
                GetSubReg32(FPSRSF0),
                GetSubReg32(FPSRTRAPID),
                GetSubReg32(FPSRTRAPUD),
                GetSubReg32(FPSRTRAPOD),
                GetSubReg32(FPSRTRAPZD),
                GetSubReg32(FPSRTRAPDD),
                GetSubReg32(FPSRTRAPVD));
*/

        //
        // Print the low floating point register set, skip FLTZERO & FLTONE
        //

        MaskOut(OutMask, "\n");
        for (i = IA64_FLTBASE; i < FLTF32; i += 2)
        {
            GetVal(i, &val);
            MaskOut(OutMask, "%9s = %I64x %I64x\n", RegNameFromIndex(i),
                    val.f16Parts.high, val.f16Parts.low);
        }
    }

    if (Mask & REGALL_HIGHFLOAT)
    {
        //
        // Print the low floating point register set, skip FLTZERO & FLTONE
        //

        MaskOut(OutMask, "\n");
        for (i = FLTF32 ; i <= FLTF127; i += 2)
        {
            GetVal(i, &val);
            MaskOut(OutMask, "%9s = %I64x %I64x\n", RegNameFromIndex(i),
                    val.f16Parts.high, val.f16Parts.low);
        }
    }
}

TRACEMODE
Ia64MachineInfo::GetTraceMode (void)
{
    if (IS_KERNEL_TARGET())
    {
        return m_TraceMode;
    }
    else
    {
        ULONG64 Ipsr = GetReg64(STIPSR);
        if (Ipsr & (1I64 << PSR_SS)) 
        {
            return TRACE_INSTRUCTION;
        }
        else if (Ipsr & (1I64 << PSR_TB)) 
        {
            return TRACE_TAKEN_BRANCH;
        }
        else 
        {
            return TRACE_NONE;
        }
    }
}

void
Ia64MachineInfo::SetTraceMode (TRACEMODE Mode)
{
    DBG_ASSERT(Mode == TRACE_NONE ||
               Mode == TRACE_INSTRUCTION ||
               Mode == TRACE_TAKEN_BRANCH);

    if (IS_KERNEL_TARGET())
    {
        m_TraceMode = Mode;
    }
    else 
    {
        ULONG64 Ipsr, IpsrSave;
        Ipsr = IpsrSave = GetReg64(STIPSR);

        Ipsr &= ~(1I64 << PSR_SS);
        Ipsr &= ~(1I64 << PSR_TB);

        switch (Mode) 
        {
        case TRACE_INSTRUCTION:
            Ipsr |= (1I64 << PSR_SS);
            break;
        case TRACE_TAKEN_BRANCH:
            Ipsr |= (1I64 << PSR_TB);
            break;
        }
        
        if (Ipsr != IpsrSave)
        {
            SetReg64(STIPSR, Ipsr);
        }
    }
}

BOOL
Ia64MachineInfo::IsStepStatusSupported(ULONG Status)
{
    switch (Status) 
    {
    case DEBUG_STATUS_STEP_INTO:   // TRACE_INSTRUCTION
    case DEBUG_STATUS_STEP_OVER:   
    case DEBUG_STATUS_STEP_BRANCH: // TRACE_TAKEN_BRANCH
        return TRUE;
    default:
        return FALSE;
    }
}

void
Ia64MachineInfo::KdUpdateControlSet
    (PDBGKD_ANY_CONTROL_SET ControlSet)
{
    switch (GetTraceMode()) 
    {
    case TRACE_NONE:
        ControlSet->IA64ControlSet.Continue = 
            IA64_DBGKD_CONTROL_SET_CONTINUE_NONE;
        break;

    case TRACE_INSTRUCTION:
        ControlSet->IA64ControlSet.Continue = 
            IA64_DBGKD_CONTROL_SET_CONTINUE_TRACE_INSTRUCTION;
        break;

    case TRACE_TAKEN_BRANCH:
        ControlSet->IA64ControlSet.Continue = 
            IA64_DBGKD_CONTROL_SET_CONTINUE_TRACE_TAKEN_BRANCH;
        break;
    }

    if (!g_WatchFunctions.IsStarted() && g_WatchBeginCurFunc != 1)
    {
        ControlSet->IA64ControlSet.CurrentSymbolStart = 0;
        ControlSet->IA64ControlSet.CurrentSymbolEnd = 0;
    }
    else
    {
        ControlSet->IA64ControlSet.CurrentSymbolStart = g_WatchBeginCurFunc;
        ControlSet->IA64ControlSet.CurrentSymbolEnd = g_WatchEndCurFunc;
    }
}

void
Ia64MachineInfo::KdSaveProcessorState(
    void
    )
{
    MachineInfo::KdSaveProcessorState();
    m_SavedSpecialRegContext = m_SpecialRegContext;
}

void
Ia64MachineInfo::KdRestoreProcessorState(
    void
    )
{
    MachineInfo::KdRestoreProcessorState();
    m_SpecialRegContext = m_SavedSpecialRegContext;
}

ULONG
Ia64MachineInfo::ExecutingMachine(void)
{
    if (IsIA32InstructionSet())
    {
        return IMAGE_FILE_MACHINE_I386;
    }

    return IMAGE_FILE_MACHINE_IA64;
}

HRESULT
Ia64MachineInfo::SetPageDirectory(ULONG Idx, ULONG64 PageDir,
                                  PULONG NextIdx)
{
    HRESULT Status;

    switch(Idx)
    {
    case PAGE_DIR_USER:
        if (PageDir == 0)
        {
            if ((Status = g_Target->ReadImplicitProcessInfoPointer
                 (m_OffsetEprocessDirectoryTableBase, &PageDir)) != S_OK)
            {
                return Status;
            }
        }
        *NextIdx = PAGE_DIR_SESSION;
        break;

    case PAGE_DIR_SESSION:
        if (PageDir == 0)
        {
            if ((Status = g_Target->
                 ReadImplicitProcessInfoPointer
                 (g_Machine->m_OffsetEprocessDirectoryTableBase +
                  5 * sizeof(ULONG64), &PageDir)) != S_OK)
            {
                return Status;
            }
        }
        *NextIdx = PAGE_DIR_KERNEL;
        break;

    case PAGE_DIR_KERNEL:
        if (PageDir == 0)
        {
            PageDir = m_KernPageDir;
            if (PageDir == 0)
            {
                ErrOut("Invalid IA64 kernel page directory base 0x%I64x\n",
                       PageDir);
                return E_FAIL;
            }
        }
        *NextIdx = PAGE_DIR_COUNT;
        break;

    case 4:
        // There's a directly mapped physical section for
        // most of region 4 so allow the default to be
        // set for this directory index.
        if (PageDir != 0)
        {
            return E_INVALIDARG;
        }
        *NextIdx = 5;
        break;
        
    default:
        return E_INVALIDARG;
    }

    // Sanitize the value.
    m_PageDirectories[Idx] =
        ((PageDir & IA64_VALID_PFN_MASK) >> IA64_VALID_PFN_SHIFT) <<
        IA64_PAGE_SHIFT;
    return S_OK;
}

#define IA64_PAGE_FILE_INDEX(Entry) \
    (((ULONG)(Entry) >> 28) & MAX_PAGING_FILE_MASK)
#define IA64_PAGE_FILE_OFFSET(Entry) \
    (((Entry) >> 32) << IA64_PAGE_SHIFT)

HRESULT
Ia64MachineInfo::GetVirtualTranslationPhysicalOffsets(ULONG64 Virt,
                                                      PULONG64 Offsets,
                                                      ULONG OffsetsSize,
                                                      PULONG Levels,
                                                      PULONG PfIndex,
                                                      PULONG64 LastVal)
{
    HRESULT Status;

    *Levels = 0;
    
    if (m_Translating)
    {
        return E_UNEXPECTED;
    }
    m_Translating = TRUE;
    
    ULONG Vrn = (ULONG)((Virt & IA64_REGION_MASK) >> IA64_REGION_SHIFT);
    
    //
    // Reset the page directory in case it was 0
    //
    if (m_PageDirectories[Vrn] == 0)
    {
        if ((Status = SetDefaultPageDirectories(1 << Vrn)) != S_OK)
        {
            m_Translating = FALSE;
            return Status;
        }
    }

    KdOut("Ia64VtoP: Virt %s, pagedir %d:%s\n",
          FormatAddr64(Virt), Vrn, FormatAddr64(m_PageDirectories[Vrn]));
    
    (*Levels)++;
    if (Offsets != NULL && OffsetsSize > 0)
    {
        *Offsets++ = m_PageDirectories[Vrn];
        OffsetsSize--;
    }
        
    //
    // Certain ranges of the system are mapped directly.
    //

    if ((Virt >= IA64_PHYSICAL1_START) && (Virt <= IA64_PHYSICAL1_END))
    {
        *LastVal = Virt - IA64_PHYSICAL1_START;

        KdOut("Ia64VtoP: Direct phys 1 %s\n", FormatAddr64(*LastVal));

        (*Levels)++;
        if (Offsets != NULL && OffsetsSize > 0)
        {
            *Offsets++ = *LastVal;
            OffsetsSize--;
        }
        
        m_Translating = FALSE;
        return S_OK;
    }
    if ((Virt >= IA64_PHYSICAL2_START) && (Virt <= IA64_PHYSICAL2_END))
    {
        *LastVal = Virt - IA64_PHYSICAL2_START;

        KdOut("Ia64VtoP: Direct phys 2 %s\n", FormatAddr64(*LastVal));

        (*Levels)++;
        if (Offsets != NULL && OffsetsSize > 0)
        {
            *Offsets++ = *LastVal;
            OffsetsSize--;
        }
        
        m_Translating = FALSE;
        return S_OK;
    }

    // If we're still translating and there's no page
    // directory we have a garbage address.
    if (m_PageDirectories[Vrn] == 0)
    {
        m_Translating = FALSE;
        return HR_PAGE_NOT_AVAILABLE;
    }
        
    ULONG64 Addr;
    ULONG64 Entry;
    
    Addr = (((Virt >> IA64_PDE1_SHIFT) & IA64_PDE_MASK) * sizeof(Entry)) +
        m_PageDirectories[Vrn];

    Status = g_Target->ReadAllPhysical(Addr, &Entry, sizeof(Entry));
    
    KdOut("Ia64VtoP: PDE1 %s - %016I64x, 0x%X\n",
          FormatAddr64(Addr), Entry, Status);
    
    (*Levels)++;
    if (Offsets != NULL && OffsetsSize > 0)
    {
        *Offsets++ = Addr;
        OffsetsSize--;
    }
        
    if (Status != S_OK)
    {
        KdOut("Ia64VtoP: PDE1 read error 0x%X\n", Status);
        m_Translating = FALSE;
        return Status;
    }

    if (Entry == 0)
    {
        KdOut("Ia64VtoP: zero PDE1\n");
        m_Translating = FALSE;
        return HR_PAGE_NOT_AVAILABLE;
    }
    else if (!(Entry & 1))
    {
        Addr = (((Virt >> IA64_PDE2_SHIFT) & IA64_PDE_MASK) *
                sizeof(Entry)) + IA64_PAGE_FILE_OFFSET(Entry);

        KdOut("Ia64VtoP: pagefile PDE2 %d:%s\n",
              IA64_PAGE_FILE_INDEX(Entry), FormatAddr64(Addr));
        
        if ((Status = g_Target->
             ReadPageFile(IA64_PAGE_FILE_INDEX(Entry), Addr,
                          &Entry, sizeof(Entry))) != S_OK)
        {
            KdOut("Ia64VtoP: PDE1 not present, 0x%X\n", Status);
            m_Translating = FALSE;
            return Status;
        }
    }
    else
    {
        Addr = (((Virt >> IA64_PDE2_SHIFT) & IA64_PDE_MASK) * sizeof(Entry)) +
            (((Entry & IA64_VALID_PFN_MASK) >> IA64_VALID_PFN_SHIFT) <<
             IA64_PAGE_SHIFT);

        Status = g_Target->ReadAllPhysical(Addr, &Entry, sizeof(Entry));
    
        KdOut("Ia64VtoP: PDE2 %s - %016I64x, 0x%X\n",
              FormatAddr64(Addr), Entry, Status);
    
        (*Levels)++;
        if (Offsets != NULL && OffsetsSize > 0)
        {
            *Offsets++ = Addr;
            OffsetsSize--;
        }
        
        if (Status != S_OK)
        {
            KdOut("Ia64VtoP: PDE2 read error 0x%X\n", Status);
            m_Translating = FALSE;
            return Status;
        }
    }
    
    if (Entry == 0)
    {
        KdOut("Ia64VtoP: zero PDE2\n");
        m_Translating = FALSE;
        return HR_PAGE_NOT_AVAILABLE;
    }
    else if (!(Entry & 1))
    {
        Addr = (((Virt >> IA64_PTE_SHIFT) & IA64_PTE_MASK) *
                sizeof(Entry)) + IA64_PAGE_FILE_OFFSET(Entry);

        KdOut("Ia64VtoP: pagefile PTE %d:%s\n",
              IA64_PAGE_FILE_INDEX(Entry), FormatAddr64(Addr));
        
        if ((Status = g_Target->
             ReadPageFile(IA64_PAGE_FILE_INDEX(Entry), Addr,
                          &Entry, sizeof(Entry))) != S_OK)
        {
            KdOut("Ia64VtoP: PDE2 not present, 0x%X\n", Status);
            m_Translating = FALSE;
            return Status;
        }
    }
    else
    {
        Addr = (((Virt >> IA64_PTE_SHIFT) & IA64_PTE_MASK) * sizeof(Entry)) +
            (((Entry & IA64_VALID_PFN_MASK) >> IA64_VALID_PFN_SHIFT) <<
             IA64_PAGE_SHIFT);

        Status = g_Target->ReadAllPhysical(Addr, &Entry, sizeof(Entry));
    
        KdOut("Ia64VtoP: PTE %s - %016I64x, 0x%X\n",
              FormatAddr64(Addr), Entry, Status);
    
        (*Levels)++;
        if (Offsets != NULL && OffsetsSize > 0)
        {
            *Offsets++ = Addr;
            OffsetsSize--;
        }
        
        if (Status != S_OK)
        {
            KdOut("Ia64VtoP: PTE read error 0x%X\n", Status);
            m_Translating = FALSE;
            return Status;
        }
    }
    
    if (!(Entry & 0x1) &&
        ((Entry & IA64_MM_PTE_PROTOTYPE_MASK) ||
         !(Entry & IA64_MM_PTE_TRANSITION_MASK)))
    {
        if (Entry == 0)
        {
            KdOut("Ia64VtoP: zero PTE\n");
            Status = HR_PAGE_NOT_AVAILABLE;
        }
        else if (Entry & IA64_MM_PTE_PROTOTYPE_MASK)
        {
            KdOut("Ia64VtoP: prototype PTE\n");
            Status = HR_PAGE_NOT_AVAILABLE;
        }
        else
        {
            *PfIndex = IA64_PAGE_FILE_INDEX(Entry);
            *LastVal = (Virt & (IA64_PAGE_SIZE - 1)) +
                IA64_PAGE_FILE_OFFSET(Entry);
            KdOut("Ia64VtoP: PTE not present, pagefile %d:%s\n",
                  *PfIndex, FormatAddr64(*LastVal));
            Status = HR_PAGE_IN_PAGE_FILE;
        }
        m_Translating = FALSE;
        return Status;
    }

    //
    // This is a page which is either present or in transition.
    // Return the physical address for the request virtual address.
    //
    
    *LastVal = (((Entry & IA64_VALID_PFN_MASK) >> IA64_VALID_PFN_SHIFT) <<
                 IA64_PAGE_SHIFT) | (Virt & (IA64_PAGE_SIZE - 1));
    
    KdOut("Ia64VtoP: Mapped phys %s\n", FormatAddr64(*LastVal));

    (*Levels)++;
    if (Offsets != NULL && OffsetsSize > 0)
    {
        *Offsets++ = *LastVal;
        OffsetsSize--;
    }
        
    m_Translating = FALSE;
    return S_OK;
}

HRESULT
Ia64MachineInfo::GetBaseTranslationVirtualOffset(PULONG64 Offset)
{
    if (IS_LOCAL_KERNEL_TARGET())
    {
        CROSS_PLATFORM_KSPECIAL_REGISTERS Special;
        HRESULT Status;
        
        // We can't actually load a context when
        // local kernel debugging but we can
        // read the special registers and get
        // the PTA value from there.
        if ((Status = g_Target->GetTargetSpecialRegisters
             (VIRTUAL_THREAD_HANDLE(0), &Special)) != S_OK)
        {
            return Status;
        }

        *Offset = Special.IA64Special.ApPTA;
    }
    else
    {
        *Offset = GetReg64(APPTA);
        if (*Offset == 0)
        {
            return E_FAIL;
        }
    }
    return S_OK;
}

#define HIGH128(x) (((FLOAT128 *)(&x))->HighPart)
#define LOW128(x) (((FLOAT128 *)(&x))->LowPart)

#define HIGHANDLOW128(x) HIGH128(x), LOW128(x)

BOOL 
Ia64MachineInfo::DisplayTrapFrame(ULONG64 FrameAddress,
                                  OUT PCROSS_PLATFORM_CONTEXT Context)
{
    IA64_KTRAP_FRAME TrapContents;

    ULONG64 Address=FrameAddress, IntSp;
    ULONG result;
    DWORD64 DisasmAddr;
    DWORD64 Displacement;
    DWORD64 Bsp, RealBsp;
    DWORD SizeOfFrame;
    DWORD i;
    SHORT temp, j;
    CHAR Buffer[80];
    ULONG64 StIIP, StISR;

    if ( g_Target->ReadVirtual(Address, &TrapContents, sizeof(IA64_KTRAP_FRAME), &result) != S_OK)
    {
        dprintf("unable to get trap frame contents\n");
        return FALSE;
    }

    dprintf("f6 (ft0) =\t %016I64x %016I64x\n" , HIGHANDLOW128(TrapContents.FltT0) );
    dprintf("f7 (ft1) =\t %016I64x %016I64x\n" , HIGHANDLOW128(TrapContents.FltT1));
    dprintf("f8 (ft2) =\t %016I64x %016I64x\n" , HIGHANDLOW128(TrapContents.FltT2));
    dprintf("f9 (ft3) =\t %016I64x %016I64x\n" , HIGHANDLOW128(TrapContents.FltT3));
    dprintf("f10 (ft3) =\t %016I64x %016I64x\n" , HIGHANDLOW128(TrapContents.FltT4));
    dprintf("f11 (ft4) =\t %016I64x %016I64x\n" , HIGHANDLOW128(TrapContents.FltT5));
    dprintf("f12 (ft5) =\t %016I64x %016I64x\n" , HIGHANDLOW128(TrapContents.FltT6));
    dprintf("f13 (ft6) =\t %016I64x %016I64x\n" , HIGHANDLOW128(TrapContents.FltT7));
    dprintf("f14 (ft7) =\t %016I64x %016I64x\n" , HIGHANDLOW128(TrapContents.FltT8));
    dprintf("f15 (ft8) =\t %016I64x %016I64x\n" , HIGHANDLOW128(TrapContents.FltT9));

    dprintf("unat =\t %016I64lx\t", TrapContents.ApUNAT);
    dprintf("ccv =\t %016I64lx\n" , TrapContents.ApCCV);
    dprintf("dcr =\t %016I64lx\t" , TrapContents.ApDCR);
    dprintf("preds =\t %016I64lx\n",TrapContents.Preds);

    dprintf("rsc =\t %016I64lx\t",  TrapContents.RsRSC);

    SizeOfFrame = (ULONG)(TrapContents.StIFS & (IA64_PFS_SIZE_MASK));

    if (TrapContents.PreviousMode == 1 /*UserMode*/)
    {
        ULONG64 RsBSPSTORE=TrapContents.RsBSPSTORE;
        dprintf("rnat =\t %016I64lx\n", TrapContents.RsRNAT);
        dprintf("bspstore=%016I64lx\n", RsBSPSTORE);

        //
        // Calculate where the stacked registers are for the function which trapped.  
        // The regisisters are stored in the kernel backing store notCalculated the users.  
        // First calculate the start of the kernel store based on trap address, since 
        // this is a user mode trap we should start at the begining of the kernel stack
        // so just round up the trap address to a page size.  Next calculate the actual 
        // BSP for the function.  This depends on the  BSP and BSPstore at the time of
        // the trap.  Note that the trap handle start the kernel backing store on the 
        // same alignment as the user's BSPstore.  
        // 

        //Calculated
        // Round trap address to a page boundary. The should be the Initial kernel BSP.
        //

        Bsp = (Address + IA64_PAGE_SIZE - 1) & ~(DWORD64)(IA64_PAGE_SIZE - 1);

        //
        // Start the actual stack on the same bountry as the users.
        //

        Bsp += RsBSPSTORE & IA64_RNAT_ALIGNMENT;

        //
        // The BSP of the trap handler is right after all the user values have been
        // saved.  The unsaved user values is the differenc of BSP and BSPStore.
        //

        Bsp += TrapContents.RsBSP - RsBSPSTORE;

    }
    else
    {
        dprintf("rnat =\t ???????? ????????\n", TrapContents.RsRNAT);
        dprintf("bspstore=???????? ????????\n", TrapContents.RsBSPSTORE);

        //
        // For kernel mode the actual BSP is saved.
        //

        Bsp = TrapContents.RsBSP;
    }

    //
    //  Now backup by the size of the faulting functions frame.
    //

    Bsp -= (SizeOfFrame * sizeof(ULONGLONG));

    //
    // Adjust for saved RNATs
    //

    temp = (SHORT)(Bsp >> 3) & IA64_NAT_BITS_PER_RNAT_REG;
    temp += (SHORT)SizeOfFrame - IA64_NAT_BITS_PER_RNAT_REG;
    while (temp >= 0)
    {
        Bsp -= sizeof(ULONGLONG);
        temp -= IA64_NAT_BITS_PER_RNAT_REG;
    }

    dprintf("bsp =\t %016I64lx\t",  TrapContents.RsBSP);
    dprintf("Real bsp = %016I64lx\n",  RealBsp = Bsp);


    dprintf("r1 (gp) =\t %016I64lx\t" ,  TrapContents.IntGp);
    dprintf("r2 (t0) =\t %016I64lx\n" ,  TrapContents.IntT0);
    dprintf("r3 (t1) =\t %016I64lx\t" ,  TrapContents.IntT1);
    dprintf("r8 (v0) =\t %016I64lx\n" ,  TrapContents.IntV0);
    dprintf("r9 (t2) =\t %016I64lx\t" ,  TrapContents.IntT2);
    dprintf("r10 (t3) =\t %016I64lx\n" ,  TrapContents.IntT3);
    dprintf("r11 (t4) =\t %016I64lx\t" ,  TrapContents.IntT4);
    dprintf("r12 (sp) =\t %016I64lx\n" ,  IntSp = TrapContents.IntSp);
    dprintf("r13 (teb) =\t %016I64lx\t" , TrapContents.IntTeb);
    dprintf("r14 (t5) =\t %016I64lx\n" ,  TrapContents.IntT5);
    dprintf("r15 (t6) =\t %016I64lx\t" ,  TrapContents.IntT6);
    dprintf("r16 (t7) =\t %016I64lx\n" ,  TrapContents.IntT7);
    dprintf("r17 (t8) =\t %016I64lx\t" ,  TrapContents.IntT8);
    dprintf("r18 (t9) =\t %016I64lx\n" ,  TrapContents.IntT9);
    dprintf("r19 (t10) =\t %016I64lx\t" , TrapContents.IntT10);
    dprintf("r20 (t11) =\t %016I64lx\n" , TrapContents.IntT11);
    dprintf("r21 (t12) =\t %016I64lx\t" , TrapContents.IntT12);
    dprintf("r22 (t13) =\t %016I64lx\n" , TrapContents.IntT13);
    dprintf("r23 (t14) =\t %016I64lx\t" , TrapContents.IntT14);
    dprintf("r24 (t15) =\t %016I64lx\n" , TrapContents.IntT15);
    dprintf("r25 (t16) =\t %016I64lx\t" , TrapContents.IntT16);
    dprintf("r26 (t17) =\t %016I64lx\n" , TrapContents.IntT17);
    dprintf("r27 (t18) =\t %016I64lx\t" , TrapContents.IntT18);
    dprintf("r28 (t19) =\t %016I64lx\n" , TrapContents.IntT19);
    dprintf("r29 (t20) =\t %016I64lx\t" , TrapContents.IntT20);
    dprintf("r30 (t21) =\t %016I64lx\n" , TrapContents.IntT21);
    dprintf("r31 (t22) =\t %016I64lx\n" , TrapContents.IntT22);

    //
    // Print out the stack registers.
    //

    for ( i = 0; i < SizeOfFrame; Bsp += sizeof(ULONGLONG))
    {
        ULONGLONG reg;

        //
        // Skip the NAT values.
        //

        if ((Bsp & IA64_RNAT_ALIGNMENT) == IA64_RNAT_ALIGNMENT)
        {
            continue;
        }

        if ( g_Target->ReadVirtual( Bsp, &reg, sizeof(ULONGLONG), &result) )
        {
            dprintf("Cannot read backing register store at %16I64x\n", Bsp);
        }

        dprintf("r%d =\t\t %016I64lx", (i + 32), reg);

        if ((i % 2) == 1)
        {
            dprintf("\n");
        }
        else
        {
            dprintf("\t");
        }

        i++;
    }

    dprintf("\n");


    dprintf("b0 (brrp) =\t %016I64lx\n", TrapContents.BrRp);
    dprintf("b6 (brt0) =\t %016I64lx\n", TrapContents.BrT0);
    dprintf("b7 (brt1) =\t %016I64lx\n", TrapContents.BrT1);


    dprintf("nats =\t %016I64lx\n", TrapContents.IntNats);
    dprintf("pfs =\t %016I64lx\n",  TrapContents.RsPFS);

    dprintf("ipsr =\t %016I64lx\n", TrapContents.StIPSR);
    dprintf("isr =\t %016I64lx\n" , (StISR = TrapContents.StISR));
    dprintf("ifa =\t %016I64lx\n" , TrapContents.StIFA);
    dprintf("iip =\t %016I64lx\n" , StIIP = TrapContents.StIIP);
    dprintf("iipa =\t %016I64lx\n", TrapContents.StIIPA);
    dprintf("ifs =\t %016I64lx\n" , TrapContents.StIFS);
    dprintf("iim =\t %016I64lx\n" , TrapContents.StIIM);
    dprintf("iha =\t %016I64lx\n" , TrapContents.StIHA);

    dprintf("fpsr =\t\t  %08lx\n" , TrapContents.StFPSR);


    //  iA32 status info ???

    dprintf("oldirql =\t  %08lx\n" , TrapContents.OldIrql);
    dprintf("previousmode =\t  %08lx\n" , TrapContents.PreviousMode);
    dprintf("trapframe =\t  %08lx\n" , TrapContents.TrapFrame);

    ULONG TrapFrameType = (ULONG)(TrapContents.EOFMarker) & 0xf;

    switch (TrapFrameType)
    {
    case IA64_SYSCALL_FRAME:
        dprintf("Trap Type: syscall\n");
        break;
    case IA64_INTERRUPT_FRAME:
        dprintf("Trap Type: interrupt\n");
        break;
    case IA64_EXCEPTION_FRAME:
        dprintf("Trap Type: exception\n");
        break;
    case IA64_CONTEXT_FRAME:
        dprintf("Trap Type: context\n");
        break;
    default:
        dprintf("Trap Type: unknown\n");
        break;
    }

    DisasmAddr = StIIP;

    //
    // Adjust for the bundle. 
    //

    DisasmAddr += ((StISR >> 41) & 3) * 4;

    GetSymbolStdCall(DisasmAddr, Buffer, sizeof(Buffer), &Displacement, NULL);
    dprintf("\n%s+0x%I64x\n", Buffer, Displacement);
    
    ADDR    tempAddr;
    BOOL    ret;

    Type(tempAddr) = ADDR_FLAT | FLAT_COMPUTED;
    Off(tempAddr) = Flat(tempAddr) = DisasmAddr;
    if (g_Machine->Disassemble(&tempAddr, Buffer, FALSE))
    {

        dprintf(Buffer);

    }
    else
    {

        dprintf("???????????????\n", DisasmAddr);
    }
    
    g_LastRegFrame.InstructionOffset  = StIIP;
    g_LastRegFrame.StackOffset        = IntSp;
    g_LastRegFrame.FrameOffset        = RealBsp;

    if (Context) 
    {
        // Fill up the context struct
#define CPCXT(Fld) Context->IA64Context.Fld = TrapContents.Fld

        CPCXT(BrRp); CPCXT(BrT0); CPCXT(BrT1);

        CPCXT(FltT0); CPCXT(FltT1); CPCXT(FltT2); CPCXT(FltT3); CPCXT(FltT4);
        CPCXT(FltT5); CPCXT(FltT6); CPCXT(FltT7); CPCXT(FltT8); CPCXT(FltT9);

        CPCXT(ApUNAT); CPCXT(ApCCV); CPCXT(ApDCR); CPCXT(Preds); 

        CPCXT(RsRSC); CPCXT(RsRNAT); CPCXT(RsBSPSTORE); CPCXT(RsBSP); CPCXT(RsPFS);

        CPCXT(StIPSR); CPCXT(StIIP); CPCXT(StIFS); CPCXT(StFPSR);
        CPCXT(IntSp);  CPCXT(IntGp); CPCXT(IntV0); CPCXT(IntTeb); CPCXT(IntNats);

        CPCXT(IntT0);  CPCXT(IntT1);  CPCXT(IntT2);  CPCXT(IntT3);  CPCXT(IntT4);  
        CPCXT(IntT5);  CPCXT(IntT6);  CPCXT(IntT7);  CPCXT(IntT8);  CPCXT(IntT9);  
        CPCXT(IntT10); CPCXT(IntT11); CPCXT(IntT12); CPCXT(IntT13); CPCXT(IntT14);  
        CPCXT(IntT15); CPCXT(IntT16); CPCXT(IntT17); CPCXT(IntT18); CPCXT(IntT19);  
        CPCXT(IntT20); CPCXT(IntT21); CPCXT(IntT22); 

        Context->IA64Context.RsBSP = RealBsp; // Store the real Bsp
#undef CPCXT
    }
    return TRUE;
}

void
Ia64MachineInfo::ValidateCxr(PCROSS_PLATFORM_CONTEXT Context)
{
    // XXX drewb - Why doesn't this do anything?
}

void
Ia64MachineInfo::OutputFunctionEntry(PVOID RawEntry)
{
    PIMAGE_IA64_RUNTIME_FUNCTION_ENTRY Entry =
        (PIMAGE_IA64_RUNTIME_FUNCTION_ENTRY)RawEntry;
    
    dprintf("BeginAddress      = %s\n",
            FormatAddr64(Entry->BeginAddress));
    dprintf("EndAddress        = %s\n",
            FormatAddr64(Entry->EndAddress));
    dprintf("UnwindInfoAddress = %s\n",
            FormatAddr64(Entry->UnwindInfoAddress));
}

HRESULT
Ia64MachineInfo::ReadDynamicFunctionTable(ULONG64 Table,
                                          PULONG64 NextTable,
                                          PULONG64 MinAddress,
                                          PULONG64 MaxAddress,
                                          PULONG64 BaseAddress,
                                          PULONG64 TableData,
                                          PULONG TableSize,
                                          PWSTR OutOfProcessDll,
                                          PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE RawTable)
{
    HRESULT Status;

    if ((Status = g_Target->
         ReadAllVirtual(Table, &RawTable->IA64Table,
                        sizeof(RawTable->IA64Table))) != S_OK)
    {
        return Status;
    }

    *NextTable = RawTable->IA64Table.Links.Flink;
    *MinAddress = RawTable->IA64Table.MinimumAddress;
    *MaxAddress = RawTable->IA64Table.MaximumAddress;
    *BaseAddress = RawTable->IA64Table.BaseAddress;
    if (RawTable->IA64Table.Type == IA64_RF_CALLBACK)
    {
        ULONG Done;
        
        *TableData = 0;
        *TableSize = 0;
        if ((Status = g_Target->
             ReadVirtual(RawTable->IA64Table.OutOfProcessCallbackDll,
                         OutOfProcessDll, (MAX_PATH - 1) * sizeof(WCHAR),
                         &Done)) != S_OK)
        {
            return Status;
        }

        OutOfProcessDll[Done / sizeof(WCHAR)] = 0;
    }
    else
    {
        *TableData = RawTable->IA64Table.FunctionTable;
        *TableSize = RawTable->IA64Table.EntryCount *
            sizeof(IMAGE_IA64_RUNTIME_FUNCTION_ENTRY);
        OutOfProcessDll[0] = 0;
    }
    return S_OK;
}

PVOID
Ia64MachineInfo::FindDynamicFunctionEntry(PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE Table,
                                          ULONG64 Address,
                                          PVOID TableData,
                                          ULONG TableSize)
{
    ULONG i;
    PIMAGE_IA64_RUNTIME_FUNCTION_ENTRY Func;
    static IMAGE_IA64_RUNTIME_FUNCTION_ENTRY s_RetFunc;

    Func = (PIMAGE_IA64_RUNTIME_FUNCTION_ENTRY)TableData;
    for (i = 0; i < TableSize / sizeof(IMAGE_IA64_RUNTIME_FUNCTION_ENTRY); i++)
    {
        if (Address >= IA64_RF_BEGIN_ADDRESS(Table->IA64Table.BaseAddress, Func) &&
            Address < IA64_RF_END_ADDRESS(Table->IA64Table.BaseAddress, Func))
        {
            // The table data is temporary so copy the data into
            // a static buffer for longer-term storage.
            s_RetFunc.BeginAddress = Func->BeginAddress;
            s_RetFunc.EndAddress = Func->EndAddress;
            s_RetFunc.UnwindInfoAddress = Func->UnwindInfoAddress;
            return (PVOID)&s_RetFunc;
        }

        Func++;
    }

    return NULL;
}

HRESULT
Ia64MachineInfo::ReadKernelProcessorId
    (ULONG Processor, PDEBUG_PROCESSOR_IDENTIFICATION_ALL Id)
{
    HRESULT Status;
    ULONG64 Prcb, PrcbMember;
    ULONG Data[4];

    if ((Status = g_Target->
         GetProcessorSystemDataOffset(Processor, DEBUG_DATA_KPRCB_OFFSET,
                                      &Prcb)) != S_OK)
    {
        return Status;
    }

    PrcbMember = Prcb + FIELD_OFFSET(IA64_PARTIAL_KPRCB, ProcessorModel);

    if ((Status = g_Target->
         ReadAllVirtual(PrcbMember, Data, sizeof(Data))) != S_OK)
    {
        return Status;
    }

    Id->Ia64.Model = Data[0];
    Id->Ia64.Revision = Data[1];
    Id->Ia64.Family = Data[2];
    Id->Ia64.ArchRev = Data[3];
    
    PrcbMember = Prcb + FIELD_OFFSET(IA64_PARTIAL_KPRCB,
                                     ProcessorVendorString);

    if ((Status = g_Target->
         ReadAllVirtual(PrcbMember, Id->Ia64.VendorString,
                        sizeof(Id->Ia64.VendorString))) != S_OK)
    {
        return Status;
    }

    return S_OK;
}

BOOL
Ia64MachineInfo::IsIA32InstructionSet(VOID)
{
    return ((GetReg64(STIPSR) & (1I64 << PSR_IS)) ? TRUE : FALSE);
}

void
Ia64MachineInfo::KdGetSpecialRegistersFromContext(void)
{
    DBG_ASSERT(m_ContextState >= MCTX_FULL);

    memcpy(&m_SpecialRegContext.KernelDbI0, &m_Context.IA64Context.DbI0,
           IA64_DB_COUNT * sizeof(ULONG64));
}

void
Ia64MachineInfo::KdSetSpecialRegistersInContext(void)
{
    DBG_ASSERT(m_ContextState >= MCTX_FULL);

    memcpy(&m_Context.IA64Context.DbI0, &m_SpecialRegContext.KernelDbI0,
           IA64_DB_COUNT * sizeof(ULONG64));
}

BOOL
Ia64MachineInfo::GetStackedRegVal(
    IN ULONG64 RsBSP, 
    IN USHORT FrameSize, 
    IN ULONG64 RsRNAT, 
    IN ULONG regnum, 
    OUT REGVAL *val
    )
{
    SHORT index;
    SHORT temp;
    ULONG result;
    ULONG64 TargetAddress;
    ULONG64 TargetNatAddress;

    index = (SHORT)(RsBSP >> 3) & NAT_BITS_PER_RNAT_REG;
    temp = index + (SHORT)FrameSize - NAT_BITS_PER_RNAT_REG;
    while (temp >= 0) {
        FrameSize++;
        temp -= NAT_BITS_PER_RNAT_REG;
    }

    TargetAddress = RsBSP;
    while (regnum > 0) {
        regnum -= 1;
        TargetAddress += 8;
        if ((TargetAddress & 0x1F8) == 0x1F8) {
            TargetAddress += 8;
        }
    }


    if (g_Target->ReadVirtual(TargetAddress, (PUCHAR)&val->i64, 8,
                              &result) != S_OK ||
        (result < 8))
    {
        ErrOut("unable to read memory location %I64x\n", TargetAddress);
        return FALSE;
    }

    index = (SHORT)((TargetAddress - (TargetAddress & ~(0x1F8i64))) >> 3);
    TargetNatAddress = TargetAddress | 0x1F8;
    if (TargetNatAddress <= (RsBSP + (FrameSize * sizeof(ULONG64)))) {

        //
        // update backing store
        //

        if (g_Target->ReadVirtual(TargetNatAddress, (PUCHAR)&RsRNAT, 8,
                                  &result) != S_OK || (result < 8))
        {
            ErrOut("unable to read memory location %I64x\n", TargetNatAddress);
            return FALSE;
        }

    }

    val->Nat = (UCHAR)(RsRNAT >> index) & 0x1;
    return TRUE;
}

BOOL
Ia64MachineInfo::SetStackedRegVal(
    IN ULONG64 RsBSP, 
    IN USHORT FrameSize, 
    IN ULONG64 *RsRNAT, 
    IN ULONG regnum, 
    IN REGVAL *val
    )
{
    SHORT index;
    SHORT temp;
    ULONG result;
    ULONG64 Mask;
    ULONG64 LocalRnat;
    ULONG64 TargetAddress;
    ULONG64 TargetNatAddress;

    index = (SHORT)(RsBSP >> 3) & NAT_BITS_PER_RNAT_REG;
    temp = index + (SHORT)FrameSize - NAT_BITS_PER_RNAT_REG;
    while (temp >= 0) {
        FrameSize++;
        temp -= NAT_BITS_PER_RNAT_REG;
    }

    TargetAddress = RsBSP;
    while (regnum > 0) {
        regnum -= 1;
        TargetAddress += 8;
        if ((TargetAddress & 0x1F8) == 0x1F8) {
            TargetAddress += 8;
        }
    }

    if (g_Target->WriteVirtual(TargetAddress, &val->i64, 8, &result) != S_OK ||
        (result < 8))
    {
        ErrOut("unable to write memory location %I64x\n", TargetAddress);
        return FALSE;
    }

    index = (SHORT)((TargetAddress - (TargetAddress & ~(0x1F8i64))) >> 3);
    TargetNatAddress = TargetAddress | 0x1F8;
    Mask = 0x1i64 << index;

    if (TargetNatAddress <= (RsBSP + (FrameSize * sizeof(ULONG64)))) {

        if (g_Target->ReadVirtual(TargetNatAddress, (PUCHAR)&LocalRnat, 8,
                                  &result) != S_OK || (result < 8))
        {
            ErrOut("unable to read memory location %I64x\n", TargetNatAddress);
            return FALSE;
        }

        if (val->Nat) {
            LocalRnat |= Mask;
        } else  {
            LocalRnat &= ~Mask;
        }
        if (g_Target->WriteVirtual(TargetNatAddress, &LocalRnat, 8,
                                   &result) != S_OK ||
            (result < 8))
        {
            ErrOut("unable to write memory location %I64x\n",TargetNatAddress);
            return FALSE;
        }

    } else {

        if (val->Nat) {
            *RsRNAT |= Mask;
        } else  {
            *RsRNAT &= ~Mask;
        }

    }

    return TRUE;
}
    
//----------------------------------------------------------------------------
//
// X86OnIa64MachineInfo.
//
//----------------------------------------------------------------------------

X86OnIa64MachineInfo g_X86OnIa64Machine;

HRESULT
X86OnIa64MachineInfo::InitializeForProcessor(void)
{
    HRESULT Status = X86MachineInfo::InitializeForProcessor();
    m_MaxDataBreakpoints = min(m_MaxDataBreakpoints, 
                               IA64_REG_MAX_DATA_BREAKPOINTS);
    return Status;
}

HRESULT
X86OnIa64MachineInfo::UdGetContextState(ULONG State)
{
    HRESULT Status;
    
    if ((Status = g_Ia64Machine.UdGetContextState(MCTX_FULL)) != S_OK)
    {
        return Status;
    }

    Ia64ContextToX86(&g_Ia64Machine.m_Context.IA64Context,
                     &m_Context.X86Nt5Context);
    m_ContextState = MCTX_FULL;

    return S_OK;
}

HRESULT
X86OnIa64MachineInfo::UdSetContext(void)
{
    g_Ia64Machine.InitializeContextFlags(&g_Ia64Machine.m_Context,
                                         g_SystemVersion);
    X86ContextToIa64(&m_Context.X86Nt5Context,
                     &g_Ia64Machine.m_Context.IA64Context);
    return g_Ia64Machine.UdSetContext();
}


HRESULT
X86OnIa64MachineInfo::KdGetContextState(ULONG State)
{
    HRESULT Status;
    
    dprintf("The context is partially valid. Only x86 user-mode context is available!\n");
    if ((Status = g_Ia64Machine.KdGetContextState(MCTX_FULL)) != S_OK)
    {
        return Status;
    }

    Ia64ContextToX86(&g_Ia64Machine.m_Context.IA64Context,
                     &m_Context.X86Nt5Context);
    m_ContextState = MCTX_FULL;

    return S_OK;
}

HRESULT
X86OnIa64MachineInfo::KdSetContext(void)
{
    dprintf("The context is partially valid. Only x86 user-mode context is available!\n");
    g_Ia64Machine.InitializeContextFlags(&g_Ia64Machine.m_Context,
                                         g_SystemVersion);
    X86ContextToIa64(&m_Context.X86Nt5Context,
                     &g_Ia64Machine.m_Context.IA64Context);
    return g_Ia64Machine.KdSetContext();
}

HRESULT
X86OnIa64MachineInfo::GetSegRegDescriptor(ULONG SegReg, PDESCRIPTOR64 Desc)
{
    // XXX drewb - This should probably use the
    // descriptor information embedded in the IA64 context.
    
    ULONG RegNum = GetSegRegNum(SegReg);
    if (RegNum == 0)
    {
        return E_INVALIDARG;
    }

    return EmulateNtSelDescriptor(this, GetIntReg(RegNum), Desc);
}

HRESULT
X86OnIa64MachineInfo::NewBreakpoint(DebugClient* Client, 
                                    ULONG Type,
                                    ULONG Id,
                                    Breakpoint** RetBp)
{
    HRESULT Status;

    switch(Type & (DEBUG_BREAKPOINT_CODE | DEBUG_BREAKPOINT_DATA))
    {
    case DEBUG_BREAKPOINT_CODE:
        *RetBp = new CodeBreakpoint(Client, Id, IMAGE_FILE_MACHINE_I386);
        Status = (*RetBp) ? S_OK : E_OUTOFMEMORY;

        break;
    case DEBUG_BREAKPOINT_DATA:
        *RetBp = new X86OnIa64DataBreakpoint(Client, Id);
        Status = (*RetBp) ? S_OK : E_OUTOFMEMORY;
        break;
    default:
        // Unknown breakpoint type.
        Status = E_NOINTERFACE;
    }

    return Status;
}

void X86OnIa64MachineInfo::InsertAllDataBreakpoints(void)
{
    DBG_ASSERT(!&X86OnIa64MachineInfo::InsertAllDataBreakpoints);
}

void X86OnIa64MachineInfo::RemoveAllDataBreakpoints(void)
{
    DBG_ASSERT(!&X86OnIa64MachineInfo::RemoveAllDataBreakpoints);
}

ULONG
X86OnIa64MachineInfo::IsBreakpointOrStepException(PEXCEPTION_RECORD64 Record,
                                                  ULONG FirstChance,
                                                  PADDR BpAddr,
                                                  PADDR RelAddr)
{
    //
    // XXX olegk - This is pure hack to eliminate need to map unavalable 
    // in 64-bit context ISR register to DR6.
    // We using the fact that Code Breakpoint is recognized normally and 
    // for Data Breakpoint ISR register is avalable as 5th parameter of 
    // exception record.
    //
    ULONG Exbs = 
        X86MachineInfo::IsBreakpointOrStepException(Record, 
                                                    FirstChance,
                                                    BpAddr, RelAddr);

    if (Exbs == EXBS_BREAKPOINT_CODE) 
    {
        return Exbs;
    }

    if (Record->ExceptionCode == STATUS_WX86_SINGLE_STEP)
    {
        ULONG64 Isr = Record->ExceptionInformation[4]; // Trap code is 2 lower bytes
        ULONG TrapCode = ULONG(Isr & ISR_CODE_MASK);
        ULONG Vector = (ULONG)(Isr >> ISR_IA_VECTOR) & 0xff;

        if (Vector != 1) 
        {
            return EXBS_NONE;
        }

        if (Isr & (1 << ISR_TB_TRAP))
        {
            ADDRFLAT(RelAddr, Record->ExceptionInformation[3]);
            return EXBS_STEP_BRANCH;
        }
        else if (Isr & (1 << ISR_SS_TRAP))
        {
            return EXBS_STEP_INSTRUCTION;
        }
        else {
            if (Isr & ((ULONG64)1 << ISR_X))  // Exec Data Breakpoint
            {
                return EXBS_BREAKPOINT_DATA;
            }
            else // Data Breakpoint
            {
                for (int i = 0; i < 4; ++i)
                {
                    if (TrapCode & (1 << (4 + i))) 
                    {
                        ULONG Addr = GetReg32(X86_DR0 + i);
                        if (Addr) 
                        {
                            ADDRFLAT(BpAddr, Addr);
                            return EXBS_BREAKPOINT_DATA;
                        }
                    }
                }
            }
        }
    }

    return EXBS_NONE;
}

#define NUMBER_OF_387REGS (X86_ST_LAST - X86_ST_FIRST + 1)
#define NUMBER_OF_XMMI_REGS (X86_XMM_LAST - X86_XMM_FIRST + 1)

VOID
Wow64CopyFpFromIa64Byte16(
    IN PVOID Byte16Fp,
    IN OUT PVOID Byte10Fp,
    IN ULONG NumRegs);

VOID
Wow64CopyFpToIa64Byte16(
    IN PVOID Byte10Fp,
    IN OUT PVOID Byte16Fp,
    IN ULONG NumRegs);

VOID
Wow64CopyXMMIToIa64Byte16(
    IN PVOID ByteXMMI,
    IN OUT PVOID Byte16Fp,
    IN ULONG NumRegs);

VOID
Wow64CopyXMMIFromIa64Byte16(
    IN PVOID Byte16Fp,
    IN OUT PVOID ByteXMMI,
    IN ULONG NumRegs);

VOID
Wow64RotateFpTop(
    IN ULONGLONG Ia64_FSR,
    IN OUT FLOAT128 UNALIGNED *ia32FxSave);

VOID
Wow64CopyIa64FromSpill(
    IN PFLOAT128 SpillArea,
    IN OUT FLOAT128 UNALIGNED *ia64Fp,
    IN ULONG NumRegs);

VOID
Wow64CopyIa64ToFill(
    IN FLOAT128 UNALIGNED *ia64Fp,
    IN OUT PFLOAT128 FillArea,
    IN ULONG NumRegs);

BOOL
MapDbgSlotIa64ToX86(
    UINT    Slot,
    ULONG64 Ipsr,
    ULONG64 DbD,
    ULONG64 DbD1,
    ULONG64 DbI,
    ULONG64 DbI1,
    ULONG*  Dr7,
    ULONG*  Dr);

void
MapDbgSlotX86ToIa64(
    UINT     Slot,
    ULONG    Dr7,
    ULONG    Dr,
    ULONG64* Ipsr,
    ULONG64* DbD,
    ULONG64* DbD1,
    ULONG64* DbI,
    ULONG64* DbI1);

void
X86OnIa64MachineInfo::Ia64ContextToX86(
    PIA64_CONTEXT ContextIa64,
    PX86_NT5_CONTEXT ContextX86)
{
    FLOAT128 tmpFloat[NUMBER_OF_387REGS];
    ULONG Ia32ContextFlags = ContextX86->ContextFlags;

    ULONG Tid = GetCurrentThreadId();
    DebugClient* Client;
 
    for (Client = g_Clients; Client != NULL; Client = Client->m_Next)
    {
        if (Client->m_ThreadId == Tid)
        {
            break;
        }
    }

    DBG_ASSERT((Client!=NULL));

    if (!g_Ia64Machine.IsIA32InstructionSet())
    {
        if (g_Wow64exts == NULL)
        {
            dprintf("Need to load wow64exts.dll to retrieve context!\n");
            return;
        }
        (*g_Wow64exts)(WOW64EXTS_GET_CONTEXT, 
                       (ULONG64)Client,
                       (ULONG64)ContextX86,
                       (ULONG64)NULL);
        return;
    }

    if ((Ia32ContextFlags & VDMCONTEXT_CONTROL) == VDMCONTEXT_CONTROL)
    {
        //
        // And the control stuff
        //
        ContextX86->Ebp    = (ULONG)ContextIa64->IntTeb;
        ContextX86->SegCs  = X86_KGDT_R3_CODE|3;
        ContextX86->Eip    = (ULONG)ContextIa64->StIIP;
        ContextX86->SegSs  = X86_KGDT_R3_DATA|3;
        ContextX86->Esp    = (ULONG)ContextIa64->IntSp;
        ContextX86->EFlags = (ULONG)ContextIa64->Eflag;

        //
        // Map single step flag (EFlags.tf = EFlags.tf || PSR.ss)
        //
        if (ContextIa64->StIPSR & (1I64 << PSR_SS))
        {
            ContextX86->EFlags |= X86_BIT_FLAGTF;
        }
    }

    if ((Ia32ContextFlags & VDMCONTEXT_INTEGER)  == VDMCONTEXT_INTEGER)
    {
        //
        // Now for the integer state...
        //
        ContextX86->Edi = (ULONG)ContextIa64->IntT6;
        ContextX86->Esi = (ULONG)ContextIa64->IntT5;
        ContextX86->Ebx = (ULONG)ContextIa64->IntT4;
        ContextX86->Edx = (ULONG)ContextIa64->IntT3;
        ContextX86->Ecx = (ULONG)ContextIa64->IntT2;
        ContextX86->Eax = (ULONG)ContextIa64->IntV0;
    }

    if ((Ia32ContextFlags & VDMCONTEXT_SEGMENTS) == VDMCONTEXT_SEGMENTS)
    {
        //
        // These are constants (and constants are used on ia32->ia64
        // transition, not saved values) so make our life easy...
        //
        ContextX86->SegGs = X86_KGDT_R3_DATA|3;
        ContextX86->SegEs = X86_KGDT_R3_DATA|3;
        ContextX86->SegDs = X86_KGDT_R3_DATA|3;
        ContextX86->SegSs = X86_KGDT_R3_DATA|3;
        ContextX86->SegFs = X86_KGDT_R3_TEB|3;
        ContextX86->SegCs = X86_KGDT_R3_CODE|3;
    }

    if ((Ia32ContextFlags & VDMCONTEXT_EXTENDED_REGISTERS) ==
        VDMCONTEXT_EXTENDED_REGISTERS)
    {
        PX86_FXSAVE_FORMAT xmmi =
            (PX86_FXSAVE_FORMAT) ContextX86->ExtendedRegisters;
        
        xmmi->ControlWord   = (USHORT)(ContextIa64->StFCR & 0xffff);
        xmmi->StatusWord    = (USHORT)(ContextIa64->StFSR & 0xffff);
        xmmi->TagWord       = (USHORT)(ContextIa64->StFSR >> 16) & 0xffff;
        xmmi->ErrorOpcode   = (USHORT)(ContextIa64->StFIR >> 48);
        xmmi->ErrorOffset   = (ULONG) (ContextIa64->StFIR & 0xffffffff);
        xmmi->ErrorSelector = (ULONG) (ContextIa64->StFIR >> 32);
        xmmi->DataOffset    = (ULONG) (ContextIa64->StFDR & 0xffffffff);
        xmmi->DataSelector  = (ULONG) (ContextIa64->StFDR >> 32);
        xmmi->MXCsr         = (ULONG) (ContextIa64->StFCR >> 32) & 0xffff;

        //
        // Copy over the FP registers.  Even though this is the new
        // FXSAVE format with 16-bytes for each register, need to
        // convert from spill/fill format to 80-bit double extended format
        //
        Wow64CopyIa64FromSpill((PFLOAT128) &(ContextIa64->FltT2),
                               (PFLOAT128) xmmi->RegisterArea,
                               NUMBER_OF_387REGS);

        //
        // Rotate the registers appropriately
        //
        Wow64RotateFpTop(ContextIa64->StFSR, (PFLOAT128) xmmi->RegisterArea);

        //
        // Finally copy the xmmi registers
        //
        Wow64CopyXMMIFromIa64Byte16(&(ContextIa64->FltS4),
                                    xmmi->Reserved3,
                                    NUMBER_OF_XMMI_REGS);
    }

    if ((Ia32ContextFlags & VDMCONTEXT_FLOATING_POINT) ==
        VDMCONTEXT_FLOATING_POINT)
    {
        //
        // Copy over the floating point status/control stuff
        //
        ContextX86->FloatSave.ControlWord   = (ULONG)(ContextIa64->StFCR & 0xffff);
        ContextX86->FloatSave.StatusWord    = (ULONG)(ContextIa64->StFSR & 0xffff);
        ContextX86->FloatSave.TagWord       = (ULONG)(ContextIa64->StFSR >> 16) & 0xffff;
        ContextX86->FloatSave.ErrorOffset   = (ULONG)(ContextIa64->StFIR & 0xffffffff);
        ContextX86->FloatSave.ErrorSelector = (ULONG)(ContextIa64->StFIR >> 32);
        ContextX86->FloatSave.DataOffset    = (ULONG)(ContextIa64->StFDR & 0xffffffff);
        ContextX86->FloatSave.DataSelector  = (ULONG)(ContextIa64->StFDR >> 32);

        //
        // Copy over the FP registers into temporary space
        // Even though this is the new
        // FXSAVE format with 16-bytes for each register, need to
        // convert from spill/fill format to 80-bit double extended format
        //
        Wow64CopyIa64FromSpill((PFLOAT128) &(ContextIa64->FltT2),
                               (PFLOAT128) tmpFloat,
                               NUMBER_OF_387REGS);
        //
        // Rotate the registers appropriately
        //
        Wow64RotateFpTop(ContextIa64->StFSR, tmpFloat);

        //
        // And put them in the older FNSAVE format (packed 10 byte values)
        //
        Wow64CopyFpFromIa64Byte16(tmpFloat,
                                  ContextX86->FloatSave.RegisterArea,
                                  NUMBER_OF_387REGS);
    }

    if ((Ia32ContextFlags & VDMCONTEXT_DEBUG_REGISTERS) ==
        VDMCONTEXT_DEBUG_REGISTERS)
    {
        // Ia64 -> X86
        BOOL Valid = TRUE;
        Valid &= MapDbgSlotIa64ToX86(0, ContextIa64->StIPSR, ContextIa64->DbD0, ContextIa64->DbD1, ContextIa64->DbI0, ContextIa64->DbI1, &ContextX86->Dr7, &ContextX86->Dr0);
        Valid &= MapDbgSlotIa64ToX86(1, ContextIa64->StIPSR, ContextIa64->DbD2, ContextIa64->DbD3, ContextIa64->DbI2, ContextIa64->DbI3, &ContextX86->Dr7, &ContextX86->Dr1);
        Valid &= MapDbgSlotIa64ToX86(2, ContextIa64->StIPSR, ContextIa64->DbD4, ContextIa64->DbD5, ContextIa64->DbI4, ContextIa64->DbI5, &ContextX86->Dr7, &ContextX86->Dr2);
        Valid &= MapDbgSlotIa64ToX86(3, ContextIa64->StIPSR, ContextIa64->DbD6, ContextIa64->DbD7, ContextIa64->DbI6, ContextIa64->DbI7, &ContextX86->Dr7, &ContextX86->Dr3);

        if (!Valid)
        {
            WarnOut("Wasn't able to map IA64 debug registers consistently!!!\n");
        }

        //
        // Map single step flag (EFlags.tf = EFlags.tf || PSR.ss)
        //
        if (ContextIa64->StIPSR & (1I64 << PSR_SS))
        {
            ContextX86->EFlags |= X86_BIT_FLAGTF;
        }
    }
}

void
X86OnIa64MachineInfo::X86ContextToIa64(
    PX86_NT5_CONTEXT ContextX86,
    PIA64_CONTEXT ContextIa64)
{
   
    FLOAT128 tmpFloat[NUMBER_OF_387REGS];
    ULONG Ia32ContextFlags = ContextX86->ContextFlags;

    ULONG Tid = GetCurrentThreadId();
    DebugClient* Client;
 
    for (Client = g_Clients; Client != NULL; Client = Client->m_Next)
    {
        if (Client->m_ThreadId == Tid)
        {
            break;
        }
    }

    DBG_ASSERT((Client!=NULL));

    if (!g_Ia64Machine.IsIA32InstructionSet())
    {
        if (g_Wow64exts == NULL)
        {
            dprintf("Need to load wow64exts.dll to retrieve context!\n");
            return;
        }
        (*g_Wow64exts)(WOW64EXTS_SET_CONTEXT, 
                       (ULONG64)Client,
                       (ULONG64)ContextX86,
                       (ULONG64)NULL);
        return;
    }

    if ((Ia32ContextFlags & VDMCONTEXT_CONTROL) == VDMCONTEXT_CONTROL)
    {
        //
        // And the control stuff
        //
        ContextIa64->IntTeb = ContextX86->Ebp;
        ContextIa64->StIIP = ContextX86->Eip;
        ContextIa64->IntSp = ContextX86->Esp;
        ContextIa64->Eflag = ContextX86->EFlags;

        //
        // Map single step flag (PSR.ss = PSR.ss || EFlags.tf)
        //
        if (ContextX86->EFlags & X86_BIT_FLAGTF) 
        {
            ContextIa64->StIPSR |= (1I64 << PSR_SS);
        }

        //
        // The segments (cs and ds) are a constant, so reset them.
        // gr17 has LDT and TSS, so might as well reset
        // all of them while we're at it...
        // These values are forced in during a transition (see simulate.s)
        // so there is no point to trying to get cute and actually
        // pass in the values from the X86 context record
        //
        ContextIa64->IntT8 = ((X86_KGDT_LDT|3) << 32) 
                           | ((X86_KGDT_R3_DATA|3) << 16)
                           | (X86_KGDT_R3_CODE|3);

    }

    if ((Ia32ContextFlags & VDMCONTEXT_INTEGER) == VDMCONTEXT_INTEGER)
    {
        //
        // Now for the integer state...
        //
         ContextIa64->IntT6 = ContextX86->Edi;
         ContextIa64->IntT5 = ContextX86->Esi;
         ContextIa64->IntT4 = ContextX86->Ebx;
         ContextIa64->IntT3 = ContextX86->Edx;
         ContextIa64->IntT2 = ContextX86->Ecx;
         ContextIa64->IntV0 = ContextX86->Eax;
    }

    if ((Ia32ContextFlags & VDMCONTEXT_SEGMENTS) == VDMCONTEXT_SEGMENTS)
    {
        //
        // These are constants (and constants are used on ia32->ia64
        // transition, not saved values) so make our life easy...
        // These values are forced in during a transition (see simulate.s)
        // so there is no point to trying to get cute and actually
        // pass in the values from the X86 context record
        //
        ContextIa64->IntT7 =  ((X86_KGDT_R3_DATA|3) << 48)
                           | ((X86_KGDT_R3_TEB|3) << 32)
                           | ((X86_KGDT_R3_DATA|3) << 16)
                           | (X86_KGDT_R3_DATA|3);
    }

    if ((Ia32ContextFlags & VDMCONTEXT_EXTENDED_REGISTERS) ==
        VDMCONTEXT_EXTENDED_REGISTERS)
    {
        PX86_FXSAVE_FORMAT xmmi =
            (PX86_FXSAVE_FORMAT) ContextX86->ExtendedRegisters;
 
        //
        // And copy over the floating point status/control stuff
        //
        ContextIa64->StFCR = (ContextIa64->StFCR & 0xffffffffffffe040i64) |
                             (xmmi->ControlWord & 0xffff) |
                             ((xmmi->MXCsr & 0xffff) << 32);

        ContextIa64->StFSR = (ContextIa64->StFSR & 0xffffffff00000000i64) | 
                             (xmmi->StatusWord & 0xffff) | 
                             ((xmmi->TagWord & 0xffff) << 16);

        ContextIa64->StFIR = (xmmi->ErrorOffset & 0xffffffff) | 
                             (xmmi->ErrorSelector << 32);

        ContextIa64->StFDR = (xmmi->DataOffset & 0xffffffff) | 
                             (xmmi->DataSelector << 32);

        //
        // Don't touch the original ia32 context. Make a copy.
        //
        memcpy(tmpFloat, xmmi->RegisterArea, 
               NUMBER_OF_387REGS * sizeof(FLOAT128));
        
        // 
        // Rotate registers back since st0 is not necessarily f8
        //
        {
            ULONGLONG RotateFSR = (NUMBER_OF_387REGS - 
                                   ((ContextIa64->StFSR >> 11) & 0x7)) << 11;
            Wow64RotateFpTop(RotateFSR, tmpFloat);
        }

        //
        // Copy over the FP registers.  Even though this is the new
        // FXSAVE format with 16-bytes for each register, need to
        // convert to spill/fill format from 80-bit double extended format
        //
        Wow64CopyIa64ToFill((PFLOAT128) tmpFloat,
                            (PFLOAT128) &(ContextIa64->FltT2),
                            NUMBER_OF_387REGS);

        //
        // Copy over the xmmi registers and convert them into a format
        // that spill/fill can use
        //
        Wow64CopyXMMIToIa64Byte16(xmmi->Reserved3, 
                                  &(ContextIa64->FltS4), 
                                  NUMBER_OF_XMMI_REGS);
    }

    if ((Ia32ContextFlags & VDMCONTEXT_FLOATING_POINT) ==
        VDMCONTEXT_FLOATING_POINT)
    {
        //
        // Copy over the floating point status/control stuff
        // Leave the MXCSR stuff alone
        //
        ContextIa64->StFCR = (ContextIa64->StFCR & 0xffffffffffffe040i64) | 
                             (ContextX86->FloatSave.ControlWord & 0xffff);

        ContextIa64->StFSR = (ContextIa64->StFSR & 0xffffffff00000000i64) | 
                             (ContextX86->FloatSave.StatusWord & 0xffff) | 
                             ((ContextX86->FloatSave.TagWord & 0xffff) << 16);

        ContextIa64->StFIR = (ContextX86->FloatSave.ErrorOffset & 0xffffffff) | 
                             (ContextX86->FloatSave.ErrorSelector << 32);

        ContextIa64->StFDR = (ContextX86->FloatSave.DataOffset & 0xffffffff) | 
                             (ContextX86->FloatSave.DataSelector << 32);


        //
        // Copy over the FP registers from packed 10-byte format
        // to 16-byte format
        //
        Wow64CopyFpToIa64Byte16(ContextX86->FloatSave.RegisterArea,
                                tmpFloat,
                                NUMBER_OF_387REGS);

        // 
        // Rotate registers back since st0 is not necessarily f8
        //
        {
            ULONGLONG RotateFSR = (NUMBER_OF_387REGS - 
                                   ((ContextIa64->StFSR >> 11) & 0x7)) << 11;
            Wow64RotateFpTop(RotateFSR, tmpFloat);
        }

        //
        // Now convert from 80 bit extended format to fill/spill format
        //
        Wow64CopyIa64ToFill((PFLOAT128) tmpFloat,
                            (PFLOAT128) &(ContextIa64->FltT2),
                            NUMBER_OF_387REGS);
    }

    if ((Ia32ContextFlags & VDMCONTEXT_DEBUG_REGISTERS) ==
        VDMCONTEXT_DEBUG_REGISTERS)
    {
        // X86 -> Ia64
        MapDbgSlotX86ToIa64(0, ContextX86->Dr7, ContextX86->Dr0, &ContextIa64->StIPSR, &ContextIa64->DbD0, &ContextIa64->DbD1, &ContextIa64->DbI0, &ContextIa64->DbI1);
        MapDbgSlotX86ToIa64(1, ContextX86->Dr7, ContextX86->Dr1, &ContextIa64->StIPSR, &ContextIa64->DbD2, &ContextIa64->DbD3, &ContextIa64->DbI2, &ContextIa64->DbI3);
        MapDbgSlotX86ToIa64(2, ContextX86->Dr7, ContextX86->Dr2, &ContextIa64->StIPSR, &ContextIa64->DbD4, &ContextIa64->DbD5, &ContextIa64->DbI4, &ContextIa64->DbI5);
        MapDbgSlotX86ToIa64(3, ContextX86->Dr7, ContextX86->Dr3, &ContextIa64->StIPSR, &ContextIa64->DbD6, &ContextIa64->DbD7, &ContextIa64->DbI6, &ContextIa64->DbI7);

        //
        // Map single step flag (PSR.ss = PSR.ss || EFlags.tf)
        //
        if (ContextX86->EFlags & X86_BIT_FLAGTF) 
        {
            ContextIa64->StIPSR |= (1I64 << PSR_SS);
        }
    }
        
}

//
// Helper functions for context conversion
// --copied from \nt\base\wow64\cpu\context\context.c
//

//
// This allows the compiler to be more efficient in copying 10 bytes
// without over copying...
//
#pragma pack(push, 2)
typedef struct _ia32fpbytes {
    ULONG significand_low;
    ULONG significand_high;
    USHORT exponent;
} IA32FPBYTES, *PIA32FPBYTES;
#pragma pack(pop)

VOID
Wow64CopyFpFromIa64Byte16(
    IN PVOID Byte16Fp,
    IN OUT PVOID Byte10Fp,
    IN ULONG NumRegs)
{
    ULONG i;
    PIA32FPBYTES from, to;

    from = (PIA32FPBYTES) Byte16Fp;
    to = (PIA32FPBYTES) Byte10Fp;

    for (i = 0; i < NumRegs; i++) {
        *to = *from;
        from = (PIA32FPBYTES) (((UINT_PTR) from) + 16);
        to = (PIA32FPBYTES) (((UINT_PTR) to) + 10);
    }
}

VOID
Wow64CopyFpToIa64Byte16(
    IN PVOID Byte10Fp,
    IN OUT PVOID Byte16Fp,
    IN ULONG NumRegs)
{
    ULONG i;
    PIA32FPBYTES from, to;  // UNALIGNED

    from = (PIA32FPBYTES) Byte10Fp;
    to = (PIA32FPBYTES) Byte16Fp;

    for (i = 0; i < NumRegs; i++) {
        *to = *from;
        from = (PIA32FPBYTES) (((UINT_PTR) from) + 10);
        to = (PIA32FPBYTES) (((UINT_PTR) to) + 16);
    }
}

//
// Alas, nothing is easy. The ia32 xmmi instructions use 16 bytes and pack
// them as nice 16 byte structs. Unfortunately, ia64 handles it as 2 8-byte
// values (using just the mantissa part). So, another conversion is required
//
VOID
Wow64CopyXMMIToIa64Byte16(
    IN PVOID ByteXMMI,
    IN OUT PVOID Byte16Fp,
    IN ULONG NumRegs)
{
    ULONG i;
    UNALIGNED ULONGLONG *from;
    ULONGLONG *to;

    from = (PULONGLONG) ByteXMMI;
    to = (PULONGLONG) Byte16Fp;

    //
    // although we have NumRegs xmmi registers, each register is 16 bytes
    // wide. This code does things in 8-byte chunks, so total
    // number of times to do things is 2 * NumRegs...
    //
    NumRegs *= 2;

    for (i = 0; i < NumRegs; i++) {
        *to++ = *from++;        // Copy over the mantissa part
        *to++ = 0x1003e;        // Force the exponent part
                                // (see ia64 eas, ia32 FP section - 6.2.7
                                // for where this magic number comes from)
    }
}

VOID
Wow64CopyXMMIFromIa64Byte16(
    IN PVOID Byte16Fp,
    IN OUT PVOID ByteXMMI,
    IN ULONG NumRegs)
{
    ULONG i;
    ULONGLONG *from;
    UNALIGNED ULONGLONG *to;

    from = (PULONGLONG) Byte16Fp;
    to = (PULONGLONG) ByteXMMI;

    //
    // although we have NumRegs xmmi registers, each register is 16 bytes
    // wide. This code does things in 8-byte chunks, so total
    // number of times to do things is 2 * NumRegs...
    //
    NumRegs *= 2;

    for (i = 0; i < NumRegs; i++) {
        *to++ = *from++;        // Copy over the mantissa part
        from++;                 // Skip over the exponent part
    }
}

VOID
Wow64RotateFpTop(
    IN ULONGLONG Ia64_FSR,
    IN OUT FLOAT128 UNALIGNED *ia32FxSave)
/*++

Routine Description:

    On transition from ia64 mode to ia32 (and back), the f8-f15 registers
    contain the st[0] to st[7] fp stack values. Alas, these values don't
    map one-one, so the FSR.top bits are used to determine which ia64
    register has the top of stack. We then need to rotate these registers
    since ia32 context is expecting st[0] to be the first fp register (as
    if FSR.top is zero). This routine only works on full 16-byte ia32
    saved fp data (such as from ExtendedRegisters - the FXSAVE format).
    Other routines can convert this into the older FNSAVE format.

Arguments:

    Ia64_FSR - The ia64 FSR register. Has the FSR.top needed for this routine

    ia32FxSave - The ia32 fp stack (in FXSAVE format). Each ia32 fp register
                 uses 16 bytes.

Return Value:

    None.  

--*/
{
    ULONG top = (ULONG) ((Ia64_FSR >> 11) & 0x7);

    if (top) {
        FLOAT128 tmpFloat[NUMBER_OF_387REGS];
        ULONG i;
        for (i = 0; i < NUMBER_OF_387REGS; i++) {
            tmpFloat[i] = ia32FxSave[i];
        }

        for (i = 0; i < NUMBER_OF_387REGS; i++) {
            ia32FxSave[i] = tmpFloat[(i + top) % NUMBER_OF_387REGS];
        }
    }
}

//
// And now for the final yuck... The ia64 context for floating point
// is saved/loaded using spill/fill instructions. This format is different
// than the 10-byte fp format so we need a conversion routine from spill/fill
// to/from 10byte fp
//

VOID
Wow64CopyIa64FromSpill(
    IN PFLOAT128 SpillArea,
    IN OUT FLOAT128 UNALIGNED *ia64Fp,
    IN ULONG NumRegs)
/*++

Routine Description:

    This function copies fp values from the ia64 spill/fill format
    into the ia64 80-bit format. The exponent needs to be adjusted
    according to the EAS (5-12) regarding Memory to Floating Point
    Register Data Translation in the ia64 floating point chapter

Arguments:

    SpillArea - The ia64 area that has the spill format for fp

    ia64Fp - The location which will get the ia64 fp in 80-bit
             double-extended format

    NumRegs - Number of registers to convert

Return Value:

    None.

--*/
{
    ULONG i;

    for (i = 0; i < NumRegs; i++) {
        ULONG64 Sign = ((SpillArea->HighPart & (1i64 << 17)) != 0);
        ULONG64 Significand = SpillArea->LowPart; 
        ULONG64 Exponent = SpillArea->HighPart & 0x1ffff; 

        if (Exponent && Significand) 
        {
            if (Exponent == 0x1ffff) // NaNs and Infinities
            {   
                Exponent = 0x7fff;
            }
            else 
            {
                ULONG64 Rebias = 0xffff - 0x3fff;
                Exponent -= Rebias;
            }
        }

        ia64Fp->HighPart = (Sign << 15) | Exponent;
        ia64Fp->LowPart = Significand;

        ia64Fp++;
        SpillArea++;
    }
}

VOID
Wow64CopyIa64ToFill(
    IN FLOAT128 UNALIGNED *ia64Fp,
    IN OUT PFLOAT128 FillArea,
    IN ULONG NumRegs)
/*++

Routine Description:

    This function copies fp values from the ia64 80-bit format
    into the fill/spill format used by the os for save/restore
    of the ia64 context. The only magic here is putting back some
    values that get truncated when converting from spill/fill to 
    80-bits. The exponent needs to be adjusted according to the
    EAS (5-12) regarding Memory to Floating Point Register Data
    Translation in the ia64 floating point chapter

Arguments:

    ia64Fp - The ia64 fp in 80-bit double-extended format

    FillArea - The ia64 area that will get the fill format for fp
                  for the copy into the ia64 context area

    NumRegs - Number of registers to convert

Return Value:

    None.

--*/
{
    ULONG i;

    for (i = 0; i < NumRegs; i++) {
        ULONG64 Sign = ((ia64Fp->HighPart & (1i64 << 15)) != 0);
        ULONG64 Significand = ia64Fp->LowPart; 
        ULONG64 Exponent = ia64Fp->HighPart & 0x7fff;

        if (Exponent && Significand) 
        {
            if (Exponent == 0x7fff) // Infinity
            {
                Exponent = 0x1ffff;
            }
            else 
            {
                ULONGLONG Rebias = 0xffff-0x3fff;
                Exponent += Rebias;
            }
        }

        FillArea->LowPart = Significand;
        FillArea->HighPart = (Sign << 17) | Exponent;

        ia64Fp++;
        FillArea++;
    }
}

ULONG 
MapDbgSlotIa64ToX86_GetSize(ULONG64 Db1, BOOL* Valid)
{
    ULONG64 Size = (~Db1 & IA64_DBG_MASK_MASK);
    if (Size > 3)
    {
        *Valid = FALSE;
    }
    return (ULONG)Size;
}

void 
MapDbgSlotIa64ToX86_InvalidateAddr(ULONG64 Db, BOOL* Valid)
{
    if (Db != (ULONG64)(ULONG)Db) 
    {
        *Valid = FALSE;
    }
}

ULONG
MapDbgSlotIa64ToX86_ExecTypeSize(
    UINT     Slot,
    ULONG64  Db,
    ULONG64  Db1,
    BOOL* Valid)
{
    ULONG TypeSize;

    if (!(Db1 >> 63)) 
    {
        *Valid = FALSE;
    }

    TypeSize = (MapDbgSlotIa64ToX86_GetSize(Db1, Valid) << 2); 
    MapDbgSlotIa64ToX86_InvalidateAddr(Db, Valid);
   
    return TypeSize;
}

ULONG
MapDbgSlotIa64ToX86_DataTypeSize(
    UINT     Slot,
    ULONG64  Db,
    ULONG64  Db1,
    BOOL* Valid)
{
    ULONG TypeSize = (ULONG)(Db1 >> 62);

    if ((TypeSize != 1) && (TypeSize != 3))
    {
        *Valid = FALSE;
    }

    TypeSize |= (MapDbgSlotIa64ToX86_GetSize(Db1, Valid) << 2); 
    MapDbgSlotIa64ToX86_InvalidateAddr(Db, Valid);
    
    return TypeSize;
}

BOOL
MapDbgSlotIa64ToX86(
    UINT    Slot,
    ULONG64 Ipsr,
    ULONG64 DbD,
    ULONG64 DbD1,
    ULONG64 DbI,
    ULONG64 DbI1,
    ULONG*  Dr7,
    ULONG*  Dr)
{
    BOOL DataValid = TRUE, ExecValid = TRUE, Valid = TRUE;
    ULONG DataTypeSize, ExecTypeSize;

    // XXX olegk - remove this after IA64_REG_MAX_DATA_BREAKPOINTS will be changed to 4
    if (Slot >= IA64_REG_MAX_DATA_BREAKPOINTS) 
    {
        return TRUE;
    }

    DataTypeSize = MapDbgSlotIa64ToX86_DataTypeSize(Slot, DbD, DbD1, &DataValid);
    ExecTypeSize = MapDbgSlotIa64ToX86_ExecTypeSize(Slot, DbI, DbI1, &ExecValid);
    
    if (DataValid)
    {
        if (!ExecValid)
        {
            *Dr = (ULONG)DbD;
            *Dr7 |= (X86_DR7_LOCAL_EXACT_ENABLE |
                     (1 << Slot * 2) |
                     (DataTypeSize << (16 + Slot * 4)));
            return !DbI && !DbI1;
        }
    }
    else if (ExecValid)
    {
        *Dr = (ULONG)DbI;
        *Dr7 |= (X86_DR7_LOCAL_EXACT_ENABLE |
                 (1 << Slot * 2) |
                 (ExecTypeSize << (16 + Slot * 4)));
        return !DbD && !DbD1;
    }
    
    *Dr7 &= ~(X86_DR7_LOCAL_EXACT_ENABLE |  
              (0xf << (16 + Slot * 4)) | 
              (1 << Slot * 2));

    if (!DbD && !DbD1 && !DbI && !DbI1)
    {
        *Dr = 0;
        return TRUE;
    }
     
    *Dr = ~(ULONG)0;

    return FALSE;
}

void
MapDbgSlotX86ToIa64(
    UINT     Slot,
    ULONG    Dr7,
    ULONG    Dr,
    ULONG64* Ipsr,
    ULONG64* DbD,
    ULONG64* DbD1,
    ULONG64* DbI,
    ULONG64* DbI1)
{
    UINT TypeSize;
    ULONG64 Control;

    if (!(Dr7 & (1 << Slot * 2)))
    {
        return;
    }

    if (Dr == ~(ULONG)0) 
    {
        return;
    }

    TypeSize = Dr7 >> (16 + Slot * 4);

    Control = (IA64_DBG_REG_PLM_USER | IA64_DBG_MASK_MASK) & 
              ~(ULONG64)(TypeSize >> 2);

    switch (TypeSize & 0x3) 
    {
    case 0x0: // Exec
        *DbI1 = Control | IA64_DBR_EXEC;        
        *DbI = Dr;
        break;
    case 0x1: // Write
        *DbD1 = Control | IA64_DBR_WR;
        *DbD = Dr;
        break;
    case 0x3: // Read/Write
        *DbD1 = Control | IA64_DBR_RD | IA64_DBR_WR;
        *DbD = Dr;
        break;
    default:
        return;
    }
    *Ipsr |= (1i64 << PSR_DB); 
}