mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-01-11 23:53:19 +00:00
169 lines
4.5 KiB
C
169 lines
4.5 KiB
C
/*
|
|
* expr.c
|
|
*/
|
|
#include <stdio.h>
|
|
#include "pdp10-arith.h"
|
|
#include "expr.h"
|
|
|
|
int eval(const struct expr *expr, struct value *value, int quiet)
|
|
{
|
|
switch (expr->tag) {
|
|
case E_UINTEGER:
|
|
value->section = SECTION_ABS;
|
|
value->offset = expr->u.e_uinteger.val;
|
|
break;
|
|
case E_SYMBOL:
|
|
xxx;
|
|
break;
|
|
case E_UNARY:
|
|
if (eval(expr->u.e_unary.expr, value, quiet) < 0)
|
|
return -1;
|
|
if (value->section != SECTION_ABS) {
|
|
if (!quiet)
|
|
fprintf(stderr, "as: %s(): unary operand is not absolute\n", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
switch (expr->u.e_unary.unop) {
|
|
case E_UMINUS:
|
|
value->offset = pdp10_neg_int36(value->offset);
|
|
break;
|
|
case E_NOT:
|
|
value->offset = pdp10_not_int36(value->offset);
|
|
break;
|
|
}
|
|
break;
|
|
case E_BINARY:
|
|
{
|
|
struct value value2;
|
|
|
|
if (eval(expr->u.e_binary.expr1, value, quiet) < 0
|
|
|| eval(expr->u.e_binary.expr2, &value2, quiet) < 0)
|
|
return -1;
|
|
|
|
switch (expr->u.e_binary.binop) {
|
|
case E_ADD:
|
|
if (value->section == SECTION_ABS)
|
|
value->section = value2.section;
|
|
else if (value2.section == SECTION_ABS)
|
|
;
|
|
else if (value->section == value2.section)
|
|
;
|
|
else {
|
|
if (!quiet)
|
|
fprintf(stderr, "as: %s(): adding operands from different sections\n", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
value->offset = pdp10_add_int36(value->offset, value2.offset);
|
|
return 0;
|
|
case E_SUB:
|
|
if (value2.section == SECTION_ABS)
|
|
;
|
|
else if (value->section == value2.section)
|
|
value->section = SECTION_ABS;
|
|
else {
|
|
if (!quiet)
|
|
fprintf(stderr, "as: %s(): subtracting operands from different sections\n", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
value->offset = pdp10_sub_int36(value->offset, value2.offset);
|
|
return 0;
|
|
default:
|
|
break;
|
|
}
|
|
if (value->section != SECTION_ABS
|
|
|| value2.section != SECTION_ABS) {
|
|
if (!quiet)
|
|
fprintf(stderr, "as: %s(): binary sub-<expr> is not absolute\n", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
switch (expr->u.e_binary.binop) {
|
|
case E_MUL:
|
|
value->offset = pdp10_mul_int36(value->offset, value2.offset);
|
|
break;
|
|
case E_DIV:
|
|
/* XXX: div-by-zero check */
|
|
value->offset = pdp10_div_int36(value->offset, value2.offset);
|
|
break;
|
|
case E_REM:
|
|
/* XXX: div-by-zero check */
|
|
value->offset = pdp10_rem_int36(value->offset, value2.offset);
|
|
break;
|
|
case E_LSHIFT:
|
|
/* XXX: range check */
|
|
value->offset = pdp10_asl_int36(value->offset, value2.offset);
|
|
break;
|
|
case E_RSHIFT:
|
|
/* XXX: range check */
|
|
value->offset = pdp10_asr_int36(value->offset, value2.offset);
|
|
break;
|
|
case E_OR:
|
|
value->offset = pdp10_or_int36(value->offset, value2.offset);
|
|
break;
|
|
case E_AND:
|
|
value->offset = pdp10_and_int36(value->offset, value2.offset);
|
|
break;
|
|
case E_XOR:
|
|
value->offset = pdp10_xor_int36(value->offset, value2.offset);
|
|
break;
|
|
case E_ORNOT:
|
|
value->offset = pdp10_or_int36(value->offset, pdp10_not_int36(value2.offset));
|
|
break;
|
|
case E_EQ:
|
|
value->offset = pdp10_eq_int36(value->offset, value2.offset) ? PDP10_UINT36_MAX : 0;
|
|
break;
|
|
case E_NE:
|
|
value->offset = pdp10_ne_int36(value->offset, value2.offset) ? PDP10_UINT36_MAX : 0;
|
|
break;
|
|
case E_LT:
|
|
value->offset = pdp10_lt_int36(value->offset, value2.offset) ? PDP10_UINT36_MAX : 0;
|
|
break;
|
|
case E_GT:
|
|
value->offset = pdp10_gt_int36(value->offset, value2.offset) ? PDP10_UINT36_MAX : 0;
|
|
break;
|
|
case E_GE:
|
|
value->offset = pdp10_ge_int36(value->offset, value2.offset) ? PDP10_UINT36_MAX : 0;
|
|
break;
|
|
case E_LE:
|
|
value->offset = pdp10_le_int36(value->offset, value2.offset) ? PDP10_UINT36_MAX : 0;
|
|
break;
|
|
case E_ANDAND:
|
|
value->offset = (pdp10_nonzero_int36(value->offset) && pdp10_nonzero_int36(value2.offset)) ? 1 : 0;
|
|
break;
|
|
case E_OROR:
|
|
value->offset = (pdp10_nonzero_int36(value->offset) || pdp10_nonzero_int36(value2.offset)) ? 1 : 0;
|
|
break;
|
|
default:
|
|
/* E_ADD / E_SUB cannot occur here, but the compiler may not see that */
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int eval_abs(const struct expr *expr, pdp10_uint36_t *offset, int quiet)
|
|
{
|
|
struct value value;
|
|
|
|
if (eval(expr, &value, quiet) < 0)
|
|
return -1;
|
|
if (value.section != SECTION_ABS) {
|
|
if (!quiet)
|
|
fprintf(stderr, "as: non-absolute expression\n");
|
|
return -1;
|
|
}
|
|
*offset = value.offset;
|
|
return 0;
|
|
}
|
|
|
|
int eval_abs_verbose(const struct expr *expr, pdp10_uint36_t *offset)
|
|
{
|
|
return eval_abs(expr, offset, 0);
|
|
}
|
|
|
|
int eval_abs_quiet(const struct expr *expr, pdp10_uint36_t *offset)
|
|
{
|
|
return eval_abs(expr, offset, 1);
|
|
}
|