/* 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;
}
Beispiel #2
0
procode(FILE *outfile)
#endif
{
	prolog(outfile, allargs);

	if (nentry > 1)
		entry_goto(outfile);
	}
Beispiel #3
0
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;
}
Beispiel #5
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();
}
Beispiel #6
0
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();
}
Beispiel #7
0
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;
}
Beispiel #8
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();
}
Beispiel #9
0
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);
}
Beispiel #11
0
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();
}
Beispiel #12
0
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).
}
Beispiel #13
0
	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);
	}
Beispiel #14
0
	int mainCRTStartup()
	{
		TraceFunc();

		prolog();

		int argc = 0;
		wchar_t ** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);

		int ret = wmain(argc, argv);

		::LocalFree(argv);

		TraceFunc();
		return epilog(ret);
	}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
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 ("");
}
Beispiel #21
0
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;
}
Beispiel #23
0
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();
}
Beispiel #24
0
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());
    }
Beispiel #26
0
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);
    }
}
Beispiel #27
0
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;
  }
Beispiel #29
0
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);
}