Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 580

Show
Ignore:
Timestamp:
07/18/10 18:15:49 (14 years ago)
Author:
walter
Message:

addressing modes for 64 bit tls

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/dmd-1.x/src/backend/cod1.c

    r579 r580  
    542542 * Can handle indirection operators, but not if they're common subs. 
    543543 * Input: 
    544544 *      e ->    elem where we get some of the data from 
    545545 *      cs ->   partially filled code to add 
    546546 *      op =    opcode 
    547547 *      reg =   reg field of (mod reg r/m) 
    548548 *      offset = data to be added to Voffset field 
    549549 *      keepmsk = mask of registers we must not destroy 
    550550 *      desmsk  = mask of registers destroyed by executing the instruction 
    551551 * Returns: 
    552552 *      pointer to code generated 
    553553 */ 
    554554 
    555555code *loadea(elem *e,code *cs,unsigned op,unsigned reg,targ_size_t offset, 
    556556        regm_t keepmsk,regm_t desmsk) 
    557557{ 
    558558  code *c,*cg,*cd; 
    559559 
    560560#ifdef DEBUG 
    561561  if (debugw) 
    562     printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%ld keepmsk=x%x desmsk=x%x\n", 
    563             e,cs,op,reg,offset,keepmsk,desmsk); 
     562    printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%lld keepmsk=x%x desmsk=x%x\n", 
     563            e,cs,op,reg,(unsigned long long)offset,keepmsk,desmsk); 
    564564#endif 
    565565 
    566566  assert(e); 
    567567  cs->Iflags = 0; 
    568568  cs->Irex = 0; 
    569569  cs->Iop = op; 
    570570  if (!I16 && op >= 0x100)               // if 2 byte opcode 
    571571  {     cs->Iop = op >> 8; 
    572572        cs->Iop2 = op; 
    573573  } 
    574574  tym_t tym = e->Ety; 
    575575  int sz = tysize(tym); 
    576576 
    577577  /* Determine if location we want to get is in a register. If so,      */ 
    578578  /* substitute the register for the EA.                                */ 
    579579  /* Note that operators don't go through this. CSE'd operators are     */ 
    580580  /* picked up by comsub().                                             */ 
    581581  if (e->Ecount &&                      /* if cse                       */ 
    582582      e->Ecount != e->Ecomsub &&        /* and cse was generated        */ 
    583583      op != 0x8D && op != 0xC4 &&       /* and not an LEA or LES        */ 
     
    12681268                { 
    12691269                    pcs->Irm = modregrm(3,0,s->Spreg & 7); 
    12701270                    if (s->Spreg & 8) 
    12711271                        pcs->Irex |= REX_B; 
    12721272                    regcon.used |= mask[s->Spreg]; 
    12731273                    break; 
    12741274                } 
    12751275            } 
    12761276            else 
    12771277                regcon.params &= ~mask[s->Spreg]; 
    12781278        } 
    12791279    case FLtmp: 
    12801280    case FLbprel: 
    12811281        reflocal = TRUE; 
    12821282        pcs->Irm = modregrm(2,0,BPRM); 
    12831283        goto L2; 
    12841284    case FLextern: 
    12851285        if (s->Sident[0] == '_' && memcmp(s->Sident + 1,"tls_array",10) == 0) 
    12861286        { 
    12871287#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    1288             // Rewrite as GS:[0000] 
    1289             pcs->Irm = modregrm(0, 0, BPRM); 
    1290             pcs->IFL1 = FLconst; 
    1291             pcs->IEV1.Vuns = 0; 
    1292             pcs->Iflags = CFgs; 
     1288            // Rewrite as GS:[0000], or FS:[0000] for 64 bit 
     1289            if (I64) 
     1290            { 
     1291                pcs->Irm = modregrm(0, 0, 4); 
     1292                pcs->Isib = modregrm(0, 4, 5);  // don't use [RIP] addressing 
     1293                pcs->IFL1 = FLconst; 
     1294                pcs->IEV1.Vuns = 0; 
     1295                pcs->Iflags = CFfs; 
     1296            } 
     1297            else 
     1298            { 
     1299                pcs->Irm = modregrm(0, 0, BPRM); 
     1300                pcs->IFL1 = FLconst; 
     1301                pcs->IEV1.Vuns = 0; 
     1302                pcs->Iflags = CFgs; 
     1303            } 
     1304            break; 
    12931305#else 
    12941306            pcs->Iflags |= CFfs;                // add FS: override 
    12951307#endif 
    12961308        } 
    12971309        if (s->ty() & mTYcs && LARGECODE) 
    12981310            goto Lfardata; 
    12991311        goto L3; 
    13001312    case FLdata: 
    13011313    case FLudata: 
    13021314    case FLcsdata: 
    13031315#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    13041316    case FLgot: 
    13051317    case FLgotoff: 
    13061318    case FLtlsdata: 
    13071319#endif 
    13081320    L3: 
    13091321        pcs->Irm = modregrm(0,0,BPRM); 
    13101322    L2: 
    13111323        if (fl == FLreg) 
    13121324        {   assert(s->Sregm & regcon.mvar); 
  • branches/dmd-1.x/src/backend/cod3.c

    r579 r580  
    4949static int EBPtoESP;            // add to EBP offset to get ESP offset 
    5050static int AAoff;               // offset of alloca temporary 
    5151 
    5252#if ELFOBJ || MACHOBJ 
    5353#define JMPSEG  CDATA 
    5454#define JMPOFF  CDoffset 
    5555#else 
    5656#define JMPSEG  DATA 
    5757#define JMPOFF  Doffset 
    5858#endif 
    5959 
    6060/************************ 
    6161 * When we don't know whether a function symbol is defined or not 
    6262 * within this module, we stuff it in this linked list of references 
    6363 * to be fixed up later. 
    6464 */ 
    6565 
    6666struct fixlist 
    6767{   symbol      *Lsymbol;       // symbol we don't know about 
    6868    int         Lseg;           // where the fixup is going (CODE or DATA, never UDATA) 
    69     short       Lflags;         // CFxxxx 
     69    int         Lflags;         // CFxxxx 
    7070    targ_size_t Loffset;        // addr of reference to symbol 
    7171    targ_size_t Lval;           // value to add into location 
    7272#if TARGET_OSX 
    7373    symbol      *Lfuncsym;      // function the symbol goes in 
    7474#endif 
    7575    fixlist *Lnext;             // next in threaded list 
    7676 
    7777    static fixlist *start; 
    7878}; 
    7979 
    8080fixlist *fixlist::start = NULL; 
    8181 
    8282/************* 
    8383 * Size in bytes of each instruction. 
    8484 * 0 means illegal instruction. 
    8585 * bit  M:      if there is a modregrm field (EV1 is reserved for modregrm) 
    8686 * bit  T:      if there is a second operand (EV2) 
    8787 * bit  E:      if second operand is only 8 bits 
    8888 * bit  A:      a short version exists for the AX reg 
    8989 * bit  R:      a short version exists for regs 
     
    34583458    unsigned char rm,mod,ins; 
    34593459    unsigned iflags; 
    34603460    unsigned i32 = I32 || I64; 
    34613461    unsigned a32 = i32; 
    34623462 
    34633463#ifdef DEBUG 
    34643464    assert((a32 & ~1) == 0); 
    34653465#endif 
    34663466    iflags = c->Iflags; 
    34673467    op = c->Iop; 
    34683468    switch (op) 
    34693469    { 
    34703470        case 0x0F: 
    34713471            ins = inssize2[c->Iop2]; 
    34723472            size = ins & 7; 
    34733473            break; 
    34743474 
    34753475        case NOP: 
    34763476        case ESCAPE: 
    34773477            size = 0;                   // since these won't be output 
    3478             goto Lret
     3478            goto Lret2
    34793479 
    34803480        case ASM: 
    34813481            if (c->Iflags == CFaddrsize)        // kludge for DA inline asm 
    34823482                size = NPTRSIZE; 
    34833483            else 
    34843484                size = c->IEV1.as.len; 
    3485             goto Lret
     3485            goto Lret2
    34863486 
    34873487        case 0xA1: 
    34883488        case 0xA3: 
    34893489            if (c->Irex) 
    34903490            { 
    34913491                size = 9;               // 64 bit immediate value for MOV to/from RAX 
    34923492                goto Lret; 
    34933493            } 
    34943494            goto Ldefault; 
    34953495 
    34963496        case 0xF6:                      /* TEST mem8,immed8             */ 
    34973497            ins = inssize[op]; 
    34983498            size = ins & 7; 
    34993499            if (i32) 
    35003500                size = inssize32[op]; 
    35013501            if ((c->Irm & (7<<3)) == 0) 
    35023502                size++;                 /* size of immed8               */ 
    35033503            break; 
    35043504 
    35053505        case 0xF7: 
     
    35823582                case 0x40: 
    35833583                    size++;             /* disp8                        */ 
    35843584                    break; 
    35853585                case 0x80: 
    35863586                    size += 4;          /* disp32                       */ 
    35873587                    break; 
    35883588            } 
    35893589        } 
    35903590        else 
    35913591        {   // 16 bit addressing 
    35923592            if (mod == 0x40)            /* 01: 8 bit displacement       */ 
    35933593                size++; 
    35943594            else if (mod == 0x80 || (mod == 0 && (rm & 7) == 6)) 
    35953595                size += 2; 
    35963596        } 
    35973597    } 
    35983598 
    35993599Lret: 
    36003600    if (c->Irex) 
    36013601        size++; 
     3602Lret2: 
    36023603    //printf("op = x%02x, size = %d\n",op,size); 
    36033604    return size; 
    36043605} 
    36053606 
    36063607 
    36073608/******************************** 
    36083609 * Return !=0 if codes match. 
    36093610 */ 
    36103611 
    36113612#if 0 
    36123613 
    36133614int code_match(code *c1,code *c2) 
    36143615{   code cs1,cs2; 
    36153616    unsigned char ins; 
    36163617 
    36173618    if (c1 == c2) 
    36183619        goto match; 
    36193620    cs1 = *c1; 
    36203621    cs2 = *c2; 
    36213622    if (cs1.Iop != cs2.Iop) 
     
    38753875        { 
    38763876            rm = c->Irm; 
    38773877            GEN(rm); 
    38783878 
    38793879            // Look for an address size override when working with the 
    38803880            // MOD R/M and SIB bytes 
    38813881 
    38823882            if (is32bitaddr( I32, flags)) 
    38833883            { 
    38843884                if (issib(rm)) 
    38853885                    GEN(c->Isib); 
    38863886                switch (rm & 0xC0) 
    38873887                {   case 0x40: 
    38883888                        do8bit((enum FL) c->IFL1,&c->IEV1);     // 8 bit 
    38893889                        break; 
    38903890                    case 0: 
    38913891                        if (!(issib(rm) && (c->Isib & 7) == 5 || 
    38923892                              (rm & 7) == 5)) 
    38933893                            break; 
    38943894                    case 0x80: 
    3895                         do32bit((enum FL)c->IFL1,&c->IEV1,CFoff); 
     3895                        do32bit((enum FL)c->IFL1,&c->IEV1,CFoff | CFpc32); 
    38963896                        break; 
    38973897                } 
    38983898            } 
    38993899            else 
    39003900            { 
    39013901                switch (rm & 0xC0) 
    39023902                {   case 0x40: 
    39033903                        do8bit((enum FL) c->IFL1,&c->IEV1);     // 8 bit 
    39043904                        break; 
    39053905                    case 0: 
    39063906                        if ((rm & 7) != 6) 
    39073907                            break; 
    39083908                    case 0x80: 
    39093909                        do16bit((enum FL)c->IFL1,&c->IEV1,CFoff); 
    39103910                        break; 
    39113911                } 
    39123912            } 
    39133913        } 
    39143914        else 
    39153915        { 
     
    41284128            //printf("FLblockoff: offset = %x, Boffset = %x, funcoffset = %x\n", offset, uev->Vblock->Boffset, funcoffset); 
    41294129            reftocodseg(cseg,offset,uev->Vblock->Boffset); 
    41304130            break; 
    41314131 
    41324132        default: 
    41334133#ifdef DEBUG 
    41344134            WRFL(fl); 
    41354135#endif 
    41364136            assert(0); 
    41374137    } 
    41384138    offset += 8; 
    41394139} 
    41404140 
    41414141 
    41424142STATIC void do32bit(enum FL fl,union evc *uev,int flags) 
    41434143{ char *p; 
    41444144  symbol *s; 
    41454145  targ_size_t ad; 
    41464146  long tmp; 
    41474147 
     4148  //printf("do32bit(flags = x%x)\n", flags); 
    41484149  switch (fl) 
    41494150  { 
    41504151    case FLconst: 
    41514152        assert(sizeof(targ_size_t) == 4 || sizeof(targ_size_t) == 8); 
    41524153        ad = * (targ_size_t *) uev; 
    41534154    L1: 
    41544155        GENP(4,&ad); 
    41554156        return; 
    41564157    case FLdatseg: 
    41574158        FLUSH(); 
    41584159        reftodatseg(cseg,offset,uev->_EP.Vpointer,uev->_EP.Vseg,flags); 
    41594160        break; 
    41604161#if 0 
    41614162    case FLcsdata: 
    41624163        FLUSH(); 
    41634164        reftocodseg(cseg,offset,uev->Vpointer); 
    41644165        break; 
    41654166#endif 
    41664167    case FLframehandler: 
    41674168        framehandleroffset = OFFSET(); 
     
    43564357void addtofixlist(symbol *s,targ_size_t soffset,int seg,targ_size_t val,int flags) 
    43574358{       fixlist *ln; 
    43584359        static char zeros[8]; 
    43594360        int numbytes; 
    43604361 
    43614362        //printf("addtofixlist(%p '%s')\n",s,s->Sident); 
    43624363        assert(flags); 
    43634364        ln = (fixlist *) mem_calloc(sizeof(fixlist)); 
    43644365        ln->Lsymbol = s; 
    43654366        ln->Loffset = soffset; 
    43664367        ln->Lseg = seg; 
    43674368        ln->Lflags = flags; 
    43684369        ln->Lval = val; 
    43694370#if TARGET_OSX 
    43704371        ln->Lfuncsym = funcsym_p; 
    43714372#endif 
    43724373        ln->Lnext = fixlist::start; 
    43734374        fixlist::start = ln; 
    43744375#if TARGET_FLAT 
    43754376        numbytes = tysize[TYnptr]; 
     4377        if (I64 && !(flags & CFoffset64)) 
     4378            numbytes = 4; 
    43764379        assert(!(flags & CFseg)); 
    43774380#else 
    43784381        switch (flags & (CFoff | CFseg)) 
    43794382        { 
    43804383            case CFoff:         numbytes = tysize[TYnptr];      break; 
    43814384            case CFseg:         numbytes = 2;                   break; 
    43824385            case CFoff | CFseg: numbytes = tysize[TYfptr];      break; 
    43834386            default:            assert(0); 
    43844387        } 
    43854388#endif 
    43864389#ifdef DEBUG 
    43874390        assert(numbytes <= sizeof(zeros)); 
    43884391#endif 
    43894392        obj_bytes(seg,soffset,numbytes,zeros); 
    43904393} 
    43914394 
    43924395/**************************** 
    43934396 * Given a function symbol we've just defined the offset for, 
    43944397 * search for it in the fixlist, and resolve any matches we find. 
    43954398 * Input: 
  • branches/dmd-1.x/src/backend/code.h

    r577 r580  
    373373#define CFtarg            4     // this code is the target of a jump 
    374374#define CFseg             8     // get segment of immediate value 
    375375#define CFoff          0x10     // get offset of immediate value 
    376376#define CFss           0x20     // generate an SS: segment override (not with 
    377377                                // CFes at the same time, though!) 
    378378#define CFpsw          0x40     // we need the flags result after this instruction 
    379379#define CFopsize       0x80     // prefix with operand size 
    380380#define CFaddrsize    0x100     // prefix with address size 
    381381#define CFds          0x200     // need DS override (not with es, ss, or cs ) 
    382382#define CFcs          0x400     // need CS override 
    383383#define CFfs          0x800     // need FS override 
    384384#define CFgs    (CFcs | CFfs)   // need GS override 
    385385#define CFwait       0x1000     // If I32 it indicates when to output a WAIT 
    386386#define CFselfrel    0x2000     // if self-relative 
    387387#define CFunambig    0x4000     // indicates cannot be accessed by other addressing 
    388388                                // modes 
    389389#define CFtarg2      0x8000     // like CFtarg, but we can't optimize this away 
    390390#define CFvolatile  0x10000     // volatile reference, do not schedule 
    391391#define CFclassinit 0x20000     // class init code 
    392392#define CFoffset64  0x40000     // offset is 64 bits 
     393#define CFpc32      0x80000     // I64: PC relative 32 bit fixup 
    393394 
    394395#define CFPREFIX (CFSEG | CFopsize | CFaddrsize) 
    395396#define CFSEG   (CFes | CFss | CFds | CFcs | CFfs | CFgs) 
    396397 
    397398 
    398399    unsigned char Iop; 
    399400    unsigned char Iop2;         // second opcode byte 
    400401    unsigned char Iop3;         // third opcode byte 
    401402 
    402403    union 
    403404    {   unsigned _Iea; 
    404405        struct 
    405406        { 
    406407            unsigned char _Irm;          // reg/mode 
    407408            unsigned char _Isib;         // SIB byte 
    408409            unsigned char _Irex;         // REX prefix 
    409410        } _ea; 
    410411    } _EA; 
    411412 
    412413#define Iea _EA._Iea 
  • branches/dmd-1.x/src/backend/el.c

    r569 r580  
    14431443#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    14441444        !(s->Stype->Tty & mTYthread) && 
    14451445#endif 
    14461446        !tyfunc(s->ty())) 
    14471447        // Position Independent Code 
    14481448        return el_picvar(s); 
    14491449#endif 
    14501450    symbol_debug(s); 
    14511451    type_debug(s->Stype); 
    14521452    e = el_calloc(); 
    14531453    e->Eoper = OPvar; 
    14541454    e->EV.sp.Vsym = s; 
    14551455    type_debug(s->Stype); 
    14561456    e->Ety = s->ty(); 
    14571457    if (s->Stype->Tty & mTYthread) 
    14581458    { 
    14591459        //printf("thread local %s\n", s->Sident); 
    14601460#if TARGET_OSX 
    14611461        ; 
    14621462#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    1463         ;               // add GS: override in back end 
    1464         /* Generate
    1465          *      MOV reg,GS:[00000000] 
     1463        /* For 32 bit: 
     1464        * Generate for var locals
     1465         *      MOV reg,GS:[00000000]   // add GS: override in back end 
    14661466         *      ADD reg, offset s@TLS_LE 
    14671467         *      e => *(&s + *(GS:0)) 
    1468          * for locals, and for globals: 
     1468         * For var globals: 
    14691469         *      MOV reg,GS:[00000000] 
    14701470         *      ADD reg, s@TLS_IE 
    14711471         *      e => *(s + *(GS:0)) 
    14721472         * note different fixup 
     1473         ***************************************** 
     1474         * For 64 bit: 
     1475         * Generate for var locals: 
     1476         *      MOV reg,FS:s@TPOFF32 
     1477         * For var globals: 
     1478         *      MOV RAX,s@GOTTPOFF[RIP] 
     1479         *      MOV reg,FS:[RAX] 
     1480         * 
     1481         * For address of locals: 
     1482         *      MOV RAX,FS:[00] 
     1483         *      LEA reg,s@TPOFF32[RAX] 
     1484         *      e => &s + *(FS:0) 
     1485         * For address of globals: 
     1486         *      MOV reg,FS:[00] 
     1487         *      MOV RAX,s@GOTTPOFF[RIP] 
     1488         *      ADD reg,RAX 
     1489         *      e => s + *(FS:0) 
     1490         * This leaves us with a problem, as the 'var' version cannot simply have 
     1491         * its address taken, as what is the address of FS:s ? The (not so efficient) 
     1492         * solution is to just use the second address form, and * it. 
     1493         * Turns out that is identical to the 32 bit version, except GS => FS and the 
     1494         * fixups are different. 
     1495         * In the future, we should figure out a way to optimize to the 'var' version. 
    14731496         */ 
    1474         elem *e1,*e2; 
    1475  
    1476         e1 = el_calloc(); 
     1497        elem *e1 = el_calloc(); 
    14771498        e1->EV.sp.Vsym = s; 
    14781499        if (s->Sclass == SCstatic || s->Sclass == SClocstat) 
    14791500        {   e1->Eoper = OPrelconst; 
    14801501            e1->Ety = TYnptr; 
    14811502        } 
    14821503        else 
    14831504        { 
    14841505            e1->Eoper = OPvar; 
    14851506            e1->Ety = TYnptr; 
    14861507        } 
    14871508 
    1488         // We'll fix this up in the back end to be GS:[0000] 
    1489         e2 = el_calloc(); 
     1509        /* Fake GS:[0000] as a load of _tls_array, and then in the back end recognize 
     1510         * the fake and rewrite it as GS:[0000] (or FS:[0000] for I64), because there is 
     1511         * no way to represent segment overrides in the elem nodes. 
     1512         */ 
     1513        elem *e2 = el_calloc(); 
    14901514        e2->Eoper = OPvar; 
    14911515        e2->EV.sp.Vsym = rtlsym[RTLSYM_TLS_ARRAY]; 
    14921516        e2->Ety = e2->EV.sp.Vsym->ty(); 
    14931517 
    14941518        e->Eoper = OPind; 
    14951519        e->E1 = el_bin(OPadd,e1->Ety,e2,e1); 
    14961520        e->E2 = NULL; 
    14971521#else 
    14981522        /* 
    14991523                mov     EAX,FS:__tls_array 
    15001524                mov     ECX,__tls_index 
    15011525                mov     EAX,[ECX*4][EAX] 
    15021526                inc     dword ptr _t[EAX] 
    15031527 
    15041528                e => *(&s + *(FS:_tls_array + _tls_index * 4)) 
    15051529 
    15061530                If this is an executable app, not a dll, _tls_index 
    15071531                can be assumed to be 0. 
    15081532         */ 
    15091533        elem *e1,*e2,*ea; 
     
    30703094  { 
    30713095        if (e->E2) 
    30723096            dbg_printf("%p %p\n",e->E1,e->E2); 
    30733097        else 
    30743098            dbg_printf("%p\n",e->E1); 
    30753099        elem_print(e->E1); 
    30763100  } 
    30773101  else if (OTbinary(e->Eoper)) 
    30783102  { 
    30793103        if (!PARSER && e->Eoper == OPstreq) 
    30803104                dbg_printf("bytes=%d ",e->Enumbytes); 
    30813105        dbg_printf("%p %p\n",e->E1,e->E2); 
    30823106        elem_print(e->E1); 
    30833107        elem_print(e->E2); 
    30843108  } 
    30853109  else 
    30863110  { 
    30873111        switch (e->Eoper) 
    30883112        { 
    30893113            case OPrelconst: 
    3090                 dbg_printf(" %ld+&",e->Eoffset); 
     3114                dbg_printf(" %lld+&",(unsigned long long)e->Eoffset); 
    30913115                dbg_printf(" %s",e->EV.sp.Vsym->Sident); 
    30923116                break; 
    30933117            case OPvar: 
    30943118                if (e->Eoffset) 
    3095                     dbg_printf(" %ld+",e->Eoffset); 
     3119                    dbg_printf(" %lld+",(unsigned long long)e->Eoffset); 
    30963120                dbg_printf(" %s",e->EV.sp.Vsym->Sident); 
    30973121                break; 
    30983122            case OPasm: 
    30993123            case OPstring: 
    31003124            case OPhstring: 
    3101                 dbg_printf(" '%s',%ld\n",e->EV.ss.Vstring,e->EV.ss.Voffset); 
     3125                dbg_printf(" '%s',%lld\n",e->EV.ss.Vstring,(unsigned long long)e->EV.ss.Voffset); 
    31023126                break; 
    31033127            case OPconst: 
    31043128                tym = tybasic(typemask(e)); 
    31053129            case_tym: 
    31063130                switch (tym) 
    31073131                {   case TYbool: 
    31083132                    case TYchar: 
    31093133                    case TYschar: 
    31103134                    case TYuchar: 
    31113135                        dbg_printf("%d ",e->EV.Vuchar); 
    31123136                        break; 
    31133137#if TX86 
    31143138                    case TYsptr: 
    31153139#if JHANDLE 
    31163140                    case TYjhandle: 
    31173141#endif 
    31183142                    case TYnullptr: 
    31193143                    case TYnptr: 
    31203144                    case TYcptr: 
    31213145#endif 
  • trunk/src/backend/cod1.c

    r579 r580  
    542542 * Can handle indirection operators, but not if they're common subs. 
    543543 * Input: 
    544544 *      e ->    elem where we get some of the data from 
    545545 *      cs ->   partially filled code to add 
    546546 *      op =    opcode 
    547547 *      reg =   reg field of (mod reg r/m) 
    548548 *      offset = data to be added to Voffset field 
    549549 *      keepmsk = mask of registers we must not destroy 
    550550 *      desmsk  = mask of registers destroyed by executing the instruction 
    551551 * Returns: 
    552552 *      pointer to code generated 
    553553 */ 
    554554 
    555555code *loadea(elem *e,code *cs,unsigned op,unsigned reg,targ_size_t offset, 
    556556        regm_t keepmsk,regm_t desmsk) 
    557557{ 
    558558  code *c,*cg,*cd; 
    559559 
    560560#ifdef DEBUG 
    561561  if (debugw) 
    562     printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%ld keepmsk=x%x desmsk=x%x\n", 
    563             e,cs,op,reg,offset,keepmsk,desmsk); 
     562    printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%lld keepmsk=x%x desmsk=x%x\n", 
     563            e,cs,op,reg,(unsigned long long)offset,keepmsk,desmsk); 
    564564#endif 
    565565 
    566566  assert(e); 
    567567  cs->Iflags = 0; 
    568568  cs->Irex = 0; 
    569569  cs->Iop = op; 
    570570  if (!I16 && op >= 0x100)               // if 2 byte opcode 
    571571  {     cs->Iop = op >> 8; 
    572572        cs->Iop2 = op; 
    573573  } 
    574574  tym_t tym = e->Ety; 
    575575  int sz = tysize(tym); 
    576576 
    577577  /* Determine if location we want to get is in a register. If so,      */ 
    578578  /* substitute the register for the EA.                                */ 
    579579  /* Note that operators don't go through this. CSE'd operators are     */ 
    580580  /* picked up by comsub().                                             */ 
    581581  if (e->Ecount &&                      /* if cse                       */ 
    582582      e->Ecount != e->Ecomsub &&        /* and cse was generated        */ 
    583583      op != 0x8D && op != 0xC4 &&       /* and not an LEA or LES        */ 
     
    12681268                { 
    12691269                    pcs->Irm = modregrm(3,0,s->Spreg & 7); 
    12701270                    if (s->Spreg & 8) 
    12711271                        pcs->Irex |= REX_B; 
    12721272                    regcon.used |= mask[s->Spreg]; 
    12731273                    break; 
    12741274                } 
    12751275            } 
    12761276            else 
    12771277                regcon.params &= ~mask[s->Spreg]; 
    12781278        } 
    12791279    case FLtmp: 
    12801280    case FLbprel: 
    12811281        reflocal = TRUE; 
    12821282        pcs->Irm = modregrm(2,0,BPRM); 
    12831283        goto L2; 
    12841284    case FLextern: 
    12851285        if (s->Sident[0] == '_' && memcmp(s->Sident + 1,"tls_array",10) == 0) 
    12861286        { 
    12871287#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    1288             // Rewrite as GS:[0000] 
    1289             pcs->Irm = modregrm(0, 0, BPRM); 
    1290             pcs->IFL1 = FLconst; 
    1291             pcs->IEV1.Vuns = 0; 
    1292             pcs->Iflags = CFgs; 
     1288            // Rewrite as GS:[0000], or FS:[0000] for 64 bit 
     1289            if (I64) 
     1290            { 
     1291                pcs->Irm = modregrm(0, 0, 4); 
     1292                pcs->Isib = modregrm(0, 4, 5);  // don't use [RIP] addressing 
     1293                pcs->IFL1 = FLconst; 
     1294                pcs->IEV1.Vuns = 0; 
     1295                pcs->Iflags = CFfs; 
     1296            } 
     1297            else 
     1298            { 
     1299                pcs->Irm = modregrm(0, 0, BPRM); 
     1300                pcs->IFL1 = FLconst; 
     1301                pcs->IEV1.Vuns = 0; 
     1302                pcs->Iflags = CFgs; 
     1303            } 
     1304            break; 
    12931305#else 
    12941306            pcs->Iflags |= CFfs;                // add FS: override 
    12951307#endif 
    12961308        } 
    12971309        if (s->ty() & mTYcs && LARGECODE) 
    12981310            goto Lfardata; 
    12991311        goto L3; 
    13001312    case FLdata: 
    13011313    case FLudata: 
    13021314    case FLcsdata: 
    13031315#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    13041316    case FLgot: 
    13051317    case FLgotoff: 
    13061318    case FLtlsdata: 
    13071319#endif 
    13081320    L3: 
    13091321        pcs->Irm = modregrm(0,0,BPRM); 
    13101322    L2: 
    13111323        if (fl == FLreg) 
    13121324        {   assert(s->Sregm & regcon.mvar); 
  • trunk/src/backend/cod3.c

    r579 r580  
    4949static int EBPtoESP;            // add to EBP offset to get ESP offset 
    5050static int AAoff;               // offset of alloca temporary 
    5151 
    5252#if ELFOBJ || MACHOBJ 
    5353#define JMPSEG  CDATA 
    5454#define JMPOFF  CDoffset 
    5555#else 
    5656#define JMPSEG  DATA 
    5757#define JMPOFF  Doffset 
    5858#endif 
    5959 
    6060/************************ 
    6161 * When we don't know whether a function symbol is defined or not 
    6262 * within this module, we stuff it in this linked list of references 
    6363 * to be fixed up later. 
    6464 */ 
    6565 
    6666struct fixlist 
    6767{   symbol      *Lsymbol;       // symbol we don't know about 
    6868    int         Lseg;           // where the fixup is going (CODE or DATA, never UDATA) 
    69     short       Lflags;         // CFxxxx 
     69    int         Lflags;         // CFxxxx 
    7070    targ_size_t Loffset;        // addr of reference to symbol 
    7171    targ_size_t Lval;           // value to add into location 
    7272#if TARGET_OSX 
    7373    symbol      *Lfuncsym;      // function the symbol goes in 
    7474#endif 
    7575    fixlist *Lnext;             // next in threaded list 
    7676 
    7777    static fixlist *start; 
    7878}; 
    7979 
    8080fixlist *fixlist::start = NULL; 
    8181 
    8282/************* 
    8383 * Size in bytes of each instruction. 
    8484 * 0 means illegal instruction. 
    8585 * bit  M:      if there is a modregrm field (EV1 is reserved for modregrm) 
    8686 * bit  T:      if there is a second operand (EV2) 
    8787 * bit  E:      if second operand is only 8 bits 
    8888 * bit  A:      a short version exists for the AX reg 
    8989 * bit  R:      a short version exists for regs 
     
    34583458    unsigned char rm,mod,ins; 
    34593459    unsigned iflags; 
    34603460    unsigned i32 = I32 || I64; 
    34613461    unsigned a32 = i32; 
    34623462 
    34633463#ifdef DEBUG 
    34643464    assert((a32 & ~1) == 0); 
    34653465#endif 
    34663466    iflags = c->Iflags; 
    34673467    op = c->Iop; 
    34683468    switch (op) 
    34693469    { 
    34703470        case 0x0F: 
    34713471            ins = inssize2[c->Iop2]; 
    34723472            size = ins & 7; 
    34733473            break; 
    34743474 
    34753475        case NOP: 
    34763476        case ESCAPE: 
    34773477            size = 0;                   // since these won't be output 
    3478             goto Lret
     3478            goto Lret2
    34793479 
    34803480        case ASM: 
    34813481            if (c->Iflags == CFaddrsize)        // kludge for DA inline asm 
    34823482                size = NPTRSIZE; 
    34833483            else 
    34843484                size = c->IEV1.as.len; 
    3485             goto Lret
     3485            goto Lret2
    34863486 
    34873487        case 0xA1: 
    34883488        case 0xA3: 
    34893489            if (c->Irex) 
    34903490            { 
    34913491                size = 9;               // 64 bit immediate value for MOV to/from RAX 
    34923492                goto Lret; 
    34933493            } 
    34943494            goto Ldefault; 
    34953495 
    34963496        case 0xF6:                      /* TEST mem8,immed8             */ 
    34973497            ins = inssize[op]; 
    34983498            size = ins & 7; 
    34993499            if (i32) 
    35003500                size = inssize32[op]; 
    35013501            if ((c->Irm & (7<<3)) == 0) 
    35023502                size++;                 /* size of immed8               */ 
    35033503            break; 
    35043504 
    35053505        case 0xF7: 
     
    35823582                case 0x40: 
    35833583                    size++;             /* disp8                        */ 
    35843584                    break; 
    35853585                case 0x80: 
    35863586                    size += 4;          /* disp32                       */ 
    35873587                    break; 
    35883588            } 
    35893589        } 
    35903590        else 
    35913591        {   // 16 bit addressing 
    35923592            if (mod == 0x40)            /* 01: 8 bit displacement       */ 
    35933593                size++; 
    35943594            else if (mod == 0x80 || (mod == 0 && (rm & 7) == 6)) 
    35953595                size += 2; 
    35963596        } 
    35973597    } 
    35983598 
    35993599Lret: 
    36003600    if (c->Irex) 
    36013601        size++; 
     3602Lret2: 
    36023603    //printf("op = x%02x, size = %d\n",op,size); 
    36033604    return size; 
    36043605} 
    36053606 
    36063607 
    36073608/******************************** 
    36083609 * Return !=0 if codes match. 
    36093610 */ 
    36103611 
    36113612#if 0 
    36123613 
    36133614int code_match(code *c1,code *c2) 
    36143615{   code cs1,cs2; 
    36153616    unsigned char ins; 
    36163617 
    36173618    if (c1 == c2) 
    36183619        goto match; 
    36193620    cs1 = *c1; 
    36203621    cs2 = *c2; 
    36213622    if (cs1.Iop != cs2.Iop) 
     
    38753875        { 
    38763876            rm = c->Irm; 
    38773877            GEN(rm); 
    38783878 
    38793879            // Look for an address size override when working with the 
    38803880            // MOD R/M and SIB bytes 
    38813881 
    38823882            if (is32bitaddr( I32, flags)) 
    38833883            { 
    38843884                if (issib(rm)) 
    38853885                    GEN(c->Isib); 
    38863886                switch (rm & 0xC0) 
    38873887                {   case 0x40: 
    38883888                        do8bit((enum FL) c->IFL1,&c->IEV1);     // 8 bit 
    38893889                        break; 
    38903890                    case 0: 
    38913891                        if (!(issib(rm) && (c->Isib & 7) == 5 || 
    38923892                              (rm & 7) == 5)) 
    38933893                            break; 
    38943894                    case 0x80: 
    3895                         do32bit((enum FL)c->IFL1,&c->IEV1,CFoff); 
     3895                        do32bit((enum FL)c->IFL1,&c->IEV1,CFoff | CFpc32); 
    38963896                        break; 
    38973897                } 
    38983898            } 
    38993899            else 
    39003900            { 
    39013901                switch (rm & 0xC0) 
    39023902                {   case 0x40: 
    39033903                        do8bit((enum FL) c->IFL1,&c->IEV1);     // 8 bit 
    39043904                        break; 
    39053905                    case 0: 
    39063906                        if ((rm & 7) != 6) 
    39073907                            break; 
    39083908                    case 0x80: 
    39093909                        do16bit((enum FL)c->IFL1,&c->IEV1,CFoff); 
    39103910                        break; 
    39113911                } 
    39123912            } 
    39133913        } 
    39143914        else 
    39153915        { 
     
    41284128            //printf("FLblockoff: offset = %x, Boffset = %x, funcoffset = %x\n", offset, uev->Vblock->Boffset, funcoffset); 
    41294129            reftocodseg(cseg,offset,uev->Vblock->Boffset); 
    41304130            break; 
    41314131 
    41324132        default: 
    41334133#ifdef DEBUG 
    41344134            WRFL(fl); 
    41354135#endif 
    41364136            assert(0); 
    41374137    } 
    41384138    offset += 8; 
    41394139} 
    41404140 
    41414141 
    41424142STATIC void do32bit(enum FL fl,union evc *uev,int flags) 
    41434143{ char *p; 
    41444144  symbol *s; 
    41454145  targ_size_t ad; 
    41464146  long tmp; 
    41474147 
     4148  //printf("do32bit(flags = x%x)\n", flags); 
    41484149  switch (fl) 
    41494150  { 
    41504151    case FLconst: 
    41514152        assert(sizeof(targ_size_t) == 4 || sizeof(targ_size_t) == 8); 
    41524153        ad = * (targ_size_t *) uev; 
    41534154    L1: 
    41544155        GENP(4,&ad); 
    41554156        return; 
    41564157    case FLdatseg: 
    41574158        FLUSH(); 
    41584159        reftodatseg(cseg,offset,uev->_EP.Vpointer,uev->_EP.Vseg,flags); 
    41594160        break; 
    41604161#if 0 
    41614162    case FLcsdata: 
    41624163        FLUSH(); 
    41634164        reftocodseg(cseg,offset,uev->Vpointer); 
    41644165        break; 
    41654166#endif 
    41664167    case FLframehandler: 
    41674168        framehandleroffset = OFFSET(); 
     
    43564357void addtofixlist(symbol *s,targ_size_t soffset,int seg,targ_size_t val,int flags) 
    43574358{       fixlist *ln; 
    43584359        static char zeros[8]; 
    43594360        int numbytes; 
    43604361 
    43614362        //printf("addtofixlist(%p '%s')\n",s,s->Sident); 
    43624363        assert(flags); 
    43634364        ln = (fixlist *) mem_calloc(sizeof(fixlist)); 
    43644365        ln->Lsymbol = s; 
    43654366        ln->Loffset = soffset; 
    43664367        ln->Lseg = seg; 
    43674368        ln->Lflags = flags; 
    43684369        ln->Lval = val; 
    43694370#if TARGET_OSX 
    43704371        ln->Lfuncsym = funcsym_p; 
    43714372#endif 
    43724373        ln->Lnext = fixlist::start; 
    43734374        fixlist::start = ln; 
    43744375#if TARGET_FLAT 
    43754376        numbytes = tysize[TYnptr]; 
     4377        if (I64 && !(flags & CFoffset64)) 
     4378            numbytes = 4; 
    43764379        assert(!(flags & CFseg)); 
    43774380#else 
    43784381        switch (flags & (CFoff | CFseg)) 
    43794382        { 
    43804383            case CFoff:         numbytes = tysize[TYnptr];      break; 
    43814384            case CFseg:         numbytes = 2;                   break; 
    43824385            case CFoff | CFseg: numbytes = tysize[TYfptr];      break; 
    43834386            default:            assert(0); 
    43844387        } 
    43854388#endif 
    43864389#ifdef DEBUG 
    43874390        assert(numbytes <= sizeof(zeros)); 
    43884391#endif 
    43894392        obj_bytes(seg,soffset,numbytes,zeros); 
    43904393} 
    43914394 
    43924395/**************************** 
    43934396 * Given a function symbol we've just defined the offset for, 
    43944397 * search for it in the fixlist, and resolve any matches we find. 
    43954398 * Input: 
  • trunk/src/backend/code.h

    r577 r580  
    373373#define CFtarg            4     // this code is the target of a jump 
    374374#define CFseg             8     // get segment of immediate value 
    375375#define CFoff          0x10     // get offset of immediate value 
    376376#define CFss           0x20     // generate an SS: segment override (not with 
    377377                                // CFes at the same time, though!) 
    378378#define CFpsw          0x40     // we need the flags result after this instruction 
    379379#define CFopsize       0x80     // prefix with operand size 
    380380#define CFaddrsize    0x100     // prefix with address size 
    381381#define CFds          0x200     // need DS override (not with es, ss, or cs ) 
    382382#define CFcs          0x400     // need CS override 
    383383#define CFfs          0x800     // need FS override 
    384384#define CFgs    (CFcs | CFfs)   // need GS override 
    385385#define CFwait       0x1000     // If I32 it indicates when to output a WAIT 
    386386#define CFselfrel    0x2000     // if self-relative 
    387387#define CFunambig    0x4000     // indicates cannot be accessed by other addressing 
    388388                                // modes 
    389389#define CFtarg2      0x8000     // like CFtarg, but we can't optimize this away 
    390390#define CFvolatile  0x10000     // volatile reference, do not schedule 
    391391#define CFclassinit 0x20000     // class init code 
    392392#define CFoffset64  0x40000     // offset is 64 bits 
     393#define CFpc32      0x80000     // I64: PC relative 32 bit fixup 
    393394 
    394395#define CFPREFIX (CFSEG | CFopsize | CFaddrsize) 
    395396#define CFSEG   (CFes | CFss | CFds | CFcs | CFfs | CFgs) 
    396397 
    397398 
    398399    unsigned char Iop; 
    399400    unsigned char Iop2;         // second opcode byte 
    400401    unsigned char Iop3;         // third opcode byte 
    401402 
    402403    union 
    403404    {   unsigned _Iea; 
    404405        struct 
    405406        { 
    406407            unsigned char _Irm;          // reg/mode 
    407408            unsigned char _Isib;         // SIB byte 
    408409            unsigned char _Irex;         // REX prefix 
    409410        } _ea; 
    410411    } _EA; 
    411412 
    412413#define Iea _EA._Iea 
  • trunk/src/backend/el.c

    r569 r580  
    14431443#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    14441444        !(s->Stype->Tty & mTYthread) && 
    14451445#endif 
    14461446        !tyfunc(s->ty())) 
    14471447        // Position Independent Code 
    14481448        return el_picvar(s); 
    14491449#endif 
    14501450    symbol_debug(s); 
    14511451    type_debug(s->Stype); 
    14521452    e = el_calloc(); 
    14531453    e->Eoper = OPvar; 
    14541454    e->EV.sp.Vsym = s; 
    14551455    type_debug(s->Stype); 
    14561456    e->Ety = s->ty(); 
    14571457    if (s->Stype->Tty & mTYthread) 
    14581458    { 
    14591459        //printf("thread local %s\n", s->Sident); 
    14601460#if TARGET_OSX 
    14611461        ; 
    14621462#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    1463         ;               // add GS: override in back end 
    1464         /* Generate
    1465          *      MOV reg,GS:[00000000] 
     1463        /* For 32 bit: 
     1464        * Generate for var locals
     1465         *      MOV reg,GS:[00000000]   // add GS: override in back end 
    14661466         *      ADD reg, offset s@TLS_LE 
    14671467         *      e => *(&s + *(GS:0)) 
    1468          * for locals, and for globals: 
     1468         * For var globals: 
    14691469         *      MOV reg,GS:[00000000] 
    14701470         *      ADD reg, s@TLS_IE 
    14711471         *      e => *(s + *(GS:0)) 
    14721472         * note different fixup 
     1473         ***************************************** 
     1474         * For 64 bit: 
     1475         * Generate for var locals: 
     1476         *      MOV reg,FS:s@TPOFF32 
     1477         * For var globals: 
     1478         *      MOV RAX,s@GOTTPOFF[RIP] 
     1479         *      MOV reg,FS:[RAX] 
     1480         * 
     1481         * For address of locals: 
     1482         *      MOV RAX,FS:[00] 
     1483         *      LEA reg,s@TPOFF32[RAX] 
     1484         *      e => &s + *(FS:0) 
     1485         * For address of globals: 
     1486         *      MOV reg,FS:[00] 
     1487         *      MOV RAX,s@GOTTPOFF[RIP] 
     1488         *      ADD reg,RAX 
     1489         *      e => s + *(FS:0) 
     1490         * This leaves us with a problem, as the 'var' version cannot simply have 
     1491         * its address taken, as what is the address of FS:s ? The (not so efficient) 
     1492         * solution is to just use the second address form, and * it. 
     1493         * Turns out that is identical to the 32 bit version, except GS => FS and the 
     1494         * fixups are different. 
     1495         * In the future, we should figure out a way to optimize to the 'var' version. 
    14731496         */ 
    1474         elem *e1,*e2; 
    1475  
    1476         e1 = el_calloc(); 
     1497        elem *e1 = el_calloc(); 
    14771498        e1->EV.sp.Vsym = s; 
    14781499        if (s->Sclass == SCstatic || s->Sclass == SClocstat) 
    14791500        {   e1->Eoper = OPrelconst; 
    14801501            e1->Ety = TYnptr; 
    14811502        } 
    14821503        else 
    14831504        { 
    14841505            e1->Eoper = OPvar; 
    14851506            e1->Ety = TYnptr; 
    14861507        } 
    14871508 
    1488         // We'll fix this up in the back end to be GS:[0000] 
    1489         e2 = el_calloc(); 
     1509        /* Fake GS:[0000] as a load of _tls_array, and then in the back end recognize 
     1510         * the fake and rewrite it as GS:[0000] (or FS:[0000] for I64), because there is 
     1511         * no way to represent segment overrides in the elem nodes. 
     1512         */ 
     1513        elem *e2 = el_calloc(); 
    14901514        e2->Eoper = OPvar; 
    14911515        e2->EV.sp.Vsym = rtlsym[RTLSYM_TLS_ARRAY]; 
    14921516        e2->Ety = e2->EV.sp.Vsym->ty(); 
    14931517 
    14941518        e->Eoper = OPind; 
    14951519        e->E1 = el_bin(OPadd,e1->Ety,e2,e1); 
    14961520        e->E2 = NULL; 
    14971521#else 
    14981522        /* 
    14991523                mov     EAX,FS:__tls_array 
    15001524                mov     ECX,__tls_index 
    15011525                mov     EAX,[ECX*4][EAX] 
    15021526                inc     dword ptr _t[EAX] 
    15031527 
    15041528                e => *(&s + *(FS:_tls_array + _tls_index * 4)) 
    15051529 
    15061530                If this is an executable app, not a dll, _tls_index 
    15071531                can be assumed to be 0. 
    15081532         */ 
    15091533        elem *e1,*e2,*ea; 
     
    30703094  { 
    30713095        if (e->E2) 
    30723096            dbg_printf("%p %p\n",e->E1,e->E2); 
    30733097        else 
    30743098            dbg_printf("%p\n",e->E1); 
    30753099        elem_print(e->E1); 
    30763100  } 
    30773101  else if (OTbinary(e->Eoper)) 
    30783102  { 
    30793103        if (!PARSER && e->Eoper == OPstreq) 
    30803104                dbg_printf("bytes=%d ",e->Enumbytes); 
    30813105        dbg_printf("%p %p\n",e->E1,e->E2); 
    30823106        elem_print(e->E1); 
    30833107        elem_print(e->E2); 
    30843108  } 
    30853109  else 
    30863110  { 
    30873111        switch (e->Eoper) 
    30883112        { 
    30893113            case OPrelconst: 
    3090                 dbg_printf(" %ld+&",e->Eoffset); 
     3114                dbg_printf(" %lld+&",(unsigned long long)e->Eoffset); 
    30913115                dbg_printf(" %s",e->EV.sp.Vsym->Sident); 
    30923116                break; 
    30933117            case OPvar: 
    30943118                if (e->Eoffset) 
    3095                     dbg_printf(" %ld+",e->Eoffset); 
     3119                    dbg_printf(" %lld+",(unsigned long long)e->Eoffset); 
    30963120                dbg_printf(" %s",e->EV.sp.Vsym->Sident); 
    30973121                break; 
    30983122            case OPasm: 
    30993123            case OPstring: 
    31003124            case OPhstring: 
    3101                 dbg_printf(" '%s',%ld\n",e->EV.ss.Vstring,e->EV.ss.Voffset); 
     3125                dbg_printf(" '%s',%lld\n",e->EV.ss.Vstring,(unsigned long long)e->EV.ss.Voffset); 
    31023126                break; 
    31033127            case OPconst: 
    31043128                tym = tybasic(typemask(e)); 
    31053129            case_tym: 
    31063130                switch (tym) 
    31073131                {   case TYbool: 
    31083132                    case TYchar: 
    31093133                    case TYschar: 
    31103134                    case TYuchar: 
    31113135                        dbg_printf("%d ",e->EV.Vuchar); 
    31123136                        break; 
    31133137#if TX86 
    31143138                    case TYsptr: 
    31153139#if JHANDLE 
    31163140                    case TYjhandle: 
    31173141#endif 
    31183142                    case TYnullptr: 
    31193143                    case TYnptr: 
    31203144                    case TYcptr: 
    31213145#endif