/* Supports instruction memory.
Copyright 1998-2005 James Bowman, Scott Dattalo
Copyright 2013 Borut Ražem
Copyright 2014-2016 Molnár Károly
*/
#include <limits.h>
#include "stdhdr.h"
#include "libgputils.h"
typedef union
{
uint8_t b[2];
uint16_t w;
} bword_t;
/**************************************************************************************************
gpmemory.c
This file provides the functions used to manipulate the PIC memory.
The memory is stored in 'memory blocks' which are implemented
with the 'MemBlock_t' structure:
typedef struct MemArg {
const char *arg;
int val; The value of the first argument.
int offs; If the argument is area then this the offset of the address.
} MemArg_t;
typedef struct MemArgList {
MemArg_t first;
MemArg_t second;
} MemArgList_t;
typedef union __attribute__ ((packed)) MemData {
unsigned all;
struct __attribute__ ((packed)) {
unsigned byte : 8; [0-7] The data byte.
unsigned is_addr_branch_src: 1; [ 8] W_ADDR_T_BRANCH_SRC
unsigned is_addr_label : 1; [ 9] W_ADDR_T_LABEL
unsigned is_addr_func : 1; [10] W_ADDR_T_FUNC
unsigned is_arg_first : 1; [11] W_ARG_T_FIRST
unsigned is_arg_second : 1; [12] W_ARG_T_SECOND
unsigned is_second_word : 1; [13] W_SECOND_WORD
unsigned is_const_data : 1; [14] W_CONST_DATA
unsigned is_byte_listed : 1; [15] BYTE_LISTED_MASK
unsigned is_byte_used : 1; [16] BYTE_USED_MASK
};
struct __attribute__ ((packed)) {
unsigned : 8;
unsigned addr_t: 3;
unsigned arg_t : 2;
unsigned : 2;
unsigned attr_t: 2;
};
struct __attribute__ ((packed)) {
unsigned : 8;
unsigned all_attr: 24;
};
} MemData_t;
typedef struct MemByte {
MemData_t data; The data byte and the attributes of.
char *section_name; During assembly or linking shows the name of section.
char *symbol_name; During assembly or linking shows the name of symbol.
After disassembly shows the name of function or label.
unsigned dest_byte_addr; After disassembly shows the target byte-address (not org) of a branch.
MemArgList_t args;
} MemByte_t;
typedef struct MemBlock {
unsigned base;
MemByte_t *memory;
struct MemBlock_t *next;
} MemBlock_t;
Each MemBlock_t can hold up to 'I_MEM_MAX' (64kB currently) bytes. The 'base'
is the base address of the memory block. If the instruction memory spans
more than 64kB, then additional memory blocks can be allocated and linked
together in a singly linked list ('next'). The last memory block in a
linked list of blocks has its next ptr set to NULL. 64kB is left over
from when it was number of two byte instructions and it corresponded
to 64k bytes which is the upper limit on inhx8m files.
**************************************************************************************************/
/**************************************************************************************************
* _memory_new
*
* Create memory for a pnew memory block.
*
* Inputs:
* m - start of the instruction memory
* mpb - pointer to the memory block structure (MemBlock_t)
* base_address - where this pnew block of memory is based
*
**************************************************************************************************/
static MemBlock_t* _memory_new(MemBlock_t *M, MemBlock_t *Mbp, unsigned Base_address)
{
unsigned block = IMemBaseFromAddr(Base_address);
Mbp->base = block;
Mbp->memory = new MemByte_t[I_MEM_MAX];
memset(Mbp->memory,0,sizeof*Mbp->memory*I_MEM_MAX);
do {
if ((M->next == NULL) || (M->next->base > block)) {
/* Insert after this block. */
Mbp->next = M->next;
M->next = Mbp;
return Mbp;
}
M = M->next;
} while (M);
assert(0);
return NULL;
}
/*------------------------------------------------------------------------------------------------*/
static void
_store_section_name(MemByte_t *Mb, const char *Name)
{
if ((Name) && (*Name != '\0')) {
Mb->section_name = GP_Strdup(Name);
}
}
/*------------------------------------------------------------------------------------------------*/
static void
_store_symbol_name(MemByte_t *Mb, const char *Name)
{
if ((Name) && (*Name != '\0')) {
Mb->symbol_name = GP_Strdup(Name);
}
}
/*------------------------------------------------------------------------------------------------*/
FUNC(MemBlock_t*) gp_mem_i_create(void) {
MemBlock_t*m = new MemBlock_t;
memset(m,0,sizeof*m);
return m;
}
/*------------------------------------------------------------------------------------------------*/
FUNC(void) gp_mem_i_free(MemBlock_t *M) {
MemBlock_t *next;
MemByte_t *b;
unsigned i;
if (M == NULL) {
return;
}
do {
if (M->memory) {
b = M->memory;
for (i = I_MEM_MAX; i; ++b, --i) {
if (b->section_name) {
free(b->section_name);
}
if (b->symbol_name) {
free(b->symbol_name);
}
}
free(M->memory);
}
next = M->next;
free(M);
M = next;
} while (M);
}
/**************************************************************************************************
* gp_mem_b_is_used
*
* Check if byte at address is used. This function will traverse through
* the linked list of memory blocks searching for the address from the
* word will be fetched.
*
* Inputs:
* M - start of the instruction memory
* Byte_address -
* Returns
* true if byte at byte_address is used, false if not
*
**************************************************************************************************/
FUNC(bool) gp_mem_b_is_used(MemBlock_t *M, unsigned Byte_address) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
do {
if (M->base == block) {
return ((M->memory) && M->memory[offset].data.is_byte_used);
}
M = M->next;
} while (M);
return false;
}
/*------------------------------------------------------------------------------------------------*/
FUNC(bool) gp_mem_b_offset_is_used(MemBlock_t *M, unsigned Byte_offset) {
if ((M == NULL) || (M->memory == NULL)) {
return false;
}
return M->memory[Byte_offset].data.is_byte_used;
}
/**************************************************************************************************
* gp_mem_b_get
*
* Fetch a byte from the pic memory. This function will traverse through
* the linked list of memory blocks searching for the address from the
* word will be fetched. If the address is not found, then `0' will be
* returned.
*
* Inputs:
* M - start of the instruction memory
* Byte_address -
* Returns
* If is used the address the byte at address and true.
* Otherwise 0 and false.
*
**************************************************************************************************/
FUNC(bool) gp_mem_b_get(const MemBlock_t *M, unsigned Byte_address, uint8_t *Byte,
const char **Section_name, const char **Symbol_name) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
MemByte_t *b;
while (M) {
if (M->base == block) {
if (M->memory) {
b = &M->memory[offset];
*Byte = b->data.byte;
if (Section_name) {
*Section_name = b->section_name;
}
if (Symbol_name) {
*Symbol_name = b->symbol_name;
}
return b->data.is_byte_used;
}
else {
*Byte = 0;
if (Section_name) {
*Section_name = NULL;
}
if (Symbol_name) {
*Symbol_name = NULL;
}
return false;
}
}
M = M->next;
}
if (Section_name) {
*Section_name = NULL;
}
if (Symbol_name) {
*Symbol_name = NULL;
}
*Byte = 0;
return false;
}
/**************************************************************************************************
* gp_mem_b_put
*
* This function will write one byte to a pic memory address. If the
* destination memory block is non-existant, a pnew one will be created.
*
* inputs:
* M - start of the instruction memory
* Byte_address - destination address of the write
* Value - the value to be written at that address
* Section_name - section_name of the memory block
* Symbol_name - symbol_name in the memory block
* returns:
* none
*
**************************************************************************************************/
FUNC(void) gp_mem_b_put(MemBlock_t *I_memory, unsigned Byte_address, uint8_t Value,
const char *Section_name, const char *Symbol_name) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
MemBlock_t *m = I_memory;
MemByte_t *b;
while (m) {
if (m->base == block) {
if (!m->memory) {
m->memory = new MemByte_t[I_MEM_MAX];
memset(m->memory,0,sizeof*m->memory);
}
b = &m->memory[offset];
if (b->section_name == NULL) {
_store_section_name(b, Section_name);
}
if (b->symbol_name == NULL) {
_store_symbol_name(b, Symbol_name);
}
b->data.byte = Value;
b->data.is_byte_used = true;
return;
}
m = m->next;
}
/* Couldn't find an address to write this value. This must be
the first time we've tried to write to high memory some place. */
m = _memory_new(I_memory, new MemBlock_t, Byte_address);
b = &m->memory[offset];
b->data.byte = Value;
b->data.is_byte_used = true;
_store_section_name(b, Section_name);
_store_symbol_name(b, Symbol_name);
}
/**************************************************************************************************
* gp_mem_b_clear
*
* This function will clear one byte of a pic memory address.
*
* inputs:
* M - start of the instruction memory
* Byte_address - destination address of the clear
* returns:
* none
*
**************************************************************************************************/
FUNC(void) gp_mem_b_clear(MemBlock_t *M, unsigned Byte_address) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
MemByte_t *b;
while (M) {
if (M->base == block) {
if (M->memory) {
b = &M->memory[offset];
b->data.all = 0;
if (b->section_name) {
free(b->section_name);
b->section_name = NULL;
}
if (b->symbol_name) {
free(b->symbol_name);
b->symbol_name = NULL;
}
}
return;
}
M = M->next;
}
}
/*------------------------------------------------------------------------------------------------*/
FUNC(void) gp_mem_b_move(MemBlock_t *M, unsigned From_byte_address, unsigned To_byte_address,
unsigned Byte_size) {
unsigned from_block = IMemBaseFromAddr(From_byte_address);
unsigned from_offset = IMemOffsFromAddr(From_byte_address);
unsigned to_block = IMemBaseFromAddr(To_byte_address);
unsigned to_offset = IMemOffsFromAddr(To_byte_address);
size_t size;
if ((From_byte_address == To_byte_address) || (Byte_size == 0)) {
return;
}
assert(from_block == to_block);
assert((from_offset + Byte_size) <= I_MEM_MAX);
assert((to_offset + Byte_size) <= I_MEM_MAX);
while (M) {
if (M->base == from_block) {
size = Byte_size * sizeof(MemByte_t);
memmove(&M->memory[to_offset], &M->memory[from_offset], size);
/* Clear the unused area. */
if (from_offset > to_offset) {
/*
* from_offset
* |
* v
* +-------+
* | |
* +-------+
*
* move direction
* <<-------
*
* to_offset unused area
* | |
* v v
* +-------+----+
* | |XXXX|
* +-------+----+
*/
size = (from_offset - to_offset) * sizeof(MemByte_t);
memset(&M->memory[to_offset + Byte_size], 0, size);
}
else {
/*
* from_offset
* |
* v
* +-------+
* | |
* +-------+
*
* move direction
* ------->>
*
* unused area
* |
* | to_offset
* | |
* v v
* +----+-------+
* |XXXX| |
* +----+-------+
*/
size = (to_offset - from_offset) * sizeof(MemByte_t);
memset(&M->memory[from_offset], 0, size);
}
return;
}
M = M->next;
}
}
/*------------------------------------------------------------------------------------------------*/
FUNC(void) gp_mem_b_delete(MemBlock_t *M, unsigned Byte_address) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
MemByte_t *b;
size_t size;
while (M) {
if (M->base == block) {
if (M->memory) {
b = &M->memory[offset];
if (b->section_name) {
free(b->section_name);
}
if (b->symbol_name) {
free(b->symbol_name);
}
size = (I_MEM_MAX - offset) * sizeof(MemByte_t);
if (size != 0) {
memmove(b, &M->memory[offset + 1], size);
}
memset(&M->memory[I_MEM_MAX], 0, sizeof(MemByte_t));
}
return;
}
M = M->next;
}
}
/*------------------------------------------------------------------------------------------------*/
FUNC(void) gp_mem_b_delete_area(MemBlock_t *M, unsigned Byte_address, unsigned Byte_number) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
MemByte_t *b;
unsigned remnant_byte_num;
unsigned i;
if (Byte_number == 0) {
return;
}
while (M) {
if (M->base == block) {
if (M->memory) {
remnant_byte_num = I_MEM_MAX - offset;
assert(Byte_number <= remnant_byte_num);
remnant_byte_num -= Byte_number;
for (b = &M->memory[offset], i = Byte_number; i > 0; ++b, --i) {
if (b->section_name) {
free(b->section_name);
}
if (b->symbol_name) {
free(b->symbol_name);
}
}
/*
* Before the deleting.
*
* block (from byte_address)
* | offset (from byte_address)
* | | byte_number
* v v | remnant_byte_num
* +----+---|----+---------|---------+
* | |<--^--->|<--------^-------->|
* +----+--------+-------------------+
* <---------------v--------------->
* |
* I_MEM_MAX
*/
if (remnant_byte_num != 0) {
/* Delete the designated area. */
memmove(&M->memory[offset], &M->memory[offset + Byte_number], remnant_byte_num * sizeof(MemByte_t));
}
/*
* After the deleting.
*
* block (from byte_address)
* | offset (from byte_address)
* | | remnant_byte_num
* v v | empty_area = byte_number
* +----+---------|---------+---|----+
* | |<--------^-------->|<--^--->|
* +----+-------------------+--------+
* <---------------v--------------->
* |
* I_MEM_MAX
*/
/* Clear the empty area. */
memset(&M->memory[offset + remnant_byte_num], 0, Byte_number * sizeof(MemByte_t));
}
return;
}
M = M->next;
}
}
/*------------------------------------------------------------------------------------------------*/
FUNC(unsigned) b_range_memory_used(const MemBlock_t *M, unsigned From_byte_address, unsigned To_byte_address) {
unsigned i;
unsigned j;
unsigned starting_block;
unsigned block;
unsigned n_bytes;
j = 0;
block = 0;
starting_block = IMemBaseFromAddr(From_byte_address);
/* find the starting block */
while ((M) && (block < starting_block)) {
j += I_MEM_MAX;
M = M->next;
++block;
}
n_bytes = 0;
/* count used bytes */
while ((M) && (j < To_byte_address)) {
for (i = 0; (i < I_MEM_MAX) && (j < To_byte_address); ++i) {
if ((M->memory) && M->memory[i].data.is_byte_used) {
++n_bytes;
}
++j;
}
M = M->next;
}
return n_bytes;
}
/*------------------------------------------------------------------------------------------------*/
FUNC(unsigned) gp_mem_b_used(const MemBlock_t *M) {
return b_range_memory_used(M, 0, UINT_MAX);
}
/**************************************************************************************************
*
*
* These functions are used to read and write instruction memory.
*
*
**************************************************************************************************/
FUNC(unsigned) gp_mem_i_offset_is_used_le(MemBlock_t *M, unsigned Byte_offset) {
unsigned ret;
ret = (gp_mem_b_offset_is_used(M, Byte_offset)) ? W_USED_L : 0;
ret |= (gp_mem_b_offset_is_used(M, Byte_offset + 1)) ? W_USED_H : 0;
return ret;
}
/*------------------------------------------------------------------------------------------------*/
unsigned gp_mem_i_get_le(const MemBlock_t *M, unsigned Byte_address, uint16_t *Word,
const char **Section_name, const char **Symbol_name) {
unsigned ret;
bword_t bw;
ret = (gp_mem_b_get(M, Byte_address, &bw.b[0], Section_name, Symbol_name)) ? W_USED_L : 0;
ret |= (gp_mem_b_get(M, Byte_address + 1, &bw.b[1], NULL, NULL)) ? W_USED_H : 0;
*Word = bw.w;
return ret;
}
/*------------------------------------------------------------------------------------------------*/
void gp_mem_i_put_le(MemBlock_t *M, unsigned Byte_address, unsigned Word,
const char *Section_name, const char *Symbol_name) {
assert(Word<65536);
gp_mem_b_put(M, Byte_address, (uint8_t)Word, Section_name, Symbol_name);
gp_mem_b_put(M, Byte_address + 1, (uint8_t)(Word>>8), Section_name, Symbol_name);
}
/*------------------------------------------------------------------------------------------------*/
unsigned gp_mem_i_offset_is_used_be(MemBlock_t *M, unsigned Byte_offset) {
unsigned ret;
ret = (gp_mem_b_offset_is_used(M, Byte_offset)) ? W_USED_H : 0;
ret |= (gp_mem_b_offset_is_used(M, Byte_offset + 1)) ? W_USED_L : 0;
return ret;
}
/*------------------------------------------------------------------------------------------------*/
unsigned gp_mem_i_get_be(const MemBlock_t *M, unsigned Byte_address, uint16_t *Word,
const char **Section_name, const char **Symbol_name) {
unsigned ret;
bword_t bw;
ret = (gp_mem_b_get(M, Byte_address, &bw.b[1], Section_name, Symbol_name)) ? W_USED_H : 0;
ret |= (gp_mem_b_get(M, Byte_address + 1, &bw.b[0], NULL, NULL)) ? W_USED_L : 0;
*Word = bw.w;
return ret;
}
/*------------------------------------------------------------------------------------------------*/
void gp_mem_i_put_be(MemBlock_t *M, unsigned Byte_address, unsigned Word,
const char *Section_name, const char *Symbol_name) {
assert(Word<65536);
gp_mem_b_put(M, Byte_address, (uint8_t)(Word>>8), Section_name, Symbol_name);
gp_mem_b_put(M, Byte_address + 1, (uint8_t)Word, Section_name, Symbol_name);
}
/*------------------------------------------------------------------------------------------------*/
void gp_mem_i_delete(MemBlock_t *m, unsigned byte_address) {
gp_mem_b_delete(m, byte_address);
gp_mem_b_delete(m, byte_address);
}
/*------------------------------------------------------------------------------------------------*/
FUNC(void) gp_mem_i_print(const MemBlock_t *M, pic_processor_t Processor) {
proc_class_t pclass;
unsigned byte_addr;
unsigned i;
unsigned j;
unsigned org;
bool row_used;
unsigned w_used;
bword_t data;
uint8_t c;
#define WORDS_IN_ROW 8
pclass = Processor->pclass;
while (M) {
if (M->memory) {
byte_addr = IMemAddrFromBase(M->base);
for (i = 0; i < I_MEM_MAX; i += 2 * WORDS_IN_ROW) {
row_used = false;
for (j = 0; j < (2 * WORDS_IN_ROW); j++) {
if (M->memory[i + j].data.all != 0) {
row_used = true;
break;
}
}
if (row_used) {
org = gp_processor_insn_from_byte_p(Processor, byte_addr + i);
printf("%08X ", org);
if ((gp_processor_is_eeprom_org(Processor, org) >= 0) ||
((pclass == PROC_CLASS_PIC16E) &&
((gp_processor_is_idlocs_org(Processor, org) >= 0) ||
(gp_processor_is_config_org(Processor, org) >= 0)))) {
/* The row should be shown byte by byte. */
for (j = 0; j < (2 * WORDS_IN_ROW); j++) {
if (gp_mem_b_get(M, byte_addr + i + j, &data.b[0], NULL, NULL)) {
printf("%02X ", data.b[0]);
}
else {
printf("-- ");
}
}
for (j = 0; j < (2 * WORDS_IN_ROW); j++) {
c = M->memory[i + j].data.byte;
putchar(isprint(c) ? c : '.');
}
}
else {
/* The row should be shown word by word. */
for (j = 0; j < WORDS_IN_ROW; j++) {
w_used = pclass->i_memory_get(M, byte_addr + i + (j * 2), &data.w, NULL, NULL);
switch (w_used & W_USED_ALL) {
case W_USED_ALL:
printf("%04X ", data.w);
break;
case W_USED_H:
printf("%02X-- ", data.b[1]);
break;
case W_USED_L:
printf("--%02X ", data.b[0]);
break;
default:
printf("---- ");
}
}
for (j = 0; j < (2 * WORDS_IN_ROW); j++) {
c = M->memory[i + j].data.byte;
putchar(isprint(c) ? c : '.');
}
}
putchar('\n');
}
}
}
M = M->next;
}
}
/**************************************************************************************************
*
*
* These functions are used to mark memory as listed.
*
*
**************************************************************************************************/
FUNC(void) gp_mem_b_set_listed(MemBlock_t *M, unsigned Byte_address, unsigned N_bytes) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
while (N_bytes--) {
while (M) {
if (M->base == block) {
if (!M->memory) {
M->memory = new MemByte_t[I_MEM_MAX];
memset(M->memory,0,sizeof*M->memory);
}
M->memory[offset].data.is_byte_listed = true;
break;
}
M = M->next;
}
++Byte_address;
}
}
/*------------------------------------------------------------------------------------------------*/
FUNC(unsigned) gp_mem_b_get_unlisted_size(const MemBlock_t *M, unsigned Byte_address) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned n_bytes = 0;
if ((M) && (M->memory)) {
while (n_bytes < 4) {
/* find memory block belonging to the byte_address */
while (block != M->base) {
M = M->next;
if (M == NULL) {
return n_bytes;
}
}
if ((M->memory) && (!M->memory[IMemOffsFromAddr(Byte_address)].data.is_byte_listed)) {
/* byte at byte_address not listed */
++Byte_address;
++n_bytes;
}
else {
/* byte at byte_address already listed */
break;
}
}
}
return n_bytes;
}
/*------------------------------------------------------------------------------------------------*/
FUNC(bool) gp_mem_b_set_addr_type(MemBlock_t *M, unsigned Byte_address, unsigned Type,
unsigned Dest_byte_addr) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
MemByte_t *b;
while (M) {
if ((M->base == block) && (M->memory)) {
b = &M->memory[offset];
if (b->data.is_byte_used) {
b->data.all |= Type & W_ADDR_T_MASK;
if (Type & W_ADDR_T_BRANCH_SRC) {
b->dest_byte_addr = Dest_byte_addr;
}
return true;
}
break;
}
M = M->next;
}
return false;
}
/*------------------------------------------------------------------------------------------------*/
FUNC(unsigned) gp_mem_b_get_addr_type(const MemBlock_t *M, unsigned Byte_address,
const char **Label_name, unsigned *Dest_byte_addr) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
MemByte_t *b;
while (M) {
if ((M->base == block) && (M->memory)) {
b = &M->memory[offset];
if (Label_name) {
*Label_name = (b->data.all & (W_ADDR_T_FUNC | W_ADDR_T_LABEL)) ? b->symbol_name : NULL;
}
if (Dest_byte_addr) {
*Dest_byte_addr = (b->data.all & W_ADDR_T_BRANCH_SRC) ? b->dest_byte_addr : 0;
}
return (b->data.all & W_ADDR_T_MASK);
}
M = M->next;
}
if (Label_name) {
*Label_name = NULL;
}
if (Dest_byte_addr) {
*Dest_byte_addr = 0;
}
return 0;
}
/*------------------------------------------------------------------------------------------------*/
FUNC(bool) gp_mem_b_set_addr_name(MemBlock_t *M, unsigned Byte_address, const char *Name) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
MemByte_t *b;
while (M) {
if ((M->base == block) && (M->memory)) {
b = &M->memory[offset];
if (b->symbol_name == NULL) {
_store_symbol_name(b, Name);
}
return true;
}
M = M->next;
}
return false;
}
/*------------------------------------------------------------------------------------------------*/
bool
gp_mem_b_set_args(MemBlock_t *M, unsigned Byte_address, unsigned Type, const MemArgList_t *Args)
{
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
MemByte_t *b;
while (M) {
if ((M->base == block) && (M->memory)) {
b = &M->memory[offset];
if (b->data.is_byte_used) {
b->data.all |= Type & W_ARG_T_MASK;
if (Type & W_ARG_T_FIRST) {
b->args.first.arg = Args->first.arg;
b->args.first.val = Args->first.val;
b->args.first.offs = Args->first.offs;
}
if (Type & W_ARG_T_SECOND) {
b->args.second.arg = Args->second.arg;
b->args.second.val = Args->second.val;
b->args.second.offs = Args->second.offs;
}
return true;
}
break;
}
M = M->next;
}
return false;
}
/*------------------------------------------------------------------------------------------------*/
unsigned
gp_mem_b_get_args(const MemBlock_t *M, unsigned Byte_address, MemArgList_t *Args)
{
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
MemByte_t *b;
while (M) {
if ((M->base == block) && (M->memory)) {
b = &M->memory[offset];
if (b->data.is_byte_used) {
if (Args) {
if (b->data.is_arg_first) {
Args->first.arg = b->args.first.arg;
Args->first.val = b->args.first.val;
Args->first.offs = b->args.first.offs;
}
else {
Args->first.arg = NULL;
Args->first.val = 0;
Args->first.offs = 0;
}
if (b->data.is_arg_second) {
Args->second.arg = b->args.second.arg;
Args->second.val = b->args.second.val;
Args->second.offs = b->args.second.offs;
}
else {
Args->second.arg = NULL;
Args->second.val = 0;
Args->second.offs = 0;
}
}
return (b->data.all & W_ARG_T_MASK);
}
}
M = M->next;
}
if (Args) {
Args->first.arg = NULL;
Args->first.val = 0;
Args->first.offs = 0;
Args->second.arg = NULL;
Args->second.val = 0;
Args->second.offs = 0;
}
return 0;
}
/*------------------------------------------------------------------------------------------------*/
FUNC(bool) gp_mem_b_set_type(MemBlock_t *M, unsigned Byte_address, unsigned Type) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
while (M) {
if ((M->base == block) && (M->memory)) {
M->memory[offset].data.all |= Type & W_TYPE_MASK;
return true;
}
M = M->next;
}
return false;
}
/*------------------------------------------------------------------------------------------------*/
bool
gp_mem_b_clear_type(MemBlock_t *M, unsigned Byte_address, unsigned Type)
{
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
while (M) {
if ((M->base == block) && (M->memory)) {
M->memory[offset].data.all &= ~(Type & W_TYPE_MASK);
return true;
}
M = M->next;
}
return false;
}
/*------------------------------------------------------------------------------------------------*/
FUNC(unsigned) gp_mem_b_get_type(const MemBlock_t *M, unsigned Byte_address) {
unsigned block = IMemBaseFromAddr(Byte_address);
unsigned offset = IMemOffsFromAddr(Byte_address);
while (M) {
if ((M->base == block) && (M->memory)) {
return (M->memory[offset].data.all & W_TYPE_MASK);
}
M = M->next;
}
return 0;
}
Detected encoding: UTF-8 | 0
|