llvm.org GIT mirror llvm / 1abac0d
Implement x86 long double in jit (not really complete, but common cases work) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42043 91177308-0d34-0410-b5e6-96231b3b80d8 Dale Johannesen 13 years ago
3 changed file(s) with 94 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
3030 struct { unsigned int first; unsigned int second; } UIntPairVal;
3131 unsigned char Untyped[8];
3232 };
33 APInt IntVal;
33 APInt IntVal; // also used for long doubles
3434
3535 GenericValue() : DoubleVal(0.0), IntVal(1,0) {}
3636 GenericValue(void *V) : PointerVal(V), IntVal(1,0) { }
375375 return GV;
376376 }
377377 case Instruction::FPTrunc: {
378 // FIXME long double
378379 GenericValue GV = getConstantValue(Op0);
379380 GV.FloatVal = float(GV.DoubleVal);
380381 return GV;
381382 }
382383 case Instruction::FPExt:{
384 // FIXME long double
383385 GenericValue GV = getConstantValue(Op0);
384386 GV.DoubleVal = double(GV.FloatVal);
385387 return GV;
388390 GenericValue GV = getConstantValue(Op0);
389391 if (CE->getType() == Type::FloatTy)
390392 GV.FloatVal = float(GV.IntVal.roundToDouble());
391 else
393 else if (CE->getType() == Type::DoubleTy)
392394 GV.DoubleVal = GV.IntVal.roundToDouble();
395 else if (CE->getType() == Type::X86_FP80Ty) {
396 const uint64_t zero[] = {0, 0};
397 APFloat apf = APFloat(APInt(80, 2, zero));
398 (void)apf.convertFromInteger(GV.IntVal.getRawData(), 2, false,
399 APFloat::rmTowardZero);
400 GV.IntVal = apf.convertToAPInt();
401 }
393402 return GV;
394403 }
395404 case Instruction::SIToFP: {
396405 GenericValue GV = getConstantValue(Op0);
397406 if (CE->getType() == Type::FloatTy)
398407 GV.FloatVal = float(GV.IntVal.signedRoundToDouble());
399 else
408 else if (CE->getType() == Type::DoubleTy)
400409 GV.DoubleVal = GV.IntVal.signedRoundToDouble();
410 else if (CE->getType() == Type::X86_FP80Ty) {
411 const uint64_t zero[] = { 0, 0};
412 APFloat apf = APFloat(APInt(80, 2, zero));
413 (void)apf.convertFromInteger(GV.IntVal.getRawData(), 2, true,
414 APFloat::rmTowardZero);
415 GV.IntVal = apf.convertToAPInt();
416 }
401417 return GV;
402418 }
403419 case Instruction::FPToUI: // double->APInt conversion handles sign
406422 uint32_t BitWidth = cast(CE->getType())->getBitWidth();
407423 if (Op0->getType() == Type::FloatTy)
408424 GV.IntVal = APIntOps::RoundFloatToAPInt(GV.FloatVal, BitWidth);
409 else
425 else if (Op0->getType() == Type::DoubleTy)
410426 GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth);
427 else if (Op0->getType() == Type::X86_FP80Ty) {
428 APFloat apf = APFloat(GV.IntVal);
429 uint64_t v;
430 (void)apf.convertToInteger(&v, BitWidth,
431 CE->getOpcode()==Instruction::FPToSI,
432 APFloat::rmTowardZero);
433 GV.IntVal = v; // endian?
434 }
411435 return GV;
412436 }
413437 case Instruction::PtrToInt: {
511535 GV.DoubleVal = ::fmod(LHS.DoubleVal,RHS.DoubleVal); break;
512536 }
513537 break;
538 case Type::X86_FP80TyID:
539 case Type::PPC_FP128TyID:
540 case Type::FP128TyID: {
541 APFloat apfLHS = APFloat(LHS.IntVal);
542 switch (CE->getOpcode()) {
543 default: assert(0 && "Invalid long double opcode"); abort();
544 case Instruction::Add:
545 apfLHS.add(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
546 GV.IntVal = apfLHS.convertToAPInt();
547 break;
548 case Instruction::Sub:
549 apfLHS.subtract(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
550 GV.IntVal = apfLHS.convertToAPInt();
551 break;
552 case Instruction::Mul:
553 apfLHS.multiply(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
554 GV.IntVal = apfLHS.convertToAPInt();
555 break;
556 case Instruction::FDiv:
557 apfLHS.divide(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
558 GV.IntVal = apfLHS.convertToAPInt();
559 break;
560 case Instruction::FRem:
561 apfLHS.mod(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
562 GV.IntVal = apfLHS.convertToAPInt();
563 break;
564 }
565 }
566 break;
514567 }
515568 return GV;
516569 }
528581 break;
529582 case Type::DoubleTyID:
530583 Result.DoubleVal = cast(C)->getValueAPF().convertToDouble();
584 break;
585 case Type::X86_FP80TyID:
586 case Type::FP128TyID:
587 case Type::PPC_FP128TyID:
588 Result.IntVal = cast (C)->getValueAPF().convertToAPInt();
531589 break;
532590 case Type::IntegerTyID:
533591 Result.IntVal = cast(C)->getValue();
582640 case Type::DoubleTyID:
583641 *((double*)Ptr) = Val.DoubleVal;
584642 break;
643 case Type::X86_FP80TyID: {
644 uint16_t *Dest = (uint16_t*)Ptr;
645 const uint16_t *Src = (uint16_t*)Val.IntVal.getRawData();
646 // This is endian dependent, but it will only work on x86 anyway.
647 Dest[0] = Src[4];
648 Dest[1] = Src[0];
649 Dest[2] = Src[1];
650 Dest[3] = Src[2];
651 Dest[4] = Src[3];
652 break;
653 }
585654 case Type::PointerTyID:
586655 *((PointerTy*)Ptr) = Val.PointerVal;
587656 break;
619688 case Type::PointerTyID:
620689 Result.PointerVal = *((PointerTy*)Ptr);
621690 break;
691 case Type::X86_FP80TyID: {
692 // This is endian dependent, but it will only work on x86 anyway.
693 uint16_t x[8], *p = (uint16_t*)Ptr;
694 x[0] = p[1];
695 x[1] = p[2];
696 x[2] = p[3];
697 x[3] = p[4];
698 x[4] = p[0];
699 Result.IntVal = APInt(80, 2, x);
700 break;
701 }
622702 default:
623703 cerr << "Cannot load value of type " << *Ty << "!\n";
624704 abort();
177177 case Type::DoubleTyID:
178178 rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
179179 return rv;
180 case Type::X86_FP80TyID:
181 case Type::FP128TyID:
182 case Type::PPC_FP128TyID:
183 assert(0 && "long double not supported yet");
184 return rv;
180185 case Type::PointerTyID:
181186 return PTOGV(((void*(*)())(intptr_t)FPtr)());
182187 }
208213 case Type::FloatTyID: C = ConstantFP ::get(ArgTy, APFloat(AV.FloatVal));
209214 break;
210215 case Type::DoubleTyID: C = ConstantFP ::get(ArgTy, APFloat(AV.DoubleVal));
211 break;
216 break;
217 case Type::PPC_FP128TyID:
218 case Type::X86_FP80TyID:
219 case Type::FP128TyID: C = ConstantFP ::get(ArgTy, APFloat(AV.IntVal));
220 break;
212221 case Type::PointerTyID:
213222 void *ArgPtr = GVTOP(AV);
214223 if (sizeof(void*) == 4) {