Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
salink: Move more code to expression.c
Some of the expression code was still in link_obj.c and the bank
associated with this file on the Next builds is running out of
bytes.  Move the remaining expression code into expression.c whose
associated bank has lots of free space.

Signed-off-by: Mark Ryan <[email protected]>
  • Loading branch information
markdryan committed Feb 4, 2024
commit e32d38d167042f3031d5dca7ddcf2dafd45fc8a7
237 changes: 229 additions & 8 deletions src/expression.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ const char *prv_get_token_e(const char *buf, salink_token_t *tok,

c = *start;
if ((c >= 'A') && (c <= 'Z')) {
tok->data.id = salink_find_global_label_e(scratch, g_obj);
tok->data.id =
salink_find_global_label_e(scratch, g_obj);
tok->type = SALINK_TOKEN_GLOBAL_LABEL;
} else {
tok->data.id =
Expand Down Expand Up @@ -293,7 +294,8 @@ static const char *prv_exp_priority0_e(const char *str, int16_t *e,
err_type = SALINK_ERROR_RECURISVE_EQU;
return NULL;
}
salink_equ_eval_global_e(g_obj, global, label, depth + 1);
salink_equ_eval_global_e(g_obj, global, label,
depth + 1);
if (err_type != SPECASM_ERROR_OK)
return NULL;
*e = label->data.off;
Expand Down Expand Up @@ -578,12 +580,8 @@ static void prv_check_equ_err(const char *name, const char *equ,
prv_check_exp_err(scratch, line_no, exact_line);
}

#ifdef SPECASM_NEXT_BANKED
int16_t salink_equ_eval_banked_e(salink_obj_t *obj, const char *str,
uint16_t line_no)
#else
int16_t salink_equ_eval_e(salink_obj_t *obj, const char *str, uint16_t line_no)
#endif
static int16_t prv_equ_eval_wrapper_e(salink_obj_t *obj, const char *str,
uint16_t line_no)
{
int16_t e;

Expand Down Expand Up @@ -638,3 +636,226 @@ void salink_equ_eval_global_e(salink_obj_t *obj, salink_global_t *global,

label->type = SALINK_LABEL_TYPE_EQU_EVAL_GLOBAL;
}

static int16_t prv_eval_exp_from_id_e(salink_obj_t *obj, unsigned int line_no,
uint8_t id, uint8_t lng)
{
const char *str;
int16_t exp;

str = salink_get_label_str_e(id, lng);
if (err_type != SPECASM_ERROR_OK)
return 0;

exp = prv_equ_eval_wrapper_e(obj, str, line_no);

if ((err_type != SPECASM_ERROR_OK) && (err_type < SPECASM_MAX_ERRORS)) {
snprintf(error_buf, sizeof(error_buf), "%s:%d %s", obj->fname,
line_no, specasm_error_msg(err_type));
err_type = SALINK_ERROR_BAD_EXP;
}

return exp;
}

static int16_t prv_eval_equ_label(specasm_line_t *line, salink_obj_t *obj,
unsigned int line_no, uint8_t id)
{
uint8_t label_type;
uint8_t lng;

label_type = specasm_line_get_addr_type(line);
lng = label_type == SPECASM_FLAGS_ADDR_SHORT ? 0 : 1;
return prv_eval_exp_from_id_e(obj, line_no, id, lng);
}

static void prv_eval_equ_8bit_e(specasm_line_t *line, salink_obj_t *obj,
unsigned int line_no, uint8_t loc)
{
int16_t exp;

exp = prv_eval_equ_label(line, obj, line_no, line->data.op_code[loc]);
if (err_type != SPECASM_ERROR_OK)
return;

if ((exp > 255) || (exp < -128)) {
snprintf(error_buf, sizeof(error_buf),
"%s:%d immediate too big :%d", obj->fname, line_no,
exp);
err_type = SALINK_ERROR_SIZE_TOO_BIG;
return;
}
line->data.op_code[loc] = exp;
}

static void prv_eval_equ_16bit_e(specasm_line_t *line, salink_obj_t *obj,
unsigned int line_no, uint8_t loc)
{
int16_t exp;

exp = prv_eval_equ_label(line, obj, line_no, line->data.op_code[loc]);
if (err_type != SPECASM_ERROR_OK)
return;

*((uint16_t *)&line->data.op_code[loc]) = exp;
}

#ifdef SPECASM_TARGET_NEXT_OPCODES
static void prv_eval_equ_push_imm_e(specasm_line_t *line, salink_obj_t *obj,
unsigned int line_no)
{
int16_t exp;
uint8_t exp_rev[2];

/*
* The push imm instruction is weird in that the immediate is encoded
* in big endian format. If we're dealing with an expression this means
* that the expression id will be in byte 3 and not byte 2 as one might
* expect.
*
* We also need to make sure we reverse the bytes of the evaluated
* expression.
*/

exp = prv_eval_equ_label(line, obj, line_no, line->data.op_code[3]);
if (err_type != SPECASM_ERROR_OK)
return;
memcpy(exp_rev, &exp, 2);
line->data.op_code[2] = exp_rev[1];
line->data.op_code[3] = exp_rev[0];
}
#endif

#ifdef SPECASM_NEXT_BANKED
void salink_apply_expressions_banked_e(specasm_line_t *line, salink_obj_t *obj,
unsigned int line_no)
#else
void salink_apply_expressions_e(specasm_line_t *line, salink_obj_t *obj,
unsigned int line_no)
#endif
{
int16_t exp;
uint8_t opcode0;

line->type -= SPECASM_LINE_TYPE_EXP_ADJ;

switch (line->type) {
case SPECASM_LINE_TYPE_ADC:
case SPECASM_LINE_TYPE_ADD:
case SPECASM_LINE_TYPE_AND:
case SPECASM_LINE_TYPE_CP:
case SPECASM_LINE_TYPE_IN:
case SPECASM_LINE_TYPE_OUT:
case SPECASM_LINE_TYPE_OR:
case SPECASM_LINE_TYPE_SBC:
case SPECASM_LINE_TYPE_SUB:
case SPECASM_LINE_TYPE_XOR:
#ifdef SPECASM_TARGET_NEXT_OPCODES
if ((line->type == SPECASM_LINE_TYPE_ADD) &&
(line->data.op_code[0] == 0xED))
prv_eval_equ_16bit_e(line, obj, line_no, 2);
else
prv_eval_equ_8bit_e(line, obj, line_no, 1);
#else
prv_eval_equ_8bit_e(line, obj, line_no, 1);
#endif
break;
case SPECASM_LINE_TYPE_RST:
exp = prv_eval_equ_label(line, obj, line_no,
line->data.op_code[1]);
if (err_type != SPECASM_ERROR_OK)
return;
if ((exp > 0x38) || (exp & 7)) {
snprintf(error_buf, sizeof(error_buf),
"%s:%d bad argument to rst :%d", obj->fname,
line_no, exp);
err_type = SALINK_ERROR_SIZE_TOO_BIG;
return;
}
line->data.op_code[0] |= exp;
break;
case SPECASM_LINE_TYPE_LD:
opcode0 = line->data.op_code[0];
if ((opcode0 & 0xC7) == 0x6) {
prv_eval_equ_8bit_e(line, obj, line_no, 1);
break;
}
switch (opcode0) {
case 0x1:
case 0x11:
case 0x21:
case 0x31:
case 0x2a:
case 0x3a:
case 0x22:
case 0x32:
prv_eval_equ_16bit_e(line, obj, line_no, 1);
break;
case 0xDD:
case 0xED:
case 0xFD:
prv_eval_equ_16bit_e(line, obj, line_no, 2);
break;
}
break;
case SPECASM_LINE_TYPE_BIT:
case SPECASM_LINE_TYPE_RES:
case SPECASM_LINE_TYPE_SET:
exp = prv_eval_equ_label(line, obj, line_no,
line->data.op_code[2]);
if (err_type != SPECASM_ERROR_OK)
return;
if (exp > 7) {
snprintf(error_buf, sizeof(error_buf),
"%s:%d bad bit position :%d", obj->fname,
line_no, exp);
err_type = SALINK_ERROR_SIZE_TOO_BIG;
return;
}
line->data.op_code[1] |= ((uint8_t)exp) << 3;
break;
case SPECASM_LINE_TYPE_IM:
exp = prv_eval_equ_label(line, obj, line_no,
line->data.op_code[2]);
if (err_type != SPECASM_ERROR_OK)
return;
if (exp > 2) {
snprintf(error_buf, sizeof(error_buf),
"%s:%d bad arg for im :%d", obj->fname,
line_no, exp);
err_type = SALINK_ERROR_SIZE_TOO_BIG;
return;
}
if (exp == 2)
line->data.op_code[1] = 0x5e;
else if (exp == 1)
line->data.op_code[1] = 0x56;
break;
case SPECASM_LINE_TYPE_CALL:
case SPECASM_LINE_TYPE_JP:
prv_eval_equ_16bit_e(line, obj, line_no, 1);
break;
case SPECASM_LINE_TYPE_DB:
prv_eval_equ_8bit_e(line, obj, line_no, 0);
break;
case SPECASM_LINE_TYPE_DW:
prv_eval_equ_16bit_e(line, obj, line_no, 0);
break;
#ifdef SPECASM_TARGET_NEXT_OPCODES
case SPECASM_LINE_TYPE_TEST:
case SPECASM_LINE_TYPE_NEXTREG:
prv_eval_equ_8bit_e(line, obj, line_no, 2);
break;
case SPECASM_LINE_TYPE_PUSH:
prv_eval_equ_push_imm_e(line, obj, line_no);
break;
#endif
default:
snprintf(error_buf, sizeof(error_buf),
"%s:%d unexpected expression", obj->fname, line_no);
err_type = SALINK_ERROR_UNEXPECTED_EXP;
break;
}

specasm_line_set_addr_type(line, SPECASM_FLAGS_ADDR_NUM);
}
3 changes: 2 additions & 1 deletion src/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@

#include "salink.h"

int16_t salink_equ_eval_e(salink_obj_t *obj, const char *str, uint16_t line_no);
void salink_apply_expressions_e(specasm_line_t *line, salink_obj_t *obj,
unsigned int line_no);
void salink_equ_eval_global_e(salink_obj_t *obj, salink_global_t *global,
salink_label_t *label, uint8_t depth);

Expand Down
Loading