/* Register device that userspace will read to store results in log file */ int vmon_p_init(dev_t dev) { int result, devno; prolog (""); vmon_p_devno = dev; vmon_p_devices = \ kmalloc(VMON_P_NR_DEVS * sizeof(struct vmon_pipe), GFP_KERNEL); if (vmon_p_devices == NULL) { critical ( "vmon_pipe couldn't be allocated!" ); unregister_chrdev_region(dev, VMON_P_NR_DEVS); return 0; } prolog ( "vmon_p_devices=0x%p", vmon_p_devices ); memset(vmon_p_devices, 0, VMON_P_NR_DEVS * sizeof(struct vmon_pipe)); init_waitqueue_head(&vmon_p_devices->buffer_wait); vmon_p_devices->buffer_watershed = VMON_P_BUFFER_WATERSHED; if (vmon_p_devices->buffer_watershed >= VMON_P_BUFFERSIZE) return -EINVAL; if (!vmon_p_devices->buffer) { /* * kmalloc (kernel) * allocates contiguous memory, up to 128KB * vmalloc (virtual) * allocates non continuous memory, can go above 128KB */ vmon_p_devices->buffer = \ kmalloc(sizeof(u64) * VMON_P_BUFFERSIZE, GFP_KERNEL); if (!vmon_p_devices->buffer) { critical ( "couldn't allocate vmon_p_buffer!" ); return -ENOMEM; } } prolog ( "vmon_p_devices->buffer=0x%p", vmon_p_devices->buffer ); vmon_p_devices->buffersize = VMON_P_BUFFERSIZE; devno = MKDEV(vmon_major, vmon_minor + 0); cdev_init(&vmon_p_devices->cdev, &vmon_pipe_fops); vmon_p_devices->cdev.owner = THIS_MODULE; result = cdev_add (&vmon_p_devices->cdev, devno, 1); /* Fail gracefully if need be */ if (result) critical ("error %d adding /dev/vmon", result); epilog ( "device vmon major=%d, minor=%d", vmon_major, vmon_minor ); return result; }
procode(FILE *outfile) #endif { prolog(outfile, allargs); if (nentry > 1) entry_goto(outfile); }
void MacroMain(int argc, char *argv[]) { prolog(0); // No local variables. push(argv[1]); // Push <fileName>. call(MacroDisplayFileContent());// Call <MacroDisplayFileContent()>. epilog(8); // Pop <argc> & <argv> parameters (8 bytes). }
static int vmon_p_release(struct inode *inode, struct file *filp) { struct vmon_pipe *dev = filp->private_data; prolog (""); clear_bit(0, &dev->buffer_opened); return 0; }
static fn_decl(stream, name, decl, block, frame_sz) { auto ret = new_label(); start_fn(decl); prolog(stream, name, frame_sz); do_block(stream, block, -1, -1, ret); emit_label( stream, ret ); epilog(stream, frame_sz); end_fn(); }
static void p9_xos_start_write_pump(unsigned long int data) { struct p9_xos_driver *drv = (struct p9_xos_driver *)data; prolog("d=%p", drv); if (!test_and_set_bit(WE_BIT, &drv->state)) queue_work(drv->workqueue, &drv->wwork); epilog(); }
int main(int argc, char **argv) { FILE *ofp = stdout; size_t num = 0; size_t scans_per_patch, bytes_per_patch; size_t y; outwidth = outheight = DEFAULT_SIZE; if (!get_args(argc, argv)) { (void)fputs(usage, stderr); bu_exit (1, NULL); } if (encapsulated) { xpoints = width; ypoints = height; } else { xpoints = outwidth * 72 + 0.5; ypoints = outheight * 72 + 0.5; } prolog(ofp, file_name, xpoints, ypoints); scans_per_patch = MAX_BYTES / width; if (scans_per_patch > height) scans_per_patch = height; bytes_per_patch = scans_per_patch * width; for (y = 0; y < height; y += scans_per_patch) { /* start a patch */ fprintf(ofp, "save\n"); fprintf(ofp, "%lu %lu 8 [%lu 0 0 %lu 0 %lu] {<\n ", (unsigned long)width, (unsigned long)scans_per_patch, /* patch size */ (unsigned long)width, (unsigned long)height, /* total size = 1.0 */ (unsigned long)-y); /* patch y origin */ /* data */ num = 0; while (num < bytes_per_patch) { fprintf(ofp, "%02x", getc(infp)); if ((++num % 32) == 0) fprintf(ofp, "\n "); } /* close this patch */ fprintf(ofp, ">} image\n"); fprintf(ofp, "restore\n"); } postlog(ofp); return 0; }
static void p9_xos_close(struct p9_client *client) { struct p9_xos_device *device; prolog("c=%p", client); client->status = Disconnected; device = (struct p9_xos_device *)client->conn; device->client = NULL; device->c_name[0] = 0; epilog(); }
static void p9_xos_flow(unsigned int event, void *cookie) { struct p9_xos_driver *drv = cookie; struct p9_xos_endpoint *ep; unsigned long flags; long int state = 0; prolog("e=%u c=%p", event, cookie); hw_raw_local_irq_save(flags); BUG_ON(event != 0); /* get empty packets */ ep = &drv->ep[WR_EP]; p9_xos_deque_move(ep->lqueue, &ep->regs[LHEAD], ep); if (ep->regs[STARVATION]) { /* Linux needs empty packets */ ep->regs[STARVATION] = 0; set_bit(MUST_WRITE, &state); } /* get data */ ep = &drv->ep[RD_EP]; p9_xos_deque_move(ep->lqueue, &ep->regs[LHEAD], ep); if (ep->regs[STARVATION]) { /* RTK needs empty packets */ drv->wake_status = 2; set_bit(MUST_SYNC, &state); } if (deque_head(ep->lqueue) != deque_null) { drv->wake_status = 2; set_bit(MUST_READ, &state); } hw_raw_local_irq_restore(flags); if (test_bit(MUST_SYNC, &state)) queue_work(drv->workqueue, &drv->swork); if (test_bit(MUST_WRITE, &state)) queue_work(drv->workqueue, &drv->wwork); if (test_bit(MUST_READ, &state)) queue_work(drv->workqueue, &drv->rwork); if (drv->wake_status == 2) wake_lock(&drv->wake_lock); epilog(); }
/* * This is called whenever a process attempts to open the device file */ static int vmon_p_open(struct inode *inode, struct file *filp) { struct vmon_pipe *dev; /* device information */ prolog (""); dev = container_of(inode->i_cdev, struct vmon_pipe, cdev); filp->private_data = dev; /* for other methods */ /* one open allowed, no reason to have more */ if (test_and_set_bit(0, &dev->buffer_opened)) return -EBUSY; return nonseekable_open(inode, filp); }
static void p9_xos_init(unsigned int event, void *cookie) { struct p9_xos_driver *drv = cookie; prolog("e=%u c=%p", event, cookie); if (drv->ep[event].regs[FAIL]) panic("9P2000 inter-OS transport initialization failed"); if (event) xos_ctrl_unregister(drv->ctrl, event); else xos_ctrl_register(drv->ctrl, P9_XOS_EVENT, p9_xos_flow, drv, 0); epilog(); }
void MacroDisplayFileContent(/*const char* fileName*/) { prolog(16); // 16 bytes in local variables. memset(var(16), 0, 16); // char content[16] = { 0 }; push(var(16)); // Push <content>. push(param(0)); // Push <fileName>. call(LoadFile()); // Call <LoadFile()>. push(var(16)); // Push <content>. push("Content: '%s'\n"); // Push <format>. call(Print()); // Call <Print()>. epilog(4); // Pop <fileName> parameter (4 bytes). }
int WinMainCRTStartup() // -mwindows { TraceFunc(); prolog(); STARTUPINFOW startupInfo; ::RtlSecureZeroMemory(&startupInfo, sizeof(startupInfo)); startupInfo.cb = sizeof(startupInfo); ::GetStartupInfoW(&startupInfo); int ret = wWinMain(::GetModuleHandleW(nullptr), nullptr, ::GetCommandLineW(), startupInfo.dwFlags & STARTF_USESHOWWINDOW ? startupInfo.wShowWindow : SW_SHOWDEFAULT); TraceFunc(); return epilog(ret); }
int mainCRTStartup() { TraceFunc(); prolog(); int argc = 0; wchar_t ** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); int ret = wmain(argc, argv); ::LocalFree(argv); TraceFunc(); return epilog(ret); }
static int p9_xos_parse_opts(char *params, struct p9_xos_device *device) { enum { opt_latency, opt_err, }; static match_table_t tokens = { {opt_latency, "latency=%u"}, {opt_err, NULL}, }; int retval = 0; char *options, *tmp_options, *p; prolog("p=%s c=%p", params, device); tmp_options = kstrdup(params, GFP_KERNEL); if (NULL == tmp_options) { retval = -ENOMEM; goto done; } options = tmp_options; while ((p = strsep(&options, ",")) != NULL) { int token, option; substring_t args[MAX_OPT_ARGS]; if (!*p) continue; token = match_token(p, tokens, args); switch (token) { case opt_latency: if (!match_int(&args[0], &option)) device->latency = msecs_to_jiffies(option); else warning("ignoring malformed latency option"); break; default: break; } } kfree(tmp_options); done: epilog("%d", retval); return retval; }
static int p9_xos_create(struct p9_client *client, const char *addr, char *args) { struct p9_xos_device *device = NULL; /* avoid compiler warning */ unsigned int id; int error; prolog("c=%p a=%s a=%s", client, addr, args); if (unlikely(!addr)) addr = "anonymous"; id = ARRAY_SIZE(driver.device); spin_lock(&driver.c_lock); while (id--) { device = &driver.device[id]; if (device->client == NULL) { device->client = client; break; } } spin_unlock(&driver.c_lock); if (id > ARRAY_SIZE(driver.device)) { error = -ENOMEM; goto bail_out; } strncpy(device->c_name, addr, ARRAY_SIZE(device->c_name) - 1); device->c_name[ARRAY_SIZE(device->c_name) - 1] = 0; client->status = Connected; client->conn = (struct p9_conn *)device; device->latency = 0; error = p9_xos_parse_opts(args, device); if (error) warning("bad options for client '%s' (%d)", addr, error); info("client '%s' got device %u", addr, id); error = 0; bail_out: epilog("%d", error); return error; }
static int p9_xos_request(struct p9_client *client, struct p9_req_t *req) { int retval = 0; struct p9_xos_device *device; struct p9_xos_driver *drv; prolog("c=%p r=%p", client, req); device = (struct p9_xos_device *)client->conn; drv = device->driver; req->aux = device; p9_xos_add_write_request(req, device->latency); epilog("%d", retval); return retval; }
/* * This is called whenever a process attempts to read the device file */ static ssize_t vmon_p_read(struct file *filp, \ char __user *buf, size_t count, loff_t *f_pos) { struct vmon_pipe *dev = filp->private_data; int retval = -EINVAL; size_t const max = dev->buffersize * sizeof(unsigned long long); prolog (""); /* handling partial reads is more trouble than it's worth */ if (count != max || *f_pos) return -EINVAL; wait_event_interruptible(dev->buffer_wait, atomic_read(&buffer_ready)); if (signal_pending(current)) return -EINTR; /* can't currently happen */ if (!atomic_read(&buffer_ready)) return -EAGAIN; mutex_lock(&buffer_mutex); atomic_set(&buffer_ready, 0); retval = -EFAULT; /* buffer_pos unit is unsigned long (4Bytes) * count unit is Bytes */ count = dev->buffer_pos * sizeof(unsigned long long); if (copy_to_user(buf, dev->buffer, count)) goto out; epilog("\"%s\" did read %li bytes\n", current->comm, (long long)count); /* we expect the user always reads the entire buffer */ retval = count; dev->buffer_pos = 0; out: mutex_unlock(&buffer_mutex); epilog (""); return retval; }
/** * called by vmon thread to fill buffer * results will be written on output file * * @return bytes written */ ssize_t vmon_write_to_buffer(unsigned long long sample) { struct vmon_pipe *dev = vmon_p_devices; prolog ( "dev->buffer=0x%p", dev->buffer ); /* FIXME: is mutex lock enough to access vmon_p_devices safely? */ if (dev->buffer_pos == dev->buffersize) { /* do we need a wait_interruptible(kthread) in this case? */ critical ( "overflow! position=%d", dev->buffer_pos ); return 0; } dev->buffer[dev->buffer_pos] = sample; if (++(dev->buffer_pos) == dev->buffersize - dev->buffer_watershed) { atomic_set(&buffer_ready, 1); wake_up(&dev->buffer_wait); } return sizeof(unsigned long long); }
/* * This is called by cleanup_module or on failure. * It is required to never fail, even if nothing was initialized first */ void vmon_p_cleanup(void) { prolog (""); if (!vmon_p_devices) { critical ( "vmon_p_devices already freed!" ); return; /* nothing else to release */ } if (!vmon_p_devices->buffer) { kfree(vmon_p_devices->buffer); vmon_p_devices->buffer = NULL; } vmon_p_devices->buffer_pos = 0; atomic_set(&buffer_ready, 0); cdev_del(&vmon_p_devices->cdev); kfree(vmon_p_devices->buffer); kfree(vmon_p_devices); unregister_chrdev_region(vmon_p_devno, VMON_P_NR_DEVS); vmon_p_devices = NULL; /* pedantic */ epilog (""); }
static void p9_xos_sync_work(struct work_struct *work) { struct p9_xos_driver *drv; struct p9_xos_endpoint *ep; unsigned long flags; prolog("w=%p", work); drv = container_of(work, struct p9_xos_driver, swork); /* send data */ ep = &drv->ep[WR_EP]; hw_raw_local_irq_save(flags); p9_xos_deque_move(&ep->regs[RHEAD], ep->rqueue, ep); hw_raw_local_irq_restore(flags); /* send empty packets if needed */ ep = &drv->ep[RD_EP]; if (nb_free_packets >= MIN_PACKETS_TO_RELEASE || ep->regs[STARVATION]) { nb_free_packets = 0; hw_raw_local_irq_save(flags); p9_xos_deque_move(&ep->regs[RHEAD], ep->rqueue, ep); hw_raw_local_irq_restore(flags); } xos_ctrl_raise(drv->ctrl, P9_XOS_EVENT); if ((!drv->wake_count) && (drv->wake_status == 1)) { drv->wake_status = 0; wake_unlock(&drv->wake_lock); wmb(); if (drv->wake_status == 2) wake_lock(&drv->wake_lock); } epilog(); }
void operativeMachine::startElement (const XMLCh * const name, AttributeList & attributes) { output_signal toDo; // controlMachine's command string gxl_element = a2b::XMLChar2string (name); // string with the element name if (gxl_element == "gxl") cm.setState (start_gxl); else { try { // astVerbosity output if (astVerbosity) cout << "Reading begin of gxl element " << gxl_element << "...\n"; // Is legal element recognized by XOgastan ? // Remember : <bool>, <set>, and so on ... are not // recognized by XOgastan if (start2input.find(gxl_element) != start2input.end()) toDo = whatWeDo (start2input[gxl_element]); else throw bad_XOgastan ("operativeMachine", "Unexpected gxl element : #" + gxl_element + "#"); switch (toDo) { case BEGIN_build: prolog (); break; case BEGIN_build_node: // get the node INDEX, and memorize it in c_node_index c_node_index = getGXLindex(a2b::XMLChar2string(attributes.getValue ("id"))); break; case BEGIN_build_edge: c_gep = new gxl_edge; // get the FROM index, and set it c_gep->setFrom ( getGXLindex(a2b::XMLChar2string(attributes.getValue("from"))) ); // get the TO index, and set it c_gep->setTo ( getGXLindex (a2b::XMLChar2string (attributes.getValue ("to"))) ); break; case BEGIN_build_attr: // get the NAME, and set it c_ga.setName (a2b::XMLChar2string (attributes.getValue ("name"))); break; case BEGIN_build_int: c_ga.setType (gxl_attr::intType); // set the TYPE of the attr break; case BEGIN_build_string: c_ga.setType (gxl_attr::stringType); // set the TYPE of the attr break; case BEGIN_build_type: // get the NAME of the TYPE, and set it c_type = getGXLtype (a2b::XMLChar2string (attributes.getValue ("xlink:href"))); break; } } catch (bad_XOgastan & b) { throw bad_factory (b.getBaseMessage (), b.getOtherMessage ()); } catch (...) { throw bad_factory ("operativeMachine", "Unknown event !"); } } return; }
static void p9_xos_read_work(struct work_struct *work) { struct p9_xos_driver *drv; struct p9_xos_endpoint *ep; int n; unsigned long flags; prolog("w=%p", work); drv = container_of(work, struct p9_xos_driver, rwork); ep = &drv->ep[RD_EP]; drv->wake_status = 1; spin_lock_irqsave(&drv->ep_lock, flags); n = p9_xos_deque_pop(ep->lqueue, ep); spin_unlock_irqrestore(&drv->ep_lock, flags); if (n == deque_null) goto done; do { u16 tag; int id; unsigned int size; struct p9_xos_device *device; struct p9_req_t *req; u8 *ptr; u8 type; ptr = n2a(n, ep) + 4; id = *(int *)ptr; ptr += 4; size = le32_to_cpu(*(__le32 *) ptr); if (size < 7) { critical("ignoring too short request"); break; } type = *(ptr + 4); __log_event(drv, id, type, RD_EP); device = &drv->device[id]; if (type & 1) { if (size >= device->client->msize) { warning("requested packet size too big: %d\n", size); goto ignore; } tag = le16_to_cpu(*(__le16 *) (ptr + 5)); req = p9_tag_lookup(device->client, tag); if (req == NULL) { warning("ignoring unexpected response"); goto ignore; } BUG_ON(!req->rc); if (likely(req->aio_cb != NULL)) { req->rc->sdata = ptr; req->status = REQ_STATUS_RCVD; p9_client_notify_aio(device->client, req); } else { req->rc->sdata = (char *)req->rc + sizeof(*req->rc); memcpy(req->rc->sdata, ptr, size); p9_client_cb(device->client, req); } ignore: spin_lock_irqsave(&drv->ep_lock, flags); p9_xos_deque_push(ep->rqueue, n, ep); nb_free_packets++; spin_unlock_irqrestore(&drv->ep_lock, flags); } else { /* * Dirty hack for pmu_int server * pmu_int is on channel 1 * pmu_int client has always a request pending * so does not keep the wake lock if only * pmu_int request pending */ if (likely(device != &drv->device[1])) drv->wake_count++; if (unlikely(!device->open)) { warning("DEVICE %d NOT OPENED, ignoring req", device->id); goto ignore2; } req = kmem_cache_alloc(drv->cache, GFP_KERNEL); req->tc = kmalloc(sizeof(struct p9_fcall), GFP_KERNEL); req->tc->size = size; req->tc->sdata = ptr; req->aux = device; spin_lock(&device->lock); list_add_tail(&req->req_list, &device->req_list); spin_unlock(&device->lock); if (device->rd_cb) device->rd_cb(device, req); } ignore2: spin_lock_irqsave(&drv->ep_lock, flags); n = p9_xos_deque_pop(ep->lqueue, ep); spin_unlock_irqrestore(&drv->ep_lock, flags); } while (n != deque_null); done: if ((!drv->wake_count) && (drv->wake_status == 1)) { drv->wake_status = 0; wake_unlock(&drv->wake_lock); wmb(); if (drv->wake_status == 2) wake_lock(&drv->wake_lock); } epilog(); }
static void p9_xos_write_work(struct work_struct *work) { struct p9_xos_driver *drv; struct p9_xos_endpoint *ep; unsigned long flags; prolog("w=%p", work); drv = container_of(work, struct p9_xos_driver, wwork); ep = &drv->ep[WR_EP]; spin_lock(&drv->q_lock); if (list_empty(&drv->req_list)) { clear_bit(WE_BIT, &drv->state); spin_unlock(&drv->q_lock); goto done; } spin_unlock(&drv->q_lock); do { u8 *ptr; struct p9_req_t *req; struct p9_xos_device *device; int n; req = list_first_entry(&drv->req_list, struct p9_req_t, req_list); spin_lock_irqsave(&drv->ep_lock, flags); n = p9_xos_deque_pop(ep->lqueue, ep); spin_unlock_irqrestore(&drv->ep_lock, flags); if (n == deque_null) { ep->regs[STARVATION] = 1; break; } ptr = n2a(n, ep) + 4; device = req->aux; spin_lock(&drv->q_lock); list_del(&req->req_list); req->status = REQ_STATUS_SENT; spin_unlock(&drv->q_lock); *(unsigned int *)ptr = device->id; ptr += 4; if (req->tc) { memcpy(ptr, req->tc->sdata, req->tc->size); } else { memcpy(ptr, req->rc->sdata, req->rc->size); spin_lock(&device->lock); BUG_ON(!device->ack_count); device->ack_count -= 1; /* * Dirty hack for pmu_int server * pmu_int is on channel 1 * pmu_int client has always a request pending * so does not keep the wake lock if only * pmu_int request pending */ if (likely(device != &drv->device[1])) drv->wake_count--; if (device->wr_cb) device->wr_cb(device, req); kmem_cache_free(drv->cache, req); spin_unlock(&device->lock); } __log_event(drv, device->id, ptr[4], WR_EP); spin_lock_irqsave(&drv->ep_lock, flags); p9_xos_deque_push(ep->rqueue, n, ep); spin_unlock_irqrestore(&drv->ep_lock, flags); } while (!list_empty(&drv->req_list)); queue_work(drv->workqueue, &drv->swork); done: clear_bit(WE_BIT, &drv->state); epilog(); }
int GGLAssembler::scanline_core(const needs_t& needs, context_t const* c) { int64_t duration = ggl_system_time(); mBlendFactorCached = 0; mBlending = 0; mMasking = 0; mAA = GGL_READ_NEEDS(P_AA, needs.p); mDithering = GGL_READ_NEEDS(P_DITHER, needs.p); mAlphaTest = GGL_READ_NEEDS(P_ALPHA_TEST, needs.p) + GGL_NEVER; mDepthTest = GGL_READ_NEEDS(P_DEPTH_TEST, needs.p) + GGL_NEVER; mFog = GGL_READ_NEEDS(P_FOG, needs.p) != 0; mSmooth = GGL_READ_NEEDS(SHADE, needs.n) != 0; mBuilderContext.needs = needs; mBuilderContext.c = c; mBuilderContext.Rctx = reserveReg(R0); // context always in R0 mCbFormat = c->formats[ GGL_READ_NEEDS(CB_FORMAT, needs.n) ]; // ------------------------------------------------------------------------ decodeLogicOpNeeds(needs); decodeTMUNeeds(needs, c); mBlendSrc = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_SRC, needs.n)); mBlendDst = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_DST, needs.n)); mBlendSrcA = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_SRCA, needs.n)); mBlendDstA = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_DSTA, needs.n)); if (!mCbFormat.c[GGLFormat::ALPHA].h) { if ((mBlendSrc == GGL_ONE_MINUS_DST_ALPHA) || (mBlendSrc == GGL_DST_ALPHA)) { mBlendSrc = GGL_ONE; } if ((mBlendSrcA == GGL_ONE_MINUS_DST_ALPHA) || (mBlendSrcA == GGL_DST_ALPHA)) { mBlendSrcA = GGL_ONE; } if ((mBlendDst == GGL_ONE_MINUS_DST_ALPHA) || (mBlendDst == GGL_DST_ALPHA)) { mBlendDst = GGL_ONE; } if ((mBlendDstA == GGL_ONE_MINUS_DST_ALPHA) || (mBlendDstA == GGL_DST_ALPHA)) { mBlendDstA = GGL_ONE; } } // if we need the framebuffer, read it now const int blending = blending_codes(mBlendSrc, mBlendDst) | blending_codes(mBlendSrcA, mBlendDstA); // XXX: handle special cases, destination not modified... if ((mBlendSrc==GGL_ZERO) && (mBlendSrcA==GGL_ZERO) && (mBlendDst==GGL_ONE) && (mBlendDstA==GGL_ONE)) { // Destination unmodified (beware of logic ops) } else if ((mBlendSrc==GGL_ZERO) && (mBlendSrcA==GGL_ZERO) && (mBlendDst==GGL_ZERO) && (mBlendDstA==GGL_ZERO)) { // Destination is zero (beware of logic ops) } int fbComponents = 0; const int masking = GGL_READ_NEEDS(MASK_ARGB, needs.n); for (int i=0 ; i<4 ; i++) { const int mask = 1<<i; component_info_t& info = mInfo[i]; int fs = i==GGLFormat::ALPHA ? mBlendSrcA : mBlendSrc; int fd = i==GGLFormat::ALPHA ? mBlendDstA : mBlendDst; if (fs==GGL_SRC_ALPHA_SATURATE && i==GGLFormat::ALPHA) fs = GGL_ONE; info.masked = !!(masking & mask); info.inDest = !info.masked && mCbFormat.c[i].h && ((mLogicOp & LOGIC_OP_SRC) || (!mLogicOp)); if (mCbFormat.components >= GGL_LUMINANCE && (i==GGLFormat::GREEN || i==GGLFormat::BLUE)) { info.inDest = false; } info.needed = (i==GGLFormat::ALPHA) && (isAlphaSourceNeeded() || mAlphaTest != GGL_ALWAYS); info.replaced = !!(mTextureMachine.replaced & mask); info.iterated = (!info.replaced && (info.inDest || info.needed)); info.smooth = mSmooth && info.iterated; info.fog = mFog && info.inDest && (i != GGLFormat::ALPHA); info.blend = (fs != int(GGL_ONE)) || (fd > int(GGL_ZERO)); mBlending |= (info.blend ? mask : 0); mMasking |= (mCbFormat.c[i].h && info.masked) ? mask : 0; fbComponents |= mCbFormat.c[i].h ? mask : 0; } mAllMasked = (mMasking == fbComponents); if (mAllMasked) { mDithering = 0; } fragment_parts_t parts; // ------------------------------------------------------------------------ prolog(); // ------------------------------------------------------------------------ build_scanline_prolog(parts, needs); if (registerFile().status()) return registerFile().status(); // ------------------------------------------------------------------------ label("fragment_loop"); // ------------------------------------------------------------------------ { Scratch regs(registerFile()); if (mDithering) { // update the dither index. MOV(AL, 0, parts.count.reg, reg_imm(parts.count.reg, ROR, GGL_DITHER_ORDER_SHIFT)); ADD(AL, 0, parts.count.reg, parts.count.reg, imm( 1 << (32 - GGL_DITHER_ORDER_SHIFT))); MOV(AL, 0, parts.count.reg, reg_imm(parts.count.reg, ROR, 32 - GGL_DITHER_ORDER_SHIFT)); } // XXX: could we do an early alpha-test here in some cases? // It would probaly be used only with smooth-alpha and no texture // (or no alpha component in the texture). // Early z-test if (mAlphaTest==GGL_ALWAYS) { build_depth_test(parts, Z_TEST|Z_WRITE); } else { // we cannot do the z-write here, because // it might be killed by the alpha-test later build_depth_test(parts, Z_TEST); } { // texture coordinates Scratch scratches(registerFile()); // texel generation build_textures(parts, regs); if (registerFile().status()) return registerFile().status(); } if ((blending & (FACTOR_DST|BLEND_DST)) || (mMasking && !mAllMasked) || (mLogicOp & LOGIC_OP_DST)) { // blending / logic_op / masking need the framebuffer mDstPixel.setTo(regs.obtain(), &mCbFormat); // load the framebuffer pixel comment("fetch color-buffer"); load(parts.cbPtr, mDstPixel); } if (registerFile().status()) return registerFile().status(); pixel_t pixel; int directTex = mTextureMachine.directTexture; if (directTex | parts.packed) { // note: we can't have both here // iterated color or direct texture pixel = directTex ? parts.texel[directTex-1] : parts.iterated; pixel.flags &= ~CORRUPTIBLE; } else { if (mDithering) { const int ctxtReg = mBuilderContext.Rctx; const int mask = GGL_DITHER_SIZE-1; parts.dither = reg_t(regs.obtain()); AND(AL, 0, parts.dither.reg, parts.count.reg, imm(mask)); ADDR_ADD(AL, 0, parts.dither.reg, ctxtReg, parts.dither.reg); LDRB(AL, parts.dither.reg, parts.dither.reg, immed12_pre(GGL_OFFSETOF(ditherMatrix))); } // allocate a register for the resulting pixel pixel.setTo(regs.obtain(), &mCbFormat, FIRST); build_component(pixel, parts, GGLFormat::ALPHA, regs); if (mAlphaTest!=GGL_ALWAYS) { // only handle the z-write part here. We know z-test // was successful, as well as alpha-test. build_depth_test(parts, Z_WRITE); } build_component(pixel, parts, GGLFormat::RED, regs); build_component(pixel, parts, GGLFormat::GREEN, regs); build_component(pixel, parts, GGLFormat::BLUE, regs); pixel.flags |= CORRUPTIBLE; } if (registerFile().status()) return registerFile().status(); if (pixel.reg == -1) { // be defensive here. if we're here it's probably // that this whole fragment is a no-op. pixel = mDstPixel; } if (!mAllMasked) { // logic operation build_logic_op(pixel, regs); // masking build_masking(pixel, regs); comment("store"); store(parts.cbPtr, pixel, WRITE_BACK); } } if (registerFile().status()) return registerFile().status(); // update the iterated color... if (parts.reload != 3) { build_smooth_shade(parts); } // update iterated z build_iterate_z(parts); // update iterated fog build_iterate_f(parts); SUB(AL, S, parts.count.reg, parts.count.reg, imm(1<<16)); B(PL, "fragment_loop"); label("epilog"); epilog(registerFile().touched()); if ((mAlphaTest!=GGL_ALWAYS) || (mDepthTest!=GGL_ALWAYS)) { if (mDepthTest!=GGL_ALWAYS) { label("discard_before_textures"); build_iterate_texture_coordinates(parts); } label("discard_after_textures"); build_smooth_shade(parts); build_iterate_z(parts); build_iterate_f(parts); if (!mAllMasked) { ADDR_ADD(AL, 0, parts.cbPtr.reg, parts.cbPtr.reg, imm(parts.cbPtr.size>>3)); } SUB(AL, S, parts.count.reg, parts.count.reg, imm(1<<16)); B(PL, "fragment_loop"); epilog(registerFile().touched()); }
void body::generateImpl(utility::outputStream& os, const string::size_type maxLineLength, const string::size_type /* curLinePos */, string::size_type* newLinePos) const { // MIME-Multipart if (getPartCount() != 0) { string boundary; if (m_header.acquire() == NULL) { boundary = generateRandomBoundaryString(); } else { try { ref <const contentTypeField> ctf = m_header.acquire()->findField(fields::CONTENT_TYPE) .dynamicCast <const contentTypeField>(); boundary = ctf->getBoundary(); } catch (exceptions::no_such_field&) { // Warning: no content-type and no boundary string specified! boundary = generateRandomBoundaryString(); } catch (exceptions::no_such_parameter&) { // Warning: no boundary string specified! boundary = generateRandomBoundaryString(); } } const string& prologText = m_prologText.empty() ? (isRootPart() ? options::getInstance()->multipart.getPrologText() : NULL_STRING ) : m_prologText; const string& epilogText = m_epilogText.empty() ? (isRootPart() ? options::getInstance()->multipart.getEpilogText() : NULL_STRING ) : m_epilogText; if (!prologText.empty()) { text prolog(prologText, vmime::charset("us-ascii")); prolog.encodeAndFold(os, maxLineLength, 0, NULL, text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE); os << CRLF; } os << "--" << boundary; for (int p = 0 ; p < getPartCount() ; ++p) { os << CRLF; getPartAt(p)->generate(os, maxLineLength, 0); os << CRLF << "--" << boundary; } os << "--" << CRLF; if (!epilogText.empty()) { text epilog(epilogText, vmime::charset("us-ascii")); epilog.encodeAndFold(os, maxLineLength, 0, NULL, text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE); os << CRLF; } if (newLinePos) *newLinePos = 0; } // Simple body else { // Generate the contents m_contents->generate(os, getEncoding(), maxLineLength); } }
jit_pointer_t _emit_code(jit_state_t *_jit) { jit_node_t *node; jit_node_t *temp; jit_word_t word; jit_int32_t value; jit_int32_t offset; struct { jit_node_t *node; jit_word_t word; jit_int32_t patch_offset; } undo; _jitc->function = NULL; jit_reglive_setup(); undo.word = 0; undo.node = NULL; undo.patch_offset = 0; #define case_rr(name, type) \ case jit_code_##name##r##type: \ name##r##type(rn(node->u.w), rn(node->v.w)); \ break #define case_rw(name, type) \ case jit_code_##name##i##type: \ name##i##type(rn(node->u.w), node->v.w); \ break #define case_wr(name, type) \ case jit_code_##name##i##type: \ name##i##type(node->u.w, rn(node->v.w)); \ break #define case_rf(name) \ case jit_code_##name##i##type: \ assert(node->flag & jit_flag_data); \ name##_f(rn(node->u.w), \ (jit_float32_t *)node->v.n->u.w); \ break #define case_rd(name) \ case jit_code_##name##i_d: \ assert(node->flag & jit_flag_data); \ name##_d(rn(node->u.w), \ (jit_float64_t *)node->v.n->u.w); \ break #define case_rrr(name, type) \ case jit_code_##name##r##type: \ name##r##type(rn(node->u.w), \ rn(node->v.w), rn(node->w.w)); \ break #define case_rrrr(name, type) \ case jit_code_##name##r##type: \ name##r##type(rn(node->u.q.l), rn(node->u.q.h), \ rn(node->v.w), rn(node->w.w)); \ break #define case_rrw(name, type) \ case jit_code_##name##i##type: \ name##i##type(rn(node->u.w), \ rn(node->v.w), node->w.w); \ break #define case_rrrw(name, type) \ case jit_code_##name##i##type: \ name##i##type(rn(node->u.q.l), rn(node->u.q.h), \ rn(node->v.w), node->w.w); \ break #define case_rrf(name, type, size) \ case jit_code_##name##i##type: \ assert(node->flag & jit_flag_data); \ name##i##type(rn(node->u.w), rn(node->v.w), \ (jit_float##size##_t *)node->w.n->u.w); \ break #define case_wrr(name, type) \ case jit_code_##name##i##type: \ name##i##type(node->u.w, rn(node->v.w), rn(node->w.w)); \ break #define case_brr(name, type) \ case jit_code_##name##r##type: \ temp = node->u.n; \ assert(temp->code == jit_code_label || \ temp->code == jit_code_epilog); \ if (temp->flag & jit_flag_patch) \ name##r##type(temp->u.w, rn(node->v.w), \ rn(node->w.w)); \ else { \ word = name##r##type(_jit->pc.w, \ rn(node->v.w), rn(node->w.w)); \ patch(word, node); \ } \ break #define case_brw(name, type) \ case jit_code_##name##i##type: \ temp = node->u.n; \ assert(temp->code == jit_code_label || \ temp->code == jit_code_epilog); \ if (temp->flag & jit_flag_patch) \ name##i##type(temp->u.w, \ rn(node->v.w), node->w.w); \ else { \ word = name##i##type(_jit->pc.w, \ rn(node->v.w), node->w.w); \ patch(word, node); \ } \ break #define case_brf(name, type, size) \ case jit_code_##name##i##type: \ temp = node->u.n; \ assert(temp->code == jit_code_label || \ temp->code == jit_code_epilog); \ if (temp->flag & jit_flag_patch) \ name##i##type(temp->u.w, rn(node->v.w), \ (jit_float##size##_t *)node->w.n->u.w); \ else { \ word = name##i##type(_jit->pc.w, rn(node->v.w), \ (jit_float##size##_t *)node->w.n->u.w); \ patch(word, node); \ } \ break for (node = _jitc->head; node; node = node->next) { if (_jit->pc.uc >= _jitc->code.end) return (NULL); value = jit_classify(node->code); jit_regarg_set(node, value); switch (node->code) { case jit_code_align: assert(!(node->u.w & (node->u.w - 1)) && node->u.w <= sizeof(jit_word_t)); if (node->u.w == sizeof(jit_word_t) && (word = _jit->pc.w & (sizeof(jit_word_t) - 1))) nop(sizeof(jit_word_t) - word); break; case jit_code_note: case jit_code_name: node->u.w = _jit->pc.w; break; case jit_code_label: if ((node->link || (node->flag & jit_flag_use)) && (word = _jit->pc.w & (sizeof(jit_word_t) - 1))) nop(sizeof(jit_word_t) - word); /* remember label is defined */ node->flag |= jit_flag_patch; node->u.w = _jit->pc.w; break; case_rrr(add,); case_rrw(add,); case_rrr(addc,); case_rrw(addc,); case_rrr(addx,); case_rrw(addx,); case_rrr(sub,); case_rrw(sub,); case_rrr(subc,); case_rrw(subc,); case_rrr(subx,); case_rrw(subx,); case_rrw(rsb,); case_rrr(mul,); case_rrw(mul,); case_rrrr(qmul,); case_rrrw(qmul,); case_rrrr(qmul, _u); case_rrrw(qmul, _u); case_rrr(div,); case_rrw(div,); case_rrr(div, _u); case_rrw(div, _u); case_rrrr(qdiv,); case_rrrw(qdiv,); case_rrrr(qdiv, _u); case_rrrw(qdiv, _u); case_rrr(rem,); case_rrw(rem,); case_rrr(rem, _u); case_rrw(rem, _u); case_rrr(and,); case_rrw(and,); case_rrr(or,); case_rrw(or,); case_rrr(xor,); case_rrw(xor,); case_rrr(lsh,); case_rrw(lsh,); case_rrr(rsh,); case_rrw(rsh,); case_rrr(rsh, _u); case_rrw(rsh, _u); case_rr(trunc, _f_i); case_rr(trunc, _d_i); case_rrr(lt,); case_rrw(lt,); case_rrr(lt, _u); case_rrw(lt, _u); case_rrr(le,); case_rrw(le,); case_rrr(le, _u); case_rrw(le, _u); case_rrr(eq,); case_rrw(eq,); case_rrr(ge,); case_rrw(ge,); case_rrr(ge, _u); case_rrw(ge, _u); case_rrr(gt,); case_rrw(gt,); case_rrr(gt, _u); case_rrw(gt, _u); case_rrr(ne,); case_rrw(ne,); case_rr(ld, _c); case_rw(ld, _c); case_rr(ld, _uc); case_rw(ld, _uc); case_rr(ld, _s); case_rw(ld, _s); case_rr(ld, _us); case_rw(ld, _us); case_rr(ld, _i); case_rw(ld, _i); case_rrr(ldx, _c); case_rrw(ldx, _c); case_rrr(ldx, _uc); case_rrw(ldx, _uc); case_rrr(ldx, _s); case_rrw(ldx, _s); case_rrr(ldx, _us); case_rrw(ldx, _us); case_rrr(ldx, _i); case_rrw(ldx, _i); case_rr(st, _c); case_wr(st, _c); case_rr(st, _s); case_wr(st, _s); case_rr(st, _i); case_wr(st, _i); case_rrr(stx, _c); case_wrr(stx, _c); case_rrr(stx, _s); case_wrr(stx, _s); case_rrr(stx, _i); case_wrr(stx, _i); case_rr(hton, _us); case_rr(hton, _ui); case_rr(ext, _c); case_rr(ext, _uc); case_rr(ext, _s); case_rr(ext, _us); case_rr(mov,); case jit_code_movi: if (node->flag & jit_flag_node) { temp = node->v.n; if (temp->code == jit_code_data || (temp->code == jit_code_label && (temp->flag & jit_flag_patch))) movi(rn(node->u.w), temp->u.w); else { assert(temp->code == jit_code_label || temp->code == jit_code_epilog); word = movi_p(rn(node->u.w), node->v.w); patch(word, node); } } else movi(rn(node->u.w), node->v.w); break; case_rr(neg,); case_rr(com,); case_brr(blt,); case_brw(blt,); case_brr(blt, _u); case_brw(blt, _u); case_brr(ble,); case_brw(ble,); case_brr(ble, _u); case_brw(ble, _u); case_brr(beq,); case_brw(beq,); case_brr(bge,); case_brw(bge,); case_brr(bge, _u); case_brw(bge, _u); case_brr(bgt,); case_brw(bgt,); case_brr(bgt, _u); case_brw(bgt, _u); case_brr(bne,); case_brw(bne,); case_brr(boadd,); case_brw(boadd,); case_brr(boadd, _u); case_brw(boadd, _u); case_brr(bxadd,); case_brw(bxadd,); case_brr(bxadd, _u); case_brw(bxadd, _u); case_brr(bosub,); case_brw(bosub,); case_brr(bosub, _u); case_brw(bosub, _u); case_brr(bxsub,); case_brw(bxsub,); case_brr(bxsub, _u); case_brw(bxsub, _u); case_brr(bms,); case_brw(bms,); case_brr(bmc,); case_brw(bmc,); case_rrr(add, _f); case_rrf(add, _f, 32); case_rrr(sub, _f); case_rrf(sub, _f, 32); case_rrf(rsb, _f, 32); case_rrr(mul, _f); case_rrf(mul, _f, 32); case_rrr(div, _f); case_rrf(div, _f, 32); case_rr(abs, _f); case_rr(neg, _f); case_rr(sqrt, _f); case_rr(ext, _f); case_rr(ext, _d_f); case_rrr(lt, _f); case_rrf(lt, _f, 32); case_rrr(le, _f); case_rrf(le, _f, 32); case_rrr(eq, _f); case_rrf(eq, _f, 32); case_rrr(ge, _f); case_rrf(ge, _f, 32); case_rrr(gt, _f); case_rrf(gt, _f, 32); case_rrr(ne, _f); case_rrf(ne, _f, 32); case_rrr(unlt, _f); case_rrf(unlt, _f, 32); case_rrr(unle, _f); case_rrf(unle, _f, 32); case_rrr(uneq, _f); case_rrf(uneq, _f, 32); case_rrr(unge, _f); case_rrf(unge, _f, 32); case_rrr(ungt, _f); case_rrf(ungt, _f, 32); case_rrr(ltgt, _f); case_rrf(ltgt, _f, 32); case_rrr(ord, _f); case_rrf(ord, _f, 32); case_rrr(unord, _f); case_rrf(unord, _f, 32); case_rr(ld, _f); case_rw(ld, _f); case_rrr(ldx, _f); case_rrw(ldx, _f); case_rr(st, _f); case_wr(st, _f); case_rrr(stx, _f); case_wrr(stx, _f); case_rr(mov, _f); case jit_code_movi_f: assert(node->flag & jit_flag_data); movi_f(rn(node->u.w), (jit_float32_t *)node->v.n->u.w); break; case_brr(blt, _f); case_brf(blt, _f, 32); case_brr(ble, _f); case_brf(ble, _f, 32); case_brr(beq, _f); case_brf(beq, _f, 32); case_brr(bge, _f); case_brf(bge, _f, 32); case_brr(bgt, _f); case_brf(bgt, _f, 32); case_brr(bne, _f); case_brf(bne, _f, 32); case_brr(bunlt, _f); case_brf(bunlt, _f, 32); case_brr(bunle, _f); case_brf(bunle, _f, 32); case_brr(buneq, _f); case_brf(buneq, _f, 32); case_brr(bunge, _f); case_brf(bunge, _f, 32); case_brr(bungt, _f); case_brf(bungt, _f, 32); case_brr(bltgt, _f); case_brf(bltgt, _f, 32); case_brr(bord, _f); case_brf(bord, _f, 32); case_brr(bunord, _f); case_brf(bunord, _f, 32); case_rrr(add, _d); case_rrf(add, _d, 64); case_rrr(sub, _d); case_rrf(sub, _d, 64); case_rrf(rsb, _d, 64); case_rrr(mul, _d); case_rrf(mul, _d, 64); case_rrr(div, _d); case_rrf(div, _d, 64); case_rr(abs, _d); case_rr(neg, _d); case_rr(sqrt, _d); case_rr(ext, _d); case_rr(ext, _f_d); case_rrr(lt, _d); case_rrf(lt, _d, 64); case_rrr(le, _d); case_rrf(le, _d, 64); case_rrr(eq, _d); case_rrf(eq, _d, 64); case_rrr(ge, _d); case_rrf(ge, _d, 64); case_rrr(gt, _d); case_rrf(gt, _d, 64); case_rrr(ne, _d); case_rrf(ne, _d, 64); case_rrr(unlt, _d); case_rrf(unlt, _d, 64); case_rrr(unle, _d); case_rrf(unle, _d, 64); case_rrr(uneq, _d); case_rrf(uneq, _d, 64); case_rrr(unge, _d); case_rrf(unge, _d, 64); case_rrr(ungt, _d); case_rrf(ungt, _d, 64); case_rrr(ltgt, _d); case_rrf(ltgt, _d, 64); case_rrr(ord, _d); case_rrf(ord, _d, 64); case_rrr(unord, _d); case_rrf(unord, _d, 64); case_rr(ld, _d); case_rw(ld, _d); case_rrr(ldx, _d); case_rrw(ldx, _d); case_rr(st, _d); case_wr(st, _d); case_rrr(stx, _d); case_wrr(stx, _d); case_rr(mov, _d); case jit_code_movi_d: assert(node->flag & jit_flag_data); movi_d(rn(node->u.w), (jit_float64_t *)node->v.n->u.w); break; case_brr(blt, _d); case_brf(blt, _d, 64); case_brr(ble, _d); case_brf(ble, _d, 64); case_brr(beq, _d); case_brf(beq, _d, 64); case_brr(bge, _d); case_brf(bge, _d, 64); case_brr(bgt, _d); case_brf(bgt, _d, 64); case_brr(bne, _d); case_brf(bne, _d, 64); case_brr(bunlt, _d); case_brf(bunlt, _d, 64); case_brr(bunle, _d); case_brf(bunle, _d, 64); case_brr(buneq, _d); case_brf(buneq, _d, 64); case_brr(bunge, _d); case_brf(bunge, _d, 64); case_brr(bungt, _d); case_brf(bungt, _d, 64); case_brr(bltgt, _d); case_brf(bltgt, _d, 64); case_brr(bord, _d); case_brf(bord, _d, 64); case_brr(bunord, _d); case_brf(bunord, _d, 64); case jit_code_jmpr: jmpr(rn(node->u.w)); break; case jit_code_jmpi: if (node->flag & jit_flag_node) { temp = node->u.n; assert(temp->code == jit_code_label || temp->code == jit_code_epilog); if (temp->flag & jit_flag_patch) jmpi(temp->u.w); else { word = jmpi_p(_jit->pc.w); patch(word, node); } } else jmpi(node->u.w); break; case jit_code_callr: callr(rn(node->u.w)); break; case jit_code_calli: if (node->flag & jit_flag_node) { temp = node->u.n; assert(temp->code == jit_code_label || temp->code == jit_code_epilog); word = calli_p(temp->u.w); if (!(temp->flag & jit_flag_patch)) patch(word, node); } else calli(node->u.w); break; case jit_code_prolog: _jitc->function = _jitc->functions.ptr + node->w.w; undo.node = node; undo.word = _jit->pc.w; undo.patch_offset = _jitc->patches.offset; restart_function: _jitc->again = 0; prolog(node); break; case jit_code_epilog: assert(_jitc->function == _jitc->functions.ptr + node->w.w); if (_jitc->again) { for (temp = undo.node->next; temp != node; temp = temp->next) { if (temp->code == jit_code_label || temp->code == jit_code_epilog) temp->flag &= ~jit_flag_patch; } temp->flag &= ~jit_flag_patch; node = undo.node; _jit->pc.w = undo.word; _jitc->patches.offset = undo.patch_offset; goto restart_function; } /* remember label is defined */ node->flag |= jit_flag_patch; node->u.w = _jit->pc.w; epilog(node); _jitc->function = NULL; break; case jit_code_live: case jit_code_arg: case jit_code_arg_f: case jit_code_arg_d: break; default: abort(); } jit_regarg_clr(node, value); assert(_jitc->regarg == 0); /* update register live state */ jit_reglive(node); } #undef case_brf #undef case_brw #undef case_brr #undef case_wrr #undef case_rrf #undef case_rrrw #undef case_rrw #undef case_rrrr #undef case_rrr #undef case_rf #undef case_wr #undef case_rw #undef case_rr for (offset = 0; offset < _jitc->patches.offset; offset++) { node = _jitc->patches.ptr[offset].node; word = node->code == jit_code_movi ? node->v.n->u.w : node->u.n->u.w; patch_at(_jitc->patches.ptr[offset].inst, word); } jit_flush(_jit->code.ptr, _jit->pc.uc); return (_jit->code.ptr); }
address generate_call_stub(address& return_address) { assert (!TaggedStackInterpreter, "not supported"); StubCodeMark mark(this, "StubRoutines", "call_stub"); address start = __ enter(); const Register call_wrapper = r3; const Register result = r4; const Register result_type = r5; const Register method = r6; const Register entry_point = r7; const Register parameters = r8; const Register parameter_words = r9; const Register thread = r10; #ifdef ASSERT // Make sure we have no pending exceptions { StackFrame frame; Label label; __ load (r0, Address(thread, Thread::pending_exception_offset())); __ compare (r0, 0); __ beq (label); __ prolog (frame); __ should_not_reach_here (__FILE__, __LINE__); __ epilog (frame); __ blr (); __ bind (label); } #endif // ASSERT // Calculate the frame size StackFrame frame; for (int i = 0; i < StackFrame::max_crfs; i++) frame.get_cr_field(); for (int i = 0; i < StackFrame::max_gprs; i++) frame.get_register(); StubRoutines::set_call_stub_base_size(frame.unaligned_size() + 3*wordSize); // the 3 extra words are for call_wrapper, result and result_type const Register parameter_bytes = parameter_words; __ shift_left (parameter_bytes, parameter_words, LogBytesPerWord); const Register frame_size = r11; const Register padding = r12; __ addi (frame_size, parameter_bytes, StubRoutines::call_stub_base_size()); __ calc_padding_for_alignment (padding, frame_size, StackAlignmentInBytes); __ add (frame_size, frame_size, padding); // Save the link register and create the new frame __ mflr (r0); __ store (r0, Address(r1, StackFrame::lr_save_offset * wordSize)); __ neg (r0, frame_size); __ store_update_indexed (r1, r1, r0); #ifdef PPC64 __ mfcr (r0); __ store (r0, Address(r1, StackFrame::cr_save_offset * wordSize)); #endif // PPC64 // Calculate the address of the interpreter's local variables const Register locals = frame_size; __ addi (locals, r1, frame.start_of_locals() - wordSize); __ add (locals, locals, padding); __ add (locals, locals, parameter_bytes); // Store the call wrapper address and the result stuff const int initial_offset = 1; int offset = initial_offset; __ store (call_wrapper, Address(locals, offset++ * wordSize)); __ store (result, Address(locals, offset++ * wordSize)); __ store (result_type, Address(locals, offset++ * wordSize)); // Store the registers #ifdef PPC32 __ mfcr (r0); __ store (r0, Address(locals, offset++ * wordSize)); #endif // PPC32 for (int i = 14; i < 32; i++) { __ store (as_Register(i), Address(locals, offset++ * wordSize)); } const int final_offset = offset; // Store the location of call_wrapper frame::set_call_wrapper_offset((final_offset - initial_offset) * wordSize); #ifdef ASSERT // Check that we wrote all the way to the end of the frame. // The frame may have been resized when we return from the // interpreter, so the start of the frame may have moved // but the end will be where we left it and we rely on this // to find our stuff. { StackFrame frame; Label label; __ load (r3, Address(r1, 0)); __ subi (r3, r3, final_offset * wordSize); __ compare (r3, locals); __ beq (label); __ prolog (frame); __ should_not_reach_here (__FILE__, __LINE__); __ epilog (frame); __ blr (); __ bind (label); } #endif // ASSERT // Pass parameters if any { Label loop, done; __ compare (parameter_bytes, 0); __ ble (done); const Register src = parameters; const Register dst = padding; __ mr (dst, locals); __ shift_right (r0, parameter_bytes, LogBytesPerWord); __ mtctr (r0); __ bind (loop); __ load (r0, Address(src, 0)); __ store (r0, Address(dst, 0)); __ addi (src, src, wordSize); __ subi (dst, dst, wordSize); __ bdnz (loop); __ bind (done); } // Make the call __ mr (Rmethod, method); __ mr (Rlocals, locals); __ mr (Rthread, thread); __ mtctr (entry_point); __ bctrl(); // This is used to identify call_stub stack frames return_address = __ pc(); // Figure out where our stuff is stored __ load (locals, Address(r1, 0)); __ subi (locals, locals, final_offset * wordSize); #ifdef ASSERT // Rlocals should contain the address we just calculated. { StackFrame frame; Label label; __ compare (Rlocals, locals); __ beq (label); __ prolog (frame); __ should_not_reach_here (__FILE__, __LINE__); __ epilog (frame); __ blr (); __ bind (label); } #endif // ASSERT // Is an exception being thrown? Label exit; __ load (r0, Address(Rthread, Thread::pending_exception_offset())); __ compare (r0, 0); __ bne (exit); // Store result depending on type const Register result_addr = r6; Label is_int, is_long, is_object; offset = initial_offset + 1; // skip call_wrapper __ load (result_addr, Address(locals, offset++ * wordSize)); __ load (result_type, Address(locals, offset++ * wordSize)); __ compare (result_type, T_INT); __ beq (is_int); __ compare (result_type, T_LONG); __ beq (is_long); __ compare (result_type, T_OBJECT); __ beq (is_object); __ should_not_reach_here (__FILE__, __LINE__); __ bind (is_int); __ stw (r3, Address(result_addr, 0)); __ b (exit); __ bind (is_long); #ifdef PPC32 __ store (r4, Address(result_addr, wordSize)); #endif __ store (r3, Address(result_addr, 0)); __ b (exit); __ bind (is_object); __ store (r3, Address(result_addr, 0)); //__ b (exit); // Restore the registers __ bind (exit); #ifdef PPC32 __ load (r0, Address(locals, offset++ * wordSize)); __ mtcr (r0); #endif // PPC32 for (int i = 14; i < 32; i++) { __ load (as_Register(i), Address(locals, offset++ * wordSize)); } #ifdef PPC64 __ load (r0, Address(r1, StackFrame::cr_save_offset * wordSize)); __ mtcr (r0); #endif // PPC64 assert (offset == final_offset, "save and restore must match"); // Unwind and return __ load (r1, Address(r1, StackFrame::back_chain_offset * wordSize)); __ load (r0, Address(r1, StackFrame::lr_save_offset * wordSize)); __ mtlr (r0); __ blr (); return start; }
void PGPFilter::DoProcess(String& text, MessageViewer *viewer, MTextStyle& style) { // do we have something looking like a PGP message? // // there should be a BEGIN line near the start of the message const wxChar *beginNext = NULL; const wxChar *start = text.c_str(); for ( size_t numLines = 0; numLines < 10; numLines++ ) { const wxChar *p = start; if ( AdvanceIfMatches(&p, PGP_BEGIN_PREFIX) ) { beginNext = p; break; } // try the next line (but only if not already at the end) if ( !*p ) break; p = wxStrchr(start, _T('\n')); if ( !p ) break; // no more text start = p + 1; // skip '\n' itself } if ( beginNext ) { // is the message just signed or encrypted? bool isKey = false; const bool isSigned = AdvanceIfMatches(&beginNext, _T("SIGNED ")); if ( !isSigned ) { isKey = AdvanceIfMatches(&beginNext, _T("PUBLIC KEY ")); } // this flag tells us if everything is ok so far -- as soon as it becomes // false, we skip all subsequent steps // We do not know (yet) what to do with public key blocks, so let's consider // that they're not ok. // TODO: propose to import it into the keyring? bool ok = !isKey; if ( ok && !AdvanceIfMatches(&beginNext, PGP_BEGIN_SUFFIX) ) { wxLogWarning(_("The BEGIN line doesn't end with expected suffix.")); ok = false; } // end of the PGP part const wxChar *end = NULL; // unneeded but suppresses the compiler warning const wxChar *endNext = NULL; // same if ( ok ) // ok, it starts with something valid { // now locate the end line const wxChar *pc = start + text.length() - 1; bool foundEnd = false; for ( ;; ) { // optimistically suppose that this line will be the END one end = pc + 2; // find the beginning of this line while ( *pc != '\n' && pc >= start ) { pc--; } // we took one extra char pc++; if ( AdvanceIfMatches(&pc, PGP_END_PREFIX) ) { endNext = pc; foundEnd = true; break; } // undo the above pc--; if ( pc < start ) { // we exhausted the message without finding the END line, leave // foundEnd at false and exit the loop break; } pc--; ASSERT_MSG( *pc == '\r', _T("line doesn't end in\"\\r\\n\"?") ); } if ( !foundEnd ) { wxLogWarning(_("END line not found.")); ok = false; } } // check that the END line matches the BEGIN one if ( ok ) { const wxChar * const suffix = isSigned ? PGP_END_SIG_SUFFIX : PGP_END_CRYPT_SUFFIX; if ( !AdvanceIfMatches(&endNext, suffix) ) { wxLogWarning(_("Mismatch between BEGIN and END lines.")); ok = false; } } // if everything was ok so far, continue with decoding/verifying if ( ok ) { // output the part before the BEGIN line, if any String prolog(text.c_str(), start); if ( !prolog.empty() ) { m_next->Process(prolog, viewer, style); } CHECK_RET( m_engine, _T("PGP filter can't work without PGP engine") ); ClickablePGPInfo *pgpInfo = NULL; MCryptoEngineOutputLog * log = new MCryptoEngineOutputLog(m_msgView->GetWindow()); String in(start, end), out; if ( isSigned ) { // pass everything between start and end to PGP for verification const MCryptoEngine::Status rc = m_engine->VerifySignature(in, out, log); pgpInfo = ClickablePGPInfo:: CreateFromSigStatusCode(m_engine, rc, m_msgView, log); // if we failed to check the signature, we need to remove the // BEGIN/END lines from output ourselves (otherwise it would have // been done by VerifySignature() itself) if ( rc != MCryptoEngine::OK ) { // beginNext points to the end of BEGIN line, go forward to the // end of the headers. // // Normally the end of the headers must be signalled by a blank // line, but in practice some implementations, notably Enigmail // used with Thunderbird, put a space in this "empty" line, so // accept any line containing only spaces as indicating the end // of headers. const wxChar* startBody = beginNext; for ( ;; ) { startBody = wxStrstr(startBody, _T("\r\n")); if ( !startBody || startBody >= endNext ) break; // end of headers not found startBody += 2; // skip "\r\n" we just matched while ( *startBody == ' ' ) startBody++; if ( startBody[0] == '\r' && startBody[1] == '\n' ) { // we found the end of the headers startBody += 2; break; } } if ( startBody && startBody < endNext ) { // endNext currently points to the end of END PGP SIGNATURE // line, rewind to the PGP_BEGIN_SIG line const wxChar *pc = endNext; for ( ;; ) { // find the beginning of this line while ( *pc != '\n' && pc >= start ) { pc--; } if ( pc < start ) { // we exhausted the message without finding the // PGP_BEGIN_SIG line break; } pc++; // skip the "\n" if ( AdvanceIfMatches(&pc, PGP_BEGIN_SIG) ) { // chop off PGP_BEGIN_SIG line as well while ( *pc != '\n' && pc >= start ) pc--; if ( pc > start ) { out = String(startBody, pc - 1); } break; } pc -= 3; // rewind beyond "\r\n" ASSERT_MSG( pc[1] == '\r', _T("line doesn't end in\"\\r\\n\"?") ); } } else { wxLogWarning(_("Blank line separating header " "from body in PGP message not found.")); } } } else // encrypted { // try to decrypt MCryptoEngine::Status rc = m_engine->Decrypt(in, out, log); switch ( rc ) { case MCryptoEngine::OK: pgpInfo = new PGPInfoGoodMsg(m_msgView); break; default: wxLogError(_("Decrypting the PGP message failed.")); // fall through // if the user cancelled decryption, don't complain about it case MCryptoEngine::OPERATION_CANCELED_BY_USER: // using unmodified text is not very helpful here anyhow so // simply replace it with an icon pgpInfo = new PGPInfoBadMsg(m_msgView); } } m_next->Process(out, viewer, style); pgpInfo->SetLog(log); pgpInfo->SetRaw(in); // we want the PGP stuff to stand out viewer->InsertText(_T("\r\n"), style); viewer->InsertClickable(pgpInfo->GetBitmap(), pgpInfo, pgpInfo->GetColour()); viewer->InsertText(_T("\r\n"), style); // output the part after the END line, if any String epilog(end); if ( !epilog.empty() ) { m_next->Process(epilog, viewer, style); } } if ( ok ) { // skip the normal display below return; } // give a warning (unless this is a KEY blok and display the message normally if ( !isKey ) { wxLogWarning(_("This message seems to be PGP signed or encrypted " "but in fact is not.")); } } m_next->Process(text, viewer, style); }