/* literals.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Literal Handling Functions */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <assert.h>
#include "strutil.h"
#include "errmsg.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmerr.h"
#include "literals.h"
/*---------------------------------------------------------------------------*/
as_literal_t *p_first_literal;
LongInt literal_forward_count;
/*---------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn literals_chk_alldone(void)
* \brief check whether all literals have been resolved
* ------------------------------------------------------------------------ */
void literals_chk_alldone(void)
{
while (p_first_literal)
{
as_literal_t *p_run;
WrError(ErrNum_MsgMissingLTORG);
p_run = p_first_literal;
p_first_literal = p_run->p_next;
literals_free(p_run);
}
}
/*!------------------------------------------------------------------------
* \fn literals_new(void)
* \brief create new literal
* \return * to new instance or NULL
* ------------------------------------------------------------------------ */
as_literal_t *literals_new(void)
{
as_literal_t
*p_ret
= (as_literal_t
*)calloc(1, sizeof(*p_ret
));
return p_ret;
}
/*!------------------------------------------------------------------------
* \fn literals_free(as_literal_t* p_literal)
* \brief destroy literal
* \param p_literalliteral to free
* ------------------------------------------------------------------------ */
void literals_free(as_literal_t* p_literal)
{
}
/*!------------------------------------------------------------------------
* \fn literals_get_name(const as_literal_t *p_lit, char *p_result, size_t result_size)
* \brief deduce name of literal
* \param p_lit literal in question
* \param p_result where to write result
* \param result_size capacity of buffer
* \return * to b uffer
* ------------------------------------------------------------------------ */
const char *literals_get_name(const as_literal_t *p_lit, char *p_result, size_t result_size)
{
as_snprintf(p_result, result_size, "LITERAL_");
if (p_lit->is_forward)
as_snprcatf(p_result, result_size, "F_%lllx", (LargeWord)p_lit->f_count);
else switch (p_lit->size)
{
case eSymbolSize32Bit:
as_snprcatf(p_result, result_size, "L_%08lllx", (LargeWord)p_lit->value);
break;
case eSymbolSize16Bit:
as_snprcatf(p_result, result_size, "W_%04x", (unsigned)p_lit->value);
break;
case eSymbolSize12Bit:
as_snprcatf(p_result, result_size, "W_%03x", (unsigned)p_lit->value);
break;
default:
}
as_snprcatf(p_result, result_size, "_%x", (unsigned)p_lit->pass_no);
return p_result;
}
/*!------------------------------------------------------------------------
* \fn literals_print(void)
* \brief dump current list of literals
* ------------------------------------------------------------------------ */
void literals_print(void)
{
as_literal_t *p_run;
String Name;
WrLstLine("LiteralList");
p_run = p_first_literal;
while (p_run)
{
literals_get_name(p_run, Name, sizeof(Name));
WrLstLine(Name); p_run = p_run->p_next;
}
}
/*!------------------------------------------------------------------------
* \fn literal_make(tStrComp *p_comp, Byte *p_data_offset, LongInt value, tSymbolSize value_size, Boolean force_create)
* \brief create/lookup literal, and return its symbolic name
* \param p_comp destination buffer for symbol name
* \param p_data_offset address offset into symbols's address (assuming big endian)
* \param value value of literal
* \param value_size operand size of literal
* \param force_create do not re-use esisting literals
* ------------------------------------------------------------------------ */
void literal_make(tStrComp *p_comp, Byte *p_data_offset, LongInt value, tSymbolSize value_size, Boolean force_create)
{
as_literal_t *p_run, *p_prev;
String name;
switch (value_size)
{
case eSymbolSize32Bit:
break;
case eSymbolSize16Bit:
value &= 0xffff;
break;
case eSymbolSize12Bit:
value &= 07777;
break;
default:
}
/* existing literal available? */
if (p_data_offset) *p_data_offset = 0;
for (p_run = p_first_literal, p_prev = NULL; p_run; p_prev = p_run, p_run = p_run->p_next)
{
if (!force_create && !p_run->is_forward && (p_run->def_section == MomSectionHandle))
{
if (((p_run->size == value_size) && (value == p_run->value))
|| ((p_run->size == eSymbolSize32Bit) && p_data_offset && (value_size == eSymbolSize16Bit) && (value == (p_run->value >> 16))))
break;
else if ((p_run->size == eSymbolSize32Bit) && p_data_offset && (value_size == eSymbolSize16Bit) && (value == (p_run->value & 0xffff)))
{
*p_data_offset = 2;
break;
}
}
}
/* no - create new one */
if (!p_run)
{
p_run = literals_new();
p_run->size = value_size;
p_run->value = value;
p_run->is_forward = force_create;
if (force_create)
p_run->f_count = literal_forward_count++;
p_run->def_section = MomSectionHandle;
for (p_run->pass_no = 1; ; p_run->pass_no++)
{
/* literals are section-specific */
as_snprintf(p_comp->str.p_str, p_comp->str.capacity, "%s[PARENT0]",
literals_get_name(p_run, name, sizeof(name)));
if (!IsSymbolDefined(p_comp))
break;
}
if (!p_prev)
p_first_literal = p_run;
else
p_prev->p_next = p_run;
}
else
{
as_snprintf(p_comp->str.p_str, p_comp->str.capacity, "%s[PARENT0]",
literals_get_name(p_run, name, sizeof(name)));
}
}
/*!------------------------------------------------------------------------
* \fn literals_dump(literal_dump_fnc_t dump, tSymbolSize value_size, LongInt section_handle, Boolean compress)
* \brief dump & free accumulated literals
* \param dump callback to actually dispose value in memory
* \param value_size only dump literals of given size
* \param section_handle only dump literals out of given section
* \param compress reference literals of same value to same address?
* ------------------------------------------------------------------------ */
void literals_dump(literal_dump_fnc_t dump, tSymbolSize value_size, LongInt section_handle, Boolean compress)
{
as_literal_t *p_curr, *p_last, *p_tmp;
LargeInt address;
String name;
tStrComp tmp_comp;
StrCompMkTemp(&tmp_comp, name, sizeof(name));
p_curr = p_first_literal;
p_last = NULL;
while (p_curr)
{
if ((p_curr->size == value_size) && (p_curr->def_section == section_handle))
{
literals_get_name(p_curr, name, sizeof(name));
address = dump(p_curr, &tmp_comp);
if (compress)
{
as_literal_t *p_eq_curr = p_curr->p_next, *p_eq_last = NULL;
while (p_eq_curr)
{
if ((p_eq_curr->size == value_size) && (p_eq_curr->def_section == section_handle) && (p_eq_curr->value == p_curr->value))
{
literals_get_name(p_eq_curr, name, sizeof(name));
EnterIntSymbol(&tmp_comp, address, ActPC, False);
p_tmp = p_eq_curr->p_next;
if (!p_eq_last)
p_curr->p_next = p_tmp;
else
p_eq_last->p_next = p_tmp;
literals_free(p_eq_curr);
p_eq_curr = p_tmp;
}
else
{
p_eq_last = p_eq_curr;
p_eq_curr = p_eq_curr->p_next;
}
}
}
p_tmp = p_curr->p_next;
if (!p_last)
p_first_literal = p_tmp;
else
p_last->p_next = p_tmp;
literals_free(p_curr);
p_curr = p_tmp;
}
else
{
p_last = p_curr;
p_curr = p_curr->p_next;
}
}
}
/*!------------------------------------------------------------------------
* \fn literals_init(void)
* \brief module initialization
* ------------------------------------------------------------------------ */
static void init_pass_literals(void)
{
literal_forward_count = 0;
}
void literals_init(void)
{
AddInitPassProc(init_pass_literals);
p_first_literal = NULL;
}