syn68k/runtime/backpatch.c
2008-09-26 08:25:10 -06:00

120 lines
2.6 KiB
C

#include "syn68k_private.h"
#include "backpatch.h"
#include "alloc.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
void
backpatch_apply_and_free (Block *b, backpatch_t *p)
{
ptr_sized_uint value;
uint32 first_byte;
int length;
BOOL found_p;
backpatch_t **bp;
char *base;
/* Find the backpatch in the block's list and remove it. */
for (bp = &b->backpatch, found_p = FALSE; *bp != NULL; bp = &(*bp)->next)
if (*bp == p)
{
*bp = p->next;
found_p = TRUE;
break;
}
#ifdef DEBUG
/* Make sure we actually found it in the list. */
if (!found_p)
abort ();
#endif
if (p->target == NULL)
base = (char *)0;
else
base = (char *)p->target->compiled_code;
/* First, compute the value to write out to memory. */
first_byte = p->offset_location / 8;
length = p->num_bits;
if (p->relative_p)
{
value = ((base + p->const_offset)
- ((char *)b->compiled_code + first_byte));
}
else
{
value = ((ptr_sized_uint)(base + p->const_offset));
}
#ifndef QUADALIGN
if ((p->offset_location & 7) == 0)
{
if (length == 32)
*(uint32 *)((char *)b->compiled_code + first_byte) = value;
else if (length == 16)
*(uint16 *)((char *)b->compiled_code + first_byte) = value;
else if (length == 8)
*(uint8 *)((char *)b->compiled_code + first_byte) = value;
#if defined (__alpha)
else if (length == 64)
*(uint64 *)((char *)b->compiled_code + first_byte) = value;
#endif
else
abort ();
}
else
{
abort ();
}
#else /* QUADALIGN */
/* The whole guy had better fit in one long! */
if ((p->offset_location & ~31)
== ((p->offset_location + length - 1) & ~31))
{
uint32 *ptr = (uint32 *)((char *)b->compiled_code + first_byte);
if (length == 32)
*ptr = value;
else
{
int offset = p->offset_location & 31;
#error "Write this case"
#ifdef LITTLEENDIAN
*ptr = (*ptr & ) | ;
#else /* !LITTLEENDIAN */
*ptr = (*ptr & ) | ;
#endif /* !LITTLEENDIAN */
}
}
else
abort ();
#endif /* QUADALIGN */
free (p);
}
void
backpatch_add (Block *b, int offset_location, int num_bits, BOOL relative_p,
int const_offset, Block *target)
{
backpatch_t *p;
#ifdef DEBUG
if (num_bits == 0)
abort ();
#endif
p = (backpatch_t *) xmalloc (sizeof *p);
p->next = b->backpatch;
p->offset_location = offset_location;
p->num_bits = num_bits;
p->relative_p = relative_p;
p->const_offset = const_offset;
p->target = target;
/* Prepend this guy to the block's list. */
b->backpatch = p;
}