#
# CGP.pm CGoto Prederefed
#        this is a mixture of prederefed register addressing and the
#        CGoto runloop
#        Please consult the corresponding OpTrans files for more
#
# Author: leo
#
# $Id: CGP.pm,v 1.4 2003/02/09 16:55:48 leo Exp $
#

use strict;
#use warnings;

package Parrot::OpTrans::CGP;

use Parrot::OpTrans;
use Parrot::OpTrans::CPrederef;
use vars qw(@ISA);
@ISA = qw(Parrot::OpTrans::CPrederef);


#
# suffix()
#

sub suffix
{
  return "_cgp";
}

sub defines
{
  return <<END;
#define REL_PC ((size_t)((opcode_t*)cur_opcode - (opcode_t*)interpreter->prederef_code))
#define CUR_OPCODE (interpreter->code->byte_code + REL_PC)


static void** opcode_to_prederef(struct Parrot_Interp* interpreter,
                                        opcode_t* opcode_addr)
{
    INTVAL offset_in_ops;
    if (opcode_addr == NULL) return NULL;
    offset_in_ops = opcode_addr - (opcode_t*) interpreter->code->byte_code;
    return interpreter->prederef_code + offset_in_ops;
}

END
}
#
# goto_address()
#

sub goto_address
{
  my ($self, $addr) = @_;
#print STDERR "pbcc: map_ret_abs($addr)\n";
  if ($addr eq '0') {
  	return "return (0);"
  } else {
  	return "if ((opcode_t *) $addr == 0)
	  return 0;
   goto **(cur_opcode = (opcode_t *)
	opcode_to_prederef(interpreter, $addr))";
  }
}

#
# goto_offset()
#

sub goto_offset
{
  my ($self, $offset) = @_;
  return "goto **(cur_opcode += $offset)";
}
#
# goto_pop()
#

sub goto_pop
{
  my ($self) = @_;
  return "goto ** (cur_opcode = (opcode_t*)opcode_to_prederef(interpreter,pop_dest(interpreter)))";
}
