code *orthxmm(elem *e, regm_t *pretregs) { elem *e1 = e->E1; elem *e2 = e->E2; regm_t retregs = *pretregs & XMMREGS; if (!retregs) retregs = XMMREGS; code *c = codelem(e1,&retregs,FALSE); // eval left leaf unsigned reg = findreg(retregs); regm_t rretregs = XMMREGS & ~retregs; code *cr = scodelem(e2, &rretregs, retregs, TRUE); // eval right leaf unsigned op = xmmoperator(e1->Ety, e->Eoper); unsigned rreg = findreg(rretregs); // float + ifloat is not actually addition if ((e->Eoper == OPadd || e->Eoper == OPmin) && ((tyreal(e1->Ety) && tyimaginary(e2->Ety)) || (tyreal(e2->Ety) && tyimaginary(e1->Ety)))) { retregs |= rretregs; c = cat(c, cr); if (e->Eoper == OPmin) { unsigned nretregs = XMMREGS & ~retregs; unsigned sreg; // hold sign bit unsigned sz = tysize[tybasic(e1->Ety)]; c = cat(c,allocreg(&nretregs,&sreg,e2->Ety)); targ_size_t signbit = 0x80000000; if (sz == 8) signbit = 0x8000000000000000LL; c = cat(c, movxmmconst(sreg, sz, signbit, 0)); c = cat(c, getregs(nretregs)); unsigned xop = (sz == 8) ? XORPD : XORPS; // XORPD/S rreg,sreg c = cat(c, gen2(CNIL,xop,modregxrmx(3,rreg-XMM0,sreg-XMM0))); } if (retregs != *pretregs) c = cat(c, fixresult(e,retregs,pretregs)); return c; } /* We should take advantage of mem addressing modes for OP XMM,MEM * but we do not at the moment. */ code *cg; if (OTrel(e->Eoper)) { retregs = mPSW; cg = NULL; code *cc = gen2(CNIL,op,modregxrmx(3,rreg-XMM0,reg-XMM0)); return cat4(c,cr,cg,cc); } else cg = getregs(retregs); code *co = gen2(CNIL,op,modregxrmx(3,reg-XMM0,rreg-XMM0)); if (retregs != *pretregs) co = cat(co,fixresult(e,retregs,pretregs)); return cat4(c,cr,cg,co); }
char* cat8(char* s1, char* s2, char* s3, char* s4, char* s5, char* s6, char* s7, char* s8) { char* part2 = cat4(s5, s6, s7, s8); char* part1 = cat4(s1, s2, s3, s4); sprintf(output, "%s%s%s", part1, SEPARATOR, part2); free(part1); free(part2); return strdup(output); }
code *xmmneg(elem *e,regm_t *pretregs) { //printf("xmmneg()\n"); //elem_print(e); assert(*pretregs); tym_t tyml = tybasic(e->E1->Ety); int sz = tysize[tyml]; regm_t retregs = *pretregs & XMMREGS; if (!retregs) retregs = XMMREGS; /* Generate: * MOV reg,e1 * MOV rreg,signbit * XOR reg,rreg */ code *cl = codelem(e->E1,&retregs,FALSE); cl = cat(cl,getregs(retregs)); unsigned reg = findreg(retregs); regm_t rretregs = XMMREGS & ~retregs; unsigned rreg; cl = cat(cl,allocreg(&rretregs,&rreg,tyml)); targ_size_t signbit = 0x80000000; if (sz == 8) signbit = 0x8000000000000000LL; code *c = movxmmconst(rreg, sz, signbit, 0); code *cg = getregs(retregs); unsigned op = (sz == 8) ? XORPD : XORPS; // XORPD/S reg,rreg code *co = gen2(CNIL,op,modregxrmx(3,reg-XMM0,rreg-XMM0)); co = cat(co,fixresult(e,retregs,pretregs)); return cat4(cl,c,cg,co); }
char* cat5(char* s1, char* s2, char* s3, char* s4, char* s5) { char* part1 = cat4(s1, s2, s3, s4); if (s5 == NULL) s5 = blank; sprintf(output, "%s%s%s", part1, SEPARATOR, s5); free(part1); return strdup(output); }
code *nteh_unwind(regm_t retregs,unsigned index) { code *c; code cs; code *cs1; code *cs2; regm_t desregs; int reg; int local_unwind; // Shouldn't this always be CX? #if SCPP reg = AX; #else reg = CX; #endif #if MARS local_unwind = RTLSYM_D_LOCAL_UNWIND2; #else local_unwind = RTLSYM_LOCAL_UNWIND2; #endif desregs = (~rtlsym[local_unwind]->Sregsaved & (ALLREGS)) | mask[reg]; gensaverestore(retregs & desregs,&cs1,&cs2); c = getregs(desregs); cs.Iop = 0x8D; cs.Irm = modregrm(2,reg,BPRM); cs.Iflags = 0; cs.Irex = 0; cs.IFL1 = FLconst; // EBP offset of __context.prev cs.IEV1.Vint = nteh_EBPoffset_prev(); c = gen(c,&cs); // LEA ECX,contextsym genc2(c,0x68,0,index); // PUSH index gen1(c,0x50 + reg); // PUSH ECX #if MARS //gencs(c,0xB8+AX,0,FLextern,nteh_scopetable()); // MOV EAX,&scope_table gencs(c,0x68,0,FLextern,nteh_scopetable()); // PUSH &scope_table gencs(c,0xE8,0,FLfunc,rtlsym[local_unwind]); // CALL __d_local_unwind2() genc2(c,0x81,modregrm(3,0,SP),12); // ADD ESP,12 #else gencs(c,0xE8,0,FLfunc,rtlsym[local_unwind]); // CALL __local_unwind2() genc2(c,0x81,modregrm(3,0,SP),8); // ADD ESP,8 #endif c = cat4(cs1,c,cs2,NULL); return c; }
std::vector<Cat> MakeVectorOfCats() { std::vector<Cat> cattor; cattor.reserve(4); cattor.push_back(Cat(L"Fluff")); cattor.push_back(Cat(L"Puff")); cattor.push_back(Cat(L"Ruff")); Cat cat4(L"Cough"); cattor.push_back(std::move(cat4)); return cattor; }
PUBLIC char * ar_ioOutPiece(Type t, const char *arg) { char * piece; TypeDescription d; list dimList; t = myUrType(t); d = type_description(t); dimList = d->structuredDes.array.dimensions; if (list_size(dimList) == 1) { piece = arraySpecialElemTypeName(d->structuredDes.array.type); if (piece != NULL) { return (ioSpecialElemOutPiece(piece, arg, (unsigned long) list_ref(dimList, 0))); } } return cat4(arrJName(t), ".outFunc(_call, ", arg, ")" ); }
Box MakeBoxOfCats() { Box catbox; Cat cat1(L"Furry"); catbox.MoveCatToBox(std::move(cat1)); // WARNING! At this point, cat1 has been moved to catbox, so it is no longer valid! Cat cat2(L"Purry"); catbox.AddCatToBox(cat2); Cat cat3(L"Curry"); catbox.AddCatToBox(cat3); Cat cat4(L"Allergy"); catbox.AddCatToBox(cat4); return catbox; }
code *linux_unwind(regm_t retregs,unsigned index) { code *c; code *cs1; code *cs2; int i; regm_t desregs; int reg; int local_unwind; // Shouldn't this always be CX? #if SCPP reg = AX; #else reg = CX; #endif #if MARS local_unwind = RTLSYM_D_LOCAL_UNWIND2; #else local_unwind = RTLSYM_LOCAL_UNWIND2; #endif desregs = (~rtlsym[local_unwind]->Sregsaved & (ALLREGS)) | mask[reg]; gensaverestore(retregs & desregs,&cs1,&cs2); c = getregs(desregs); c = genc2(c,0x68,0,index); // PUSH index #if MARS // gencs(c,0x68,0,FLextern,nteh_scopetable()); // PUSH &scope_table gencs(c,0xE8,0,FLfunc,rtlsym[local_unwind]); // CALL __d_local_unwind2() genc2(c,0x81,modregrm(3,0,SP),4); // ADD ESP,12 #else gencs(c,0xE8,0,FLfunc,rtlsym[local_unwind]); // CALL __local_unwind2() genc2(c,0x81,modregrm(3,0,SP),8); // ADD ESP,8 #endif c = cat4(cs1,c,cs2,NULL); return c; }
code *nteh_monitor_epilog(regm_t retregs) { /* * CALL _d_monitor_epilog * POP FS:__except_list */ code cs; code *c; code *cs1; code *cs2; code *cpop; regm_t desregs; Symbol *s; assert(config.flags2 & CFG2seh); // BUG: figure out how to implement for other EX's s = rtlsym[RTLSYM_MONITOR_EPILOG]; //desregs = ~s->Sregsaved & ALLREGS; desregs = 0; gensaverestore(retregs & desregs,&cs1,&cs2); c = getregs(desregs); c = gencs(c,0xE8,0,FLfunc,s); // CALL __d_monitor_epilog cs.Iop = 0x8F; cs.Irm = modregrm(0,0,BPRM); cs.Iflags = CFfs; cs.Irex = 0; cs.IFL1 = FLextern; cs.IEVsym1 = rtlsym[RTLSYM_EXCEPT_LIST]; cs.IEVoffset1 = 0; cpop = gen(NULL,&cs); // POP FS:__except_list c = cat4(cs1,c,cs2,cpop); return c; }
code *cdvector(elem *e, regm_t *pretregs) { /* e should look like one of: * vector * | * param * / \ * param op2 * / \ * op op1 */ if (!config.fpxmmregs) { printf("SIMD operations not supported on this platform\n"); exit(1); } unsigned n = el_nparams(e->E1); elem **params = (elem **)malloc(n * sizeof(elem *)); assert(params); elem **tmp = params; el_paramArray(&tmp, e->E1); #if 0 printf("cdvector()\n"); for (int i = 0; i < n; i++) { printf("[%d]: ", i); elem_print(params[i]); } #endif if (*pretregs == 0) { /* Evaluate for side effects only */ code *c = CNIL; for (int i = 0; i < n; i++) { c = cat(c, codelem(params[i], pretregs, FALSE)); *pretregs = 0; // in case they got set } return c; } assert(n >= 2 && n <= 4); elem *eop = params[0]; elem *op1 = params[1]; elem *op2 = NULL; tym_t ty2 = 0; if (n >= 3) { op2 = params[2]; ty2 = tybasic(op2->Ety); } unsigned op = el_tolong(eop); #ifdef DEBUG assert(!isXMMstore(op)); #endif tym_t ty1 = tybasic(op1->Ety); unsigned sz1 = tysize[ty1]; // assert(sz1 == 16); // float or double regm_t retregs; code *c; code *cr, *cg, *co; if (n == 3 && ty2 == TYuchar && op2->Eoper == OPconst) { // Handle: op xmm,imm8 retregs = *pretregs & XMMREGS; if (!retregs) retregs = XMMREGS; c = codelem(op1,&retregs,FALSE); // eval left leaf unsigned reg = findreg(retregs); int r; switch (op) { case PSLLD: r = 6; op = 0x660F72; break; case PSLLQ: r = 6; op = 0x660F73; break; case PSLLW: r = 6; op = 0x660F71; break; case PSRAD: r = 4; op = 0x660F72; break; case PSRAW: r = 4; op = 0x660F71; break; case PSRLD: r = 2; op = 0x660F72; break; case PSRLQ: r = 2; op = 0x660F73; break; case PSRLW: r = 2; op = 0x660F71; break; case PSRLDQ: r = 3; op = 0x660F73; break; case PSLLDQ: r = 7; op = 0x660F73; break; default: printf("op = x%x\n", op); assert(0); break; } cr = CNIL; cg = getregs(retregs); co = genc2(CNIL,op,modregrmx(3,r,reg-XMM0), el_tolong(op2)); } else if (n == 2) { /* Handle: op xmm,mem * where xmm is written only, not read */ code cs; if ((op1->Eoper == OPind && !op1->Ecount) || op1->Eoper == OPvar) { c = getlvalue(&cs, op1, RMload); // get addressing mode } else { regm_t rretregs = XMMREGS; c = codelem(op1, &rretregs, FALSE); unsigned rreg = findreg(rretregs) - XMM0; cs.Irm = modregrm(3,0,rreg & 7); cs.Iflags = 0; cs.Irex = 0; if (rreg & 8) cs.Irex |= REX_B; } retregs = *pretregs & XMMREGS; if (!retregs) retregs = XMMREGS; unsigned reg; cr = CNIL; cg = allocreg(&retregs, ®, e->Ety); code_newreg(&cs, reg - XMM0); cs.Iop = op; co = gen(CNIL,&cs); } else if (n == 3 || n == 4) { /* Handle: * op xmm,mem // n = 3 * op xmm,mem,imm8 // n = 4 * Both xmm and mem are operands, evaluate xmm first. */ code cs; retregs = *pretregs & XMMREGS; if (!retregs) retregs = XMMREGS; c = codelem(op1,&retregs,FALSE); // eval left leaf unsigned reg = findreg(retregs); if ((op2->Eoper == OPind && !op2->Ecount) || op2->Eoper == OPvar) { cr = getlvalue(&cs, op2, RMload | retregs); // get addressing mode } else { unsigned rretregs = XMMREGS & ~retregs; cr = scodelem(op2, &rretregs, retregs, TRUE); unsigned rreg = findreg(rretregs) - XMM0; cs.Irm = modregrm(3,0,rreg & 7); cs.Iflags = 0; cs.Irex = 0; if (rreg & 8) cs.Irex |= REX_B; } cg = getregs(retregs); if (n == 4) { switch (op) { case CMPPD: case CMPSS: case CMPSD: case CMPPS: case PSHUFD: case PSHUFHW: case PSHUFLW: case BLENDPD: case BLENDPS: case DPPD: case DPPS: case MPSADBW: case PBLENDW: case ROUNDPD: case ROUNDPS: case ROUNDSD: case ROUNDSS: case SHUFPD: case SHUFPS: break; default: printf("op = x%x\n", op); assert(0); break; } elem *imm8 = params[3]; cs.IFL2 = FLconst; cs.IEV2.Vsize_t = el_tolong(imm8); } code_newreg(&cs, reg - XMM0); cs.Iop = op; co = gen(CNIL,&cs); } else assert(0); co = cat(co,fixresult(e,retregs,pretregs)); free(params); freenode(e); return cat4(c,cr,cg,co); }
code *xmmopass(elem *e,regm_t *pretregs) { elem *e1 = e->E1; elem *e2 = e->E2; tym_t ty1 = tybasic(e1->Ety); unsigned sz1 = tysize[ty1]; regm_t rretregs = XMMREGS & ~*pretregs; if (!rretregs) rretregs = XMMREGS; code *cr = codelem(e2,&rretregs,FALSE); // eval right leaf unsigned rreg = findreg(rretregs); code cs; code *cl,*cg; regm_t retregs; unsigned reg; bool regvar = FALSE; if (config.flags4 & CFG4optimized) { // Be careful of cases like (x = x+x+x). We cannot evaluate in // x if x is in a register. unsigned varreg; regm_t varregm; if (isregvar(e1,&varregm,&varreg) && // if lvalue is register variable doinreg(e1->EV.sp.Vsym,e2) // and we can compute directly into it ) { regvar = TRUE; retregs = varregm; reg = varreg; // evaluate directly in target register cl = NULL; cg = getregs(retregs); // destroy these regs } } if (!regvar) { cl = getlvalue(&cs,e1,rretregs); // get EA retregs = *pretregs & XMMREGS & ~rretregs; if (!retregs) retregs = XMMREGS & ~rretregs; cg = allocreg(&retregs,®,ty1); cs.Iop = xmmload(ty1); // MOVSD xmm,xmm_m64 code_newreg(&cs,reg - XMM0); cg = gen(cg,&cs); } unsigned op = xmmoperator(e1->Ety, e->Eoper); code *co = gen2(CNIL,op,modregxrmx(3,reg-XMM0,rreg-XMM0)); if (!regvar) { cs.Iop = xmmstore(ty1); // reverse operand order of MOVS[SD] gen(co,&cs); } if (e1->Ecount || // if lvalue is a CSE or regvar) // rvalue can't be a CSE { cl = cat(cl,getregs_imm(retregs)); // necessary if both lvalue and // rvalue are CSEs (since a reg // can hold only one e at a time) cssave(e1,retregs,EOP(e1)); // if lvalue is a CSE } co = cat(co,fixresult(e,retregs,pretregs)); freenode(e1); return cat4(cr,cl,cg,co); }
code *xmmeq(elem *e, unsigned op, elem *e1, elem *e2,regm_t *pretregs) { tym_t tymll; unsigned reg; int i; code *cl,*cr,*c,cs; elem *e11; bool regvar; /* TRUE means evaluate into register variable */ regm_t varregm; unsigned varreg; targ_int postinc; //printf("xmmeq(e1 = %p, e2 = %p, *pretregs = %s)\n", e1, e2, regm_str(*pretregs)); int e2oper = e2->Eoper; tym_t tyml = tybasic(e1->Ety); /* type of lvalue */ regm_t retregs = *pretregs; if (!(retregs & XMMREGS)) retregs = XMMREGS; // pick any XMM reg cs.Iop = (op == OPeq) ? xmmstore(tyml) : op; regvar = FALSE; varregm = 0; if (config.flags4 & CFG4optimized) { // Be careful of cases like (x = x+x+x). We cannot evaluate in // x if x is in a register. if (isregvar(e1,&varregm,&varreg) && // if lvalue is register variable doinreg(e1->EV.sp.Vsym,e2) // and we can compute directly into it ) { regvar = TRUE; retregs = varregm; reg = varreg; /* evaluate directly in target register */ } } if (*pretregs & mPSW && !EOP(e1)) // if evaluating e1 couldn't change flags { // Be careful that this lines up with jmpopcode() retregs |= mPSW; *pretregs &= ~mPSW; } cr = scodelem(e2,&retregs,0,TRUE); // get rvalue // Look for special case of (*p++ = ...), where p is a register variable if (e1->Eoper == OPind && ((e11 = e1->E1)->Eoper == OPpostinc || e11->Eoper == OPpostdec) && e11->E1->Eoper == OPvar && e11->E1->EV.sp.Vsym->Sfl == FLreg ) { postinc = e11->E2->EV.Vint; if (e11->Eoper == OPpostdec) postinc = -postinc; cl = getlvalue(&cs,e11,RMstore | retregs); freenode(e11->E2); } else { postinc = 0; cl = getlvalue(&cs,e1,RMstore | retregs); // get lvalue (cl == CNIL if regvar) } c = getregs_imm(varregm); reg = findreg(retregs & XMMREGS); cs.Irm |= modregrm(0,(reg - XMM0) & 7,0); if ((reg - XMM0) & 8) cs.Irex |= REX_R; // Do not generate mov from register onto itself if (!(regvar && reg == XMM0 + ((cs.Irm & 7) | (cs.Irex & REX_B ? 8 : 0)))) c = gen(c,&cs); // MOV EA+offset,reg if (e1->Ecount || // if lvalue is a CSE or regvar) // rvalue can't be a CSE { c = cat(c,getregs_imm(retregs)); // necessary if both lvalue and // rvalue are CSEs (since a reg // can hold only one e at a time) cssave(e1,retregs,EOP(e1)); // if lvalue is a CSE } c = cat4(cr,cl,c,fixresult(e,retregs,pretregs)); Lp: if (postinc) { int reg = findreg(idxregm(&cs)); if (*pretregs & mPSW) { // Use LEA to avoid touching the flags unsigned rm = cs.Irm & 7; if (cs.Irex & REX_B) rm |= 8; c = genc1(c,0x8D,buildModregrm(2,reg,rm),FLconst,postinc); if (tysize(e11->E1->Ety) == 8) code_orrex(c, REX_W); } else if (I64) { c = genc2(c,0x81,modregrmx(3,0,reg),postinc); if (tysize(e11->E1->Ety) == 8) code_orrex(c, REX_W); } else { if (postinc == 1) c = gen1(c,0x40 + reg); // INC reg else if (postinc == -(targ_int)1) c = gen1(c,0x48 + reg); // DEC reg else { c = genc2(c,0x81,modregrm(3,0,reg),postinc); } } } freenode(e1); return c; }