NAME ^

src/utils.c - Some utility functions

DESCRIPTION ^

Prototypes are in src/misc.h.

Opcode helper functions that don't really fit elsewhere.

Functions ^

INTVAL intval_mod(INTVAL i2, INTVAL i3)

NOTE: This "corrected mod" algorithm is based on the C code on page 70 of [1]. Assuming correct behavior of the built-in mod operator (%) with positive arguments, this algorithm implements a mathematically convenient version of mod, defined thus:

    x mod y = x - y * floor(x / y)
For more information on this definition of mod, see section 3.4 of [2], pages 81-85.

References:

[1] Donald E. Knuth, *MMIXware: A RISC Computer for the Third Millennium* Springer, 1999.

[2] Ronald L. Graham, Donald E. Knuth and Oren Patashnik, *Concrete Mathematics*, Second Edition. Addison-Wesley, 1994.

FLOATVAL floatval_mod(FLOATVAL n2, FLOATVAL n3)

Returns n2 mod n3.

Includes a workaround for buggy code generation in the lcc compiler.

Random Number Generator ^

Based on the rand48() family of functions.

static void next_rand(_rand_buf X)

Returns the next random number in X.

static FLOATVAL _erand48(_rand_buf buf)

Returns a double in the interval [0.0, 1.0).

static FLOATVAL _drand48(void)

Returns a double in the interval [0.0, 1.0).

static long _jrand48(_rand_buf buf)

Returns a long in the interval [-2^31, 2^31).

static long _nrand48(_rand_buf buf)

Returns a long in the interval [0, 2^31).

static long _lrand48(void)

Returns a long in the interval [0, 2^31).

static long _mrand48(void)

Returns a long in the interval [-2^31, 2^31).

static void _srand48(long seed)

Sets the high order 32 bits to the argument seed. The low order 16 bits are set to the arbitrary value 0x330e.

FLOATVAL Parrot_float_rand(INTVAL how_random)

Returns a FLOATVAL in the interval [0.0, 1.0).

how_random is ignored.

INTVAL Parrot_uint_rand(INTVAL how_random)

Returns an INTVAL in the interval [0, 2^31).

how_random is ignored.

INTVAL Parrot_int_rand(INTVAL how_random)

Returns an INTVAL in the interval [-2^31, 2^31).

how_random is ignored.

INTVAL Parrot_range_rand(INTVAL from, INTVAL to, INTVAL how_random)

Returns an INTVAL in the range [from, to].

how_random is ignored.

void Parrot_srand(INTVAL seed)

Seeds the random number generator with seed.

Array Functions ^

void *Parrot_make_la(Interp *interpreter, PMC *array)

Creates a C array of longs with one more element than the number of elements in *array. The elements are then copied from *array to the new array, and the last (extra) element is set to 0.

Used in src/nci.c.

void Parrot_destroy_la(long *array)

Use this to destroy an array created with Parrot_make_la().

void *Parrot_make_cpa(Interp *interpreter, PMC *array)

Creates a C array of char *s with one more element than the number of elements in *array. The elements are then copied from *array to the new array, and the last (extra) element is set to 0.

Currently unused.

void Parrot_destroy_cpa(char **array)

Use this to destroy an array created with Parrot_make_cpa().

PMC *tm_to_array(Parrot_Interp, struct tm *)

Helper to convert a struct tm * to an Array

static int find_first_indegree(int *graph,int node_count, int dest)

Finds the first indegree for the given node.

static int find_root(int *graph ,int node_count, int src, int dest)

Finds the root vertex of the graph.

static void emit_mov(reg_move_func mov, Interp *interpreter, void *info, int emit, int emit_temp, int dest, int src, int temp, int *map)

Emit the move instructions

static int reorder_move(int *graph, INT node_count, int *map, INT *val, int src, int prev, int depth, reg_move_func mov, Interp *interpreter, void *info, int temp)

This method reorders the move operations.OA

typedef int (*reg_move_func)(Interp*, unsigned char d, unsigned char s, void *);

void Parrot_register_move(Interp *, int n_regs, unsigned char *dest_regs, unsigned char *src_regs, unsigned char temp_reg, reg_move_func mov, reg_move_func mov_alt, void *info)

Move n_regs from the given register list src_regs to dest_regs.

  n_regs    ... amount of registers to move
  dest_regs ... list of register numbers 0..255
  src_regs  ... list of register numbers 0..255
  temp_reg  ... a register number not in one of these lists
  mov       ... a register move function to be called to move one register
  mov_alt   ... a register move function to be called to move one register
                which triese fetching from an alternate src (or NULLfunc):
    
    (void)  (mov)(interp, dest, src, info);       
    moved = (mov_alt)(interp, dest, src, info);
Some dest_regs might be the same as src_regs, which makes this a bit non-trivial, because if the destination is already clobbered, using it later as source doesn"t work. E.g.

  0 <- 1
  1 <- 0     # register 0 already clobbered
or

  2 <- 0
  0 <- 1
  3 <- 2      # register 2 already clobbered - reorder moves
To handle such cases, we do:

  a) rearrange the order of moves (not possible in the first case)
     and/or if that failed:
  b) if an alternate move function is available, it may fetch the
     source from a different (non-clobbered) location - call it.
     if the function returns 0 also use c)
  c) if no alternate move function is available, use the temp reg   
The amount of register moves should of course be minimal.

TODO The current implementation will not work for following cases

Talked to Leo and he said those cases are not likely (Vishal Soni). 1. I0->I1 I1->I0 I0->I3 2. I1->I2 I3->I2

TODO: Add tests for the above conditions.

HISTORY ^

Initial version by leo 2003.09.09.


parrot