void *scratch_allocator_allocate(struct cel_allocator *allocator, uint32_t size, uint32_t align) { struct cel_allocator_scratch *a = (struct cel_allocator_scratch *) allocator; //CE_ASSERT("scratch", align % 4 == 0); size = ((size + 3) / 4) * 4; char *p = a->allocate; struct Header *h = (struct Header *) p; char *data = (char *) data_pointer(h, align); p = data + size; // Reached the end of the buffer, wrap around to the beginning. if (p > a->end) { h->size = (a->end - (char *) h) | 0x80000000u; p = a->begin; h = (struct Header *) p; data = (char *) data_pointer(h, align); p = data + size; } // If the buffer is exhausted use the backing allocator instead. if (in_use(a, p)) return CEL_ALLOCATE_ALIGN(a->backing, void, size, align); fill(h, data, p - (char *) h); a->allocate = p; return data; }
static data_pointer allocate(size_t size) { void *data = malloc(size); if (!data) throw std::bad_alloc(); return data_pointer(data, size); }
static Value *init_bits_value(Value *newv, Value *jt, Type *t, Value *v) { builder.CreateStore(jt, builder.CreateBitCast(newv, jl_ppvalue_llvmt)); builder.CreateStore(v , builder.CreateBitCast(data_pointer(newv), PointerType::get(t,0))); return newv; }
static void start_application(session &sess, const std::string &app_name) { key key_id = app_name; key_id.transform(sess); dnet_id id = key_id.id(); ELLIPTICS_REQUIRE(result, sess.exec(&id, app_name + "@start-task", data_pointer())); }
static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv, jl_value_t *argex, bool addressOf, int argn, jl_codectx_t *ctx, bool *mightNeedTempSpace, bool *needStackRestore) { Type *vt = jv->getType(); if (ty == jl_pvalue_llvmt) { return boxed(jv,ctx); } else if (ty == vt && !addressOf) { return jv; } else if (vt != jl_pvalue_llvmt) { // argument value is unboxed if (addressOf) { if (ty->isPointerTy() && ty->getContainedType(0)==vt) { // pass the address of an alloca'd thing, not a box // since those are immutable. *needStackRestore = true; Value *slot = builder.CreateAlloca(vt); builder.CreateStore(jv, slot); return builder.CreateBitCast(slot, ty); } } else if ((vt->isIntegerTy() && ty->isIntegerTy()) || (vt->isFloatingPointTy() && ty->isFloatingPointTy()) || (vt->isPointerTy() && ty->isPointerTy())) { if (vt->getPrimitiveSizeInBits() == ty->getPrimitiveSizeInBits()) { return builder.CreateBitCast(jv, ty); } } // error. box for error handling. jv = boxed(jv,ctx); } else if (jl_is_cpointer_type(jt)) { assert(ty->isPointerTy()); jl_value_t *aty = expr_type(argex, ctx); if (jl_is_array_type(aty) && (jl_tparam0(jt) == jl_tparam0(aty) || jl_tparam0(jt) == (jl_value_t*)jl_bottom_type)) { // array to pointer return builder.CreateBitCast(emit_arrayptr(jv), ty); } if (aty == (jl_value_t*)jl_ascii_string_type || aty == (jl_value_t*)jl_utf8_string_type) { return builder.CreateBitCast(emit_arrayptr(emit_nthptr(jv,1,tbaa_const)), ty); } if (jl_is_structtype(aty) && jl_is_leaf_type(aty) && !jl_is_array_type(aty)) { if (!addressOf) { emit_error("ccall: expected & on argument", ctx); return literal_pointer_val(jl_nothing); } return builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), ty); // skip type tag field } *mightNeedTempSpace = true; Value *p = builder.CreateCall4(prepare_call(value_to_pointer_func), literal_pointer_val(jl_tparam0(jt)), jv, ConstantInt::get(T_int32, argn), ConstantInt::get(T_int32, (int)addressOf)); return builder.CreateBitCast(p, ty); } else if (jl_is_structtype(jt)) { if (addressOf) jl_error("ccall: unexpected & on argument"); // the only "safe" thing to emit here is the expected struct assert (ty->isStructTy() && (Type*)((jl_datatype_t*)jt)->struct_decl == ty); jl_value_t *aty = expr_type(argex, ctx); if (aty != jt) { std::stringstream msg; msg << "ccall argument "; msg << argn; emit_typecheck(jv, jt, msg.str(), ctx); } //TODO: check instead that prefix matches //if (!jl_is_structtype(aty)) // emit_typecheck(emit_typeof(jv), (jl_value_t*)jl_struct_kind, "ccall: Struct argument called with something that isn't a struct", ctx); // //safe thing would be to also check that jl_typeof(aty)->size > sizeof(ty) here and/or at runtime Value *pjv = builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), PointerType::get(ty,0)); return builder.CreateLoad(pjv, false); } else if (jl_is_tuple(jt)) { return emit_unbox(ty,jv,jt); } // TODO: error for & with non-pointer argument type assert(jl_is_bitstype(jt)); std::stringstream msg; msg << "ccall argument "; msg << argn; emit_typecheck(jv, jt, msg.str(), ctx); Value *p = data_pointer(jv); return builder.CreateLoad(builder.CreateBitCast(p, PointerType::get(ty,0)), false); }
void SPC7110::mmio_write(unsigned addr, uint8 data) { addr &= 0xffff; switch(addr) { //================== //decompression unit //================== case 0x4801: r4801 = data; break; case 0x4802: r4802 = data; break; case 0x4803: r4803 = data; break; case 0x4804: r4804 = data; break; case 0x4805: r4805 = data; break; case 0x4806: { r4806 = data; unsigned table = (r4801 + (r4802 << 8) + (r4803 << 16)); unsigned index = (r4804 << 2); unsigned length = (r4809 + (r480a << 8)); unsigned addr = datarom_addr(table + index); unsigned mode = (cartridge.rom.read(addr + 0)); unsigned offset = (cartridge.rom.read(addr + 1) << 16) + (cartridge.rom.read(addr + 2) << 8) + (cartridge.rom.read(addr + 3) << 0); decomp.init(mode, offset, (r4805 + (r4806 << 8)) << mode); r480c = 0x80; } break; case 0x4807: r4807 = data; break; case 0x4808: r4808 = data; break; case 0x4809: r4809 = data; break; case 0x480a: r480a = data; break; case 0x480b: r480b = data; break; //============== //data port unit //============== case 0x4811: r4811 = data; r481x |= 0x01; break; case 0x4812: r4812 = data; r481x |= 0x02; break; case 0x4813: r4813 = data; r481x |= 0x04; break; case 0x4814: { r4814 = data; r4814_latch = true; if(!r4815_latch) break; if(!(r4818 & 2)) break; if(r4818 & 0x10) break; if((r4818 & 0x60) == 0x20) { unsigned increment = data_adjust() & 0xff; if(r4818 & 8) increment = (int8)increment; //8-bit sign extend set_data_pointer(data_pointer() + increment); } else if((r4818 & 0x60) == 0x40) { unsigned increment = data_adjust(); if(r4818 & 8) increment = (int16)increment; //16-bit sign extend set_data_pointer(data_pointer() + increment); } } break; case 0x4815: { r4815 = data; r4815_latch = true; if(!r4814_latch) break; if(!(r4818 & 2)) break; if(r4818 & 0x10) break; if((r4818 & 0x60) == 0x20) { unsigned increment = data_adjust() & 0xff; if(r4818 & 8) increment = (int8)increment; //8-bit sign extend set_data_pointer(data_pointer() + increment); } else if((r4818 & 0x60) == 0x40) { unsigned increment = data_adjust(); if(r4818 & 8) increment = (int16)increment; //16-bit sign extend set_data_pointer(data_pointer() + increment); } } break; case 0x4816: r4816 = data; break; case 0x4817: r4817 = data; break; case 0x4818: { if(r481x != 0x07) break; r4818 = data; r4814_latch = r4815_latch = false; } break; //========= //math unit //========= case 0x4820: r4820 = data; break; case 0x4821: r4821 = data; break; case 0x4822: r4822 = data; break; case 0x4823: r4823 = data; break; case 0x4824: r4824 = data; break; case 0x4825: { r4825 = data; if(r482e & 1) { //signed 16-bit x 16-bit multiplication int16 r0 = (int16)(r4824 + (r4825 << 8)); int16 r1 = (int16)(r4820 + (r4821 << 8)); signed result = r0 * r1; r4828 = result; r4829 = result >> 8; r482a = result >> 16; r482b = result >> 24; } else { //unsigned 16-bit x 16-bit multiplication uint16 r0 = (uint16)(r4824 + (r4825 << 8)); uint16 r1 = (uint16)(r4820 + (r4821 << 8)); unsigned result = r0 * r1; r4828 = result; r4829 = result >> 8; r482a = result >> 16; r482b = result >> 24; } r482f = 0x80; } break;
uint8 SPC7110::mmio_read(unsigned addr) { addr &= 0xffff; switch(addr) { //================== //decompression unit //================== case 0x4800: { uint16 counter = (r4809 + (r480a << 8)); counter--; r4809 = counter; r480a = counter >> 8; return decomp.read(); } case 0x4801: return r4801; case 0x4802: return r4802; case 0x4803: return r4803; case 0x4804: return r4804; case 0x4805: return r4805; case 0x4806: return r4806; case 0x4807: return r4807; case 0x4808: return r4808; case 0x4809: return r4809; case 0x480a: return r480a; case 0x480b: return r480b; case 0x480c: { uint8 status = r480c; r480c &= 0x7f; return status; } //============== //data port unit //============== case 0x4810: { if(r481x != 0x07) return 0x00; unsigned addr = data_pointer(); unsigned adjust = data_adjust(); if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend unsigned adjustaddr = addr; if(r4818 & 2) { adjustaddr += adjust; set_data_adjust(adjust + 1); } uint8 data = cartridge.rom.read(datarom_addr(adjustaddr)); if(!(r4818 & 2)) { unsigned increment = (r4818 & 1) ? data_increment() : 1; if(r4818 & 4) increment = (int16)increment; //16-bit sign extend if((r4818 & 16) == 0) { set_data_pointer(addr + increment); } else { set_data_adjust(adjust + increment); } } return data; } case 0x4811: return r4811; case 0x4812: return r4812; case 0x4813: return r4813; case 0x4814: return r4814; case 0x4815: return r4815; case 0x4816: return r4816; case 0x4817: return r4817; case 0x4818: return r4818; case 0x481a: { if(r481x != 0x07) return 0x00; unsigned addr = data_pointer(); unsigned adjust = data_adjust(); if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend uint8 data = cartridge.rom.read(datarom_addr(addr + adjust)); if((r4818 & 0x60) == 0x60) { if((r4818 & 16) == 0) { set_data_pointer(addr + adjust); } else { set_data_adjust(adjust + adjust); } } return data; } //========= //math unit //========= case 0x4820: return r4820; case 0x4821: return r4821; case 0x4822: return r4822; case 0x4823: return r4823; case 0x4824: return r4824; case 0x4825: return r4825; case 0x4826: return r4826; case 0x4827: return r4827; case 0x4828: return r4828; case 0x4829: return r4829; case 0x482a: return r482a; case 0x482b: return r482b; case 0x482c: return r482c; case 0x482d: return r482d; case 0x482e: return r482e; case 0x482f: { uint8 status = r482f; r482f &= 0x7f; return status; } //=================== //memory mapping unit //=================== case 0x4830: return r4830; case 0x4831: return r4831; case 0x4832: return r4832; case 0x4833: return r4833; case 0x4834: return r4834; //==================== //real-time clock unit //==================== case 0x4840: return r4840; case 0x4841: { if(rtc_state == RTCS_Inactive || rtc_state == RTCS_ModeSelect) return 0x00; r4842 = 0x80; uint8 data = rtc[rtc_index]; rtc_index = (rtc_index + 1) & 15; return data; } case 0x4842: { uint8 status = r4842; r4842 &= 0x7f; return status; } } return cpu.regs.mdr; }
static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv, jl_value_t *aty, bool addressOf, bool byRef, bool inReg, bool needCopy, int argn, jl_codectx_t *ctx, bool *needStackRestore) { Type *vt = jv->getType(); // We're passing any if (ty == jl_pvalue_llvmt) { return boxed(jv,ctx); } if (ty == vt && !addressOf && !byRef) { return jv; } if (vt != jl_pvalue_llvmt) { // argument value is unboxed if (addressOf || (byRef && inReg)) { if (ty->isPointerTy() && ty->getContainedType(0)==vt) { // pass the address of an alloca'd thing, not a box // since those are immutable. *needStackRestore = true; Value *slot = builder.CreateAlloca(vt); builder.CreateStore(jv, slot); return builder.CreateBitCast(slot, ty); } } else if ((vt->isIntegerTy() && ty->isIntegerTy()) || (vt->isFloatingPointTy() && ty->isFloatingPointTy()) || (vt->isPointerTy() && ty->isPointerTy())) { if (vt->getPrimitiveSizeInBits() == ty->getPrimitiveSizeInBits()) { if (!byRef) { return builder.CreateBitCast(jv, ty); } else { *needStackRestore = true; Value *mem = builder.CreateAlloca(ty); builder.CreateStore(jv,builder.CreateBitCast(mem,vt->getPointerTo())); return mem; } } } else if (vt->isStructTy()) { if (!byRef) { return jv; } else { *needStackRestore = true; Value *mem = builder.CreateAlloca(vt); builder.CreateStore(jv,mem); return mem; } } emit_error("ccall: argument type did not match declaration", ctx); } if (jl_is_tuple(jt)) { return emit_unbox(ty,jv,jt); } if (jl_is_cpointer_type(jt) && addressOf) { assert(ty->isPointerTy()); jl_value_t *ety = jl_tparam0(jt); if (aty != ety && ety != (jl_value_t*)jl_any_type && jt != (jl_value_t*)jl_voidpointer_type) { std::stringstream msg; msg << "ccall argument "; msg << argn; emit_typecheck(jv, ety, msg.str(), ctx); } if (jl_is_mutable_datatype(ety)) { // no copy, just reference the data field return builder.CreateBitCast(jv, ty); } else if (jl_is_immutable_datatype(ety) && jt != (jl_value_t*)jl_voidpointer_type) { // yes copy Value *nbytes; if (jl_is_leaf_type(ety)) nbytes = ConstantInt::get(T_int32, jl_datatype_size(ety)); else nbytes = tbaa_decorate(tbaa_datatype, builder.CreateLoad( builder.CreateGEP(builder.CreatePointerCast(emit_typeof(jv), T_pint32), ConstantInt::get(T_size, offsetof(jl_datatype_t,size)/sizeof(int32_t))), false)); *needStackRestore = true; AllocaInst *ai = builder.CreateAlloca(T_int8, nbytes); ai->setAlignment(16); builder.CreateMemCpy(ai, builder.CreateBitCast(jv, T_pint8), nbytes, 1); return builder.CreateBitCast(ai, ty); } // emit maybe copy *needStackRestore = true; Value *jvt = emit_typeof(jv); BasicBlock *mutableBB = BasicBlock::Create(getGlobalContext(),"is-mutable",ctx->f); BasicBlock *immutableBB = BasicBlock::Create(getGlobalContext(),"is-immutable",ctx->f); BasicBlock *afterBB = BasicBlock::Create(getGlobalContext(),"after",ctx->f); Value *ismutable = builder.CreateTrunc( tbaa_decorate(tbaa_datatype, builder.CreateLoad( builder.CreateGEP(builder.CreatePointerCast(jvt, T_pint8), ConstantInt::get(T_size, offsetof(jl_datatype_t,mutabl))), false)), T_int1); builder.CreateCondBr(ismutable, mutableBB, immutableBB); builder.SetInsertPoint(mutableBB); Value *p1 = builder.CreatePointerCast(jv, ty); builder.CreateBr(afterBB); builder.SetInsertPoint(immutableBB); Value *nbytes = tbaa_decorate(tbaa_datatype, builder.CreateLoad( builder.CreateGEP(builder.CreatePointerCast(jvt, T_pint32), ConstantInt::get(T_size, offsetof(jl_datatype_t,size)/sizeof(int32_t))), false)); AllocaInst *ai = builder.CreateAlloca(T_int8, nbytes); ai->setAlignment(16); builder.CreateMemCpy(ai, builder.CreatePointerCast(jv, T_pint8), nbytes, 1); Value *p2 = builder.CreatePointerCast(ai, ty); builder.CreateBr(afterBB); builder.SetInsertPoint(afterBB); PHINode *p = builder.CreatePHI(ty, 2); p->addIncoming(p1, mutableBB); p->addIncoming(p2, immutableBB); return p; } if (addressOf) jl_error("ccall: unexpected & on argument"); // the only "safe" thing to emit here is the expected struct assert(jl_is_datatype(jt)); if (aty != jt) { std::stringstream msg; msg << "ccall argument "; msg << argn; emit_typecheck(jv, jt, msg.str(), ctx); } Value *p = data_pointer(jv); Value *pjv = builder.CreatePointerCast(p, PointerType::get(ty,0)); if (byRef) { if (!needCopy) { return pjv; } else { *needStackRestore = true; Value *mem = builder.CreateAlloca(ty); builder.CreateMemCpy(mem,pjv,(uint64_t)jl_datatype_size(jt),(uint64_t)((jl_datatype_t*)jt)->alignment); return mem; } } else { return builder.CreateLoad(pjv,false); } }