mirror of
https://github.com/open-simh/simtools.git
synced 2026-03-03 10:06:36 +00:00
Optimize the previous version.
Fold the functionality of pull_up_reg() into evaluate_rec(). pull_up_reg() essentially returned a flag (EX_REG at the top, or not) which can be represented with the outgoing flags word. The check for recursion depth is made unneeded by doing the "exceptional" case outside the recursion; luckily it is actually the common case.
This commit is contained in:
@@ -527,7 +527,7 @@ void mode_extension(
|
||||
else
|
||||
store_global_offset_word(str, tr, 2, offset, sym->label);
|
||||
} else if (sym->section->type == SECTION_REGISTER) {
|
||||
/* Delayed action: evaluate_rec() excludes SECTION_REGISTER when
|
||||
/* Delayed action: evaluate() excludes SECTION_REGISTER when
|
||||
* turning symbols into EX_LIT. Do it here now. */
|
||||
store_word(str, tr, 2, sym->value + offset);
|
||||
} else {
|
||||
@@ -671,7 +671,7 @@ void store_value(
|
||||
if (SYM_IS_IMPORTED(sym)) {
|
||||
store_global_offset_word(stack->top, tr, size, sym->value + offset, sym->label);
|
||||
} else if (sym->section->type == SECTION_REGISTER) {
|
||||
/* Delayed action: evaluate_rec() excludes SECTION_REGISTER when
|
||||
/* Delayed action: evaluate() excludes SECTION_REGISTER when
|
||||
* turning symbols into EX_LIT. Do it here now. */
|
||||
store_word(stack->top, tr, size, sym->value + offset);
|
||||
} else if (sym->section != current_pc->section) {
|
||||
|
||||
243
extree.c
243
extree.c
@@ -304,133 +304,6 @@ EX_TREE *dup_tree(
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lift any EX_REG nodes to a higher level in the tree.
|
||||
*
|
||||
* There will be at most 1 EX_REG label left in the tree, if any,
|
||||
* and when it's there it is at the root.
|
||||
*
|
||||
* This whole complicated tree manipulation is only there because
|
||||
* DEC's Macro11 has a global bit per expression to indicate it
|
||||
* is a register... probably added after the fact without regard
|
||||
* of the weird expressions it would allow.
|
||||
*/
|
||||
|
||||
EX_TREE *pull_up_reg(
|
||||
EX_TREE *tp,
|
||||
int depth)
|
||||
{
|
||||
EX_TREE *res;
|
||||
int nsubtrees;
|
||||
|
||||
if (!tp)
|
||||
return tp;
|
||||
|
||||
/* Eliminate multiple levels of EX_REG */
|
||||
if (tp->type == EX_REG) {
|
||||
#if DEBUG_REGEXPR
|
||||
fprintf(stderr, "pull_up_reg: initial EX_REG: ");
|
||||
print_tree(stderr, tp, 0);
|
||||
#endif /* DEBUG_REGEXPR */
|
||||
|
||||
res = pull_up_reg(tp->data.child.left, depth + 1);
|
||||
if (res->type != EX_REG) {
|
||||
res = new_ex_una(EX_REG, res);
|
||||
}
|
||||
#if DEBUG_REGEXPR
|
||||
fprintf(stderr, "pull_up_reg: pulled up EX_REG: ");
|
||||
print_tree(stderr, res, 0);
|
||||
#endif /* DEBUG_REGEXPR */
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
nsubtrees = num_subtrees(tp);
|
||||
|
||||
if (nsubtrees > 0) {
|
||||
EX_TREE *left = tp->data.child.left,
|
||||
*right = tp->data.child.right,
|
||||
*evalleft,
|
||||
*evalright;
|
||||
int lifted = 0;
|
||||
|
||||
#if DEBUG_REGEXPR
|
||||
fprintf(stderr, "pull_up_reg: before: ");
|
||||
print_tree(stderr, tp, 0);
|
||||
#endif /* DEBUG_REGEXPR */
|
||||
|
||||
left = pull_up_reg(left, depth + 1);
|
||||
|
||||
evalleft = left;
|
||||
if (left && left->type == EX_REG) {
|
||||
#if DEBUG_REGEXPR
|
||||
if (tp->type == EX_REG) {
|
||||
fprintf(stderr, "pull_up_reg: left->type == EX_REG while tp->type==EX_REG\n");
|
||||
}
|
||||
#endif /* DEBUG_REGEXPR */
|
||||
evalleft = left->data.child.left;
|
||||
free(left);
|
||||
lifted++;
|
||||
}
|
||||
|
||||
if (nsubtrees > 1) {
|
||||
right = pull_up_reg(right, depth + 1);
|
||||
|
||||
evalright = right;
|
||||
if (right && right->type == EX_REG) {
|
||||
evalright = right->data.child.left;
|
||||
free(right);
|
||||
lifted++;
|
||||
}
|
||||
} else {
|
||||
evalright = NULL;
|
||||
}
|
||||
|
||||
res = new_ex_tree(tp->type);
|
||||
res->data.child.left = evalleft;
|
||||
res->data.child.right = evalright;
|
||||
res->cp = tp->cp;
|
||||
|
||||
if (lifted) {
|
||||
res = new_ex_una(EX_REG, res);
|
||||
|
||||
#if DEBUG_REGEXPR
|
||||
fprintf(stderr, "pull_up_reg: after: ");
|
||||
print_tree(stderr, res, 0);
|
||||
#endif /* DEBUG_REGEXPR */
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
if (depth > 0 && tp->type == EX_SYM) {
|
||||
/*
|
||||
* Temporarily change R0 into %0.
|
||||
* We only bother to do this in nested expressions, because for
|
||||
* the common case where R0 is the whole expression this makes
|
||||
* no sense.
|
||||
*/
|
||||
int regno = get_register(tp);
|
||||
|
||||
if (regno != NO_REG) {
|
||||
#if DEBUG_REGEXPR
|
||||
fprintf(stderr, "pull_up_reg: label `");
|
||||
print_tree(stderr, tp, 1);
|
||||
#endif /* DEBUG_REGEXPR */
|
||||
res = new_ex_lit(regno);
|
||||
res->cp = tp->cp;
|
||||
res = new_ex_una(EX_REG, res);
|
||||
#if DEBUG_REGEXPR
|
||||
fprintf(stderr, "' to ");
|
||||
print_tree(stderr, res, 0);
|
||||
#endif /* DEBUG_REGEXPR */
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return dup_tree(tp);
|
||||
}
|
||||
|
||||
#define RELTYPE(tp) (((tp)->type == EX_SYM || (tp)->type == EX_TEMP_SYM) && \
|
||||
(tp)->data.symbol->section->flags & PSECT_REL)
|
||||
|
||||
@@ -439,7 +312,8 @@ EX_TREE *pull_up_reg(
|
||||
Leaves the input tree untouched and creates a new tree as result. */
|
||||
EX_TREE *evaluate_rec(
|
||||
EX_TREE *tp,
|
||||
int flags)
|
||||
int flags,
|
||||
int *outflags)
|
||||
{
|
||||
EX_TREE *res;
|
||||
char *cp = tp->cp;
|
||||
@@ -480,9 +354,13 @@ EX_TREE *evaluate_rec(
|
||||
|
||||
/* Turn defined absolute symbol to a literal */
|
||||
if (!(sym->section->flags & PSECT_REL)
|
||||
&& !SYM_IS_IMPORTED(sym)
|
||||
&& sym->section->type != SECTION_REGISTER) {
|
||||
&& !SYM_IS_IMPORTED(sym)) {
|
||||
res = new_ex_lit(sym->value);
|
||||
|
||||
if (sym->section->type == SECTION_REGISTER) {
|
||||
*outflags |= EVALUATE_OUT_IS_REGISTER;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -512,7 +390,7 @@ EX_TREE *evaluate_rec(
|
||||
|
||||
case EX_COM:
|
||||
/* Complement */
|
||||
tp = evaluate_rec(tp->data.child.left, flags);
|
||||
tp = evaluate_rec(tp->data.child.left, flags, outflags);
|
||||
if (tp->type == EX_LIT) {
|
||||
/* Complement the literal */
|
||||
res = new_ex_lit(~tp->data.lit);
|
||||
@@ -525,7 +403,7 @@ EX_TREE *evaluate_rec(
|
||||
break;
|
||||
|
||||
case EX_NEG:
|
||||
tp = evaluate_rec(tp->data.child.left, flags);
|
||||
tp = evaluate_rec(tp->data.child.left, flags, outflags);
|
||||
if (tp->type == EX_LIT) {
|
||||
/* negate literal */
|
||||
res = new_ex_lit((unsigned) -(int) tp->data.lit);
|
||||
@@ -545,6 +423,11 @@ EX_TREE *evaluate_rec(
|
||||
}
|
||||
break;
|
||||
|
||||
case EX_REG:
|
||||
res = evaluate_rec(tp->data.child.left, flags, outflags);
|
||||
*outflags |= EVALUATE_OUT_IS_REGISTER;
|
||||
break;
|
||||
|
||||
case EX_ERR:
|
||||
/* Copy */
|
||||
res = dup_tree(tp);
|
||||
@@ -555,8 +438,8 @@ EX_TREE *evaluate_rec(
|
||||
EX_TREE *left,
|
||||
*right;
|
||||
|
||||
left = evaluate_rec(tp->data.child.left, flags);
|
||||
right = evaluate_rec(tp->data.child.right, flags);
|
||||
left = evaluate_rec(tp->data.child.left, flags, outflags);
|
||||
right = evaluate_rec(tp->data.child.right, flags, outflags);
|
||||
|
||||
/* Both literals? Sum them and return result. */
|
||||
if (left->type == EX_LIT && right->type == EX_LIT) {
|
||||
@@ -631,8 +514,8 @@ EX_TREE *evaluate_rec(
|
||||
EX_TREE *left,
|
||||
*right;
|
||||
|
||||
left = evaluate_rec(tp->data.child.left, flags);
|
||||
right = evaluate_rec(tp->data.child.right, flags);
|
||||
left = evaluate_rec(tp->data.child.left, flags, outflags);
|
||||
right = evaluate_rec(tp->data.child.right, flags, outflags);
|
||||
|
||||
/* Both literals? Subtract them and return a lit. */
|
||||
if (left->type == EX_LIT && right->type == EX_LIT) {
|
||||
@@ -707,8 +590,8 @@ EX_TREE *evaluate_rec(
|
||||
EX_TREE *left,
|
||||
*right;
|
||||
|
||||
left = evaluate_rec(tp->data.child.left, flags);
|
||||
right = evaluate_rec(tp->data.child.right, flags);
|
||||
left = evaluate_rec(tp->data.child.left, flags, outflags);
|
||||
right = evaluate_rec(tp->data.child.right, flags, outflags);
|
||||
|
||||
/* Can only multiply if both are literals */
|
||||
if (left->type == EX_LIT && right->type == EX_LIT) {
|
||||
@@ -769,8 +652,8 @@ EX_TREE *evaluate_rec(
|
||||
EX_TREE *left,
|
||||
*right;
|
||||
|
||||
left = evaluate_rec(tp->data.child.left, flags);
|
||||
right = evaluate_rec(tp->data.child.right, flags);
|
||||
left = evaluate_rec(tp->data.child.left, flags, outflags);
|
||||
right = evaluate_rec(tp->data.child.right, flags, outflags);
|
||||
|
||||
/* Can only divide if both are literals */
|
||||
if (left->type == EX_LIT && right->type == EX_LIT) {
|
||||
@@ -797,8 +680,8 @@ EX_TREE *evaluate_rec(
|
||||
EX_TREE *left,
|
||||
*right;
|
||||
|
||||
left = evaluate_rec(tp->data.child.left, flags);
|
||||
right = evaluate_rec(tp->data.child.right, flags);
|
||||
left = evaluate_rec(tp->data.child.left, flags, outflags);
|
||||
right = evaluate_rec(tp->data.child.right, flags, outflags);
|
||||
|
||||
/* Operate if both are literals */
|
||||
if (left->type == EX_LIT && right->type == EX_LIT) {
|
||||
@@ -842,8 +725,8 @@ EX_TREE *evaluate_rec(
|
||||
EX_TREE *left,
|
||||
*right;
|
||||
|
||||
left = evaluate_rec(tp->data.child.left, flags);
|
||||
right = evaluate_rec(tp->data.child.right, flags);
|
||||
left = evaluate_rec(tp->data.child.left, flags, outflags);
|
||||
right = evaluate_rec(tp->data.child.right, flags, outflags);
|
||||
|
||||
/* Operate if both are literals */
|
||||
if (left->type == EX_LIT && right->type == EX_LIT) {
|
||||
@@ -887,8 +770,8 @@ EX_TREE *evaluate_rec(
|
||||
EX_TREE *left,
|
||||
*right;
|
||||
|
||||
left = evaluate_rec(tp->data.child.left, flags);
|
||||
right = evaluate_rec(tp->data.child.right, flags);
|
||||
left = evaluate_rec(tp->data.child.left, flags, outflags);
|
||||
right = evaluate_rec(tp->data.child.right, flags, outflags);
|
||||
|
||||
/* Operate if both are literals */
|
||||
if (left->type == EX_LIT && right->type == EX_LIT) {
|
||||
@@ -940,6 +823,7 @@ EX_TREE *evaluate_rec(
|
||||
}
|
||||
|
||||
res->cp = cp;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -947,50 +831,47 @@ EX_TREE *evaluate(
|
||||
EX_TREE *tp,
|
||||
int flags)
|
||||
{
|
||||
EX_TREE *pulled_up,
|
||||
*res;
|
||||
int is_register = 0;
|
||||
EX_TREE *res;
|
||||
int outflags = 0;
|
||||
|
||||
#if DEBUG_REGEXPR
|
||||
fprintf(stderr, "Before pull_up_reg: ");
|
||||
fprintf(stderr, "evaluate: ");
|
||||
print_tree(stderr, tp, 0);
|
||||
#endif /* DEBUG_REGEXPR */
|
||||
/*
|
||||
* Check the common simple case for register references: R0...PC.
|
||||
* Copy those directly, without going into the recursion.
|
||||
* Therefore, in the recursion it can be assumed that the expression
|
||||
* is more complex, and it is worth the overhead of converting them
|
||||
* to an EX_LIT plus the EVALUATE_OUT_IS_REGISTER flag
|
||||
* (and back again, up here).
|
||||
*/
|
||||
if (tp->type == EX_SYM &&
|
||||
tp->data.symbol->section->type == SECTION_REGISTER &&
|
||||
!SYM_IS_IMPORTED(tp->data.symbol)) {
|
||||
res = dup_tree(tp);
|
||||
} else {
|
||||
res = evaluate_rec(tp, flags, &outflags);
|
||||
|
||||
pulled_up = pull_up_reg(tp, 0);
|
||||
if (outflags & EVALUATE_OUT_IS_REGISTER) {
|
||||
int regno = get_register(res);
|
||||
|
||||
if (regno == NO_REG) {
|
||||
report(NULL, "Register expression out of range.\n");
|
||||
#if DEBUG_REGEXPR
|
||||
fprintf(stderr, "After pull_up_reg: ");
|
||||
print_tree(stderr, pulled_up, 0);
|
||||
print_tree(stderr, tp, 0);
|
||||
print_tree(stderr, res, 0);
|
||||
#endif /* DEBUG_REGEXPR */
|
||||
/* TODO: maybe make this a EX_TEMP_SYM? */
|
||||
res = ex_err(res, res->cp);
|
||||
} else {
|
||||
EX_TREE *newresult = new_ex_tree(EX_SYM);
|
||||
|
||||
while (pulled_up->type == EX_REG) {
|
||||
EX_TREE *new = pulled_up->data.child.left;
|
||||
free(pulled_up);
|
||||
pulled_up = new;
|
||||
is_register = 1;
|
||||
}
|
||||
|
||||
res = evaluate_rec(pulled_up, flags);
|
||||
free_tree(pulled_up);
|
||||
|
||||
if (is_register) {
|
||||
int regno = get_register(res);
|
||||
|
||||
if (regno == NO_REG) {
|
||||
report(NULL, "Register expression out of range.\n");
|
||||
#if DEBUG_REGEXPR
|
||||
print_tree(stderr, tp, 0);
|
||||
print_tree(stderr, res, 0);
|
||||
#endif /* DEBUG_REGEXPR */
|
||||
/* TODO: maybe make this a EX_TEMP_SYM? */
|
||||
res = ex_err(res, res->cp);
|
||||
} else {
|
||||
EX_TREE *newresult = new_ex_tree(EX_SYM);
|
||||
|
||||
newresult->cp = res->cp;
|
||||
newresult->data.symbol = reg_sym[regno];
|
||||
free_tree(res);
|
||||
res = newresult;
|
||||
newresult->cp = res->cp;
|
||||
newresult->data.symbol = reg_sym[regno];
|
||||
free_tree(res);
|
||||
res = newresult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
extree.h
2
extree.h
@@ -79,4 +79,6 @@ EX_TREE *evaluate(
|
||||
|
||||
#define EVALUATE_DEFINEDNESS 1
|
||||
|
||||
#define EVALUATE_OUT_IS_REGISTER 1
|
||||
|
||||
#endif
|
||||
|
||||
@@ -69,48 +69,49 @@ test-reg.mac:44: ***ERROR Complex expression cannot be assigned to a symbol
|
||||
65 000064 010102 mov %<0+1>,r2 ; mov r1,r2
|
||||
66
|
||||
67 000066 010002 mov r0,r2 ; mov r0,r2
|
||||
68 000070 010102 mov r0+1,r2 ; mov r1,r2
|
||||
68 000070 010102 mov ----r1,<r2> ; mov r1,r2
|
||||
69 000072 010102 mov r0+1,r2 ; mov r1,r2
|
||||
**:0: ***ERROR Register expression out of range.
|
||||
test-reg.mac:69: ***ERROR Invalid addressing mode (1st operand: Invalid expression)
|
||||
69 mov r1+7,r2 ; error: too large
|
||||
70 ; R 58 000066 016702 000010' mov r1+7,r2 ; too large
|
||||
71
|
||||
72 ; this shows that after a % comes a unary expr,
|
||||
73 ; not an arbitrary binary expr:
|
||||
74 000006 l30 = 1+%2*2 ; %6.
|
||||
test-reg.mac:70: ***ERROR Invalid addressing mode (1st operand: Invalid expression)
|
||||
70 mov r1+7,r2 ; error: too large
|
||||
71 ; R 58 000066 016702 000010' mov r1+7,r2 ; too large
|
||||
72
|
||||
73 ; this shows that after a % comes a unary expr,
|
||||
74 ; not an arbitrary binary expr:
|
||||
75 000006 l30 = 1+%2*2 ; %6.
|
||||
**:0: ***ERROR Register expression out of range.
|
||||
test-reg.mac:75: ***ERROR Complex expression cannot be assigned to a symbol
|
||||
75 l31 = <1+%2>*3 ; %9. error: too large, but symbol is still defined (R error)
|
||||
test-reg.mac:76: ***ERROR Invalid expression (complex displaced relocation)
|
||||
76 000072 016700 000000 mov l31,r0 ; error: bad register; code 011100 (R error)
|
||||
77 000005 l32 = 1+%<2*2> ; %5
|
||||
78 000005 l33 = 1+<%2*2> ; %5
|
||||
79
|
||||
test-reg.mac:76: ***ERROR Complex expression cannot be assigned to a symbol
|
||||
76 l31 = <1+%2>*3 ; %9. error: too large, but symbol is still defined (R error)
|
||||
test-reg.mac:77: ***ERROR Invalid expression (complex displaced relocation)
|
||||
77 000074 016700 000000 mov l31,r0 ; error: bad register; code 011100 (R error)
|
||||
78 000005 l32 = 1+%<2*2> ; %5
|
||||
79 000005 l33 = 1+<%2*2> ; %5
|
||||
80
|
||||
81 000001 l20 = %l1
|
||||
82 000001 l21 = %l20
|
||||
83
|
||||
84 000001 l22 = l1 ; still a register
|
||||
85 000001 l23 = l22 ; still a register
|
||||
86
|
||||
87 .globl extrn
|
||||
81
|
||||
82 000001 l20 = %l1
|
||||
83 000001 l21 = %l20
|
||||
84
|
||||
85 000001 l22 = l1 ; still a register
|
||||
86 000001 l23 = l22 ; still a register
|
||||
87
|
||||
88 .globl extrn
|
||||
**:0: ***ERROR Register expression out of range.
|
||||
test-reg.mac:88: ***ERROR Complex expression cannot be assigned to a symbol
|
||||
88 l40 = %extrn ; A error; L40 =%******
|
||||
test-reg.mac:89: ***ERROR Invalid expression (complex displaced relocation)
|
||||
89 000076 016700 000000 mov l40,r0 ; U error; code 010000
|
||||
90
|
||||
91 000102 000000 000001 000002 .word r0,wait,r1+1,wait+2,%4 ; 0, 1, 2, 3, 4
|
||||
000110 000003 000004
|
||||
92
|
||||
93 .end
|
||||
94
|
||||
94
|
||||
test-reg.mac:89: ***ERROR Complex expression cannot be assigned to a symbol
|
||||
89 l40 = %extrn ; A error; L40 =%******
|
||||
test-reg.mac:90: ***ERROR Invalid expression (complex displaced relocation)
|
||||
90 000100 016700 000000 mov l40,r0 ; U error; code 010000
|
||||
91
|
||||
92 000104 000000 000001 000002 .word r0,wait,r1+1,wait+2,%4 ; 0, 1, 2, 3, 4
|
||||
000112 000003 000004
|
||||
93
|
||||
94 .end
|
||||
95
|
||||
95
|
||||
|
||||
|
||||
Symbol table
|
||||
|
||||
. = 000114 002 L11 =%000001 L21 =%000001 L33 =%000005 L8A =%000003
|
||||
. = 000116 002 L11 =%000001 L21 =%000001 L33 =%000005 L8A =%000003
|
||||
A = 000001 L12 =%000001 L22 =%000001 L4 =%000002 L9 =%000003
|
||||
B = 000002 L13 =%000007 L23 =%000001 L40 = ****** L9A =%000003
|
||||
EXTRN = ****** G L14 = ****** L3 =%000001 L5 =%000002 L9B =%000001
|
||||
@@ -123,4 +124,4 @@ Program sections:
|
||||
|
||||
. ABS. 000000 000 (RW,I,GBL,ABS,OVR,NOSAV)
|
||||
000000 001 (RW,I,LCL,REL,CON,NOSAV)
|
||||
ABS 000114 002 (RW,I,LCL,ABS,OVR,NOSAV)
|
||||
ABS 000116 002 (RW,I,LCL,ABS,OVR,NOSAV)
|
||||
|
||||
@@ -65,6 +65,7 @@ here: mov #here,%2
|
||||
mov %<0+1>,r2 ; mov r1,r2
|
||||
|
||||
mov r0,r2 ; mov r0,r2
|
||||
mov ----r1,<r2> ; mov r1,r2
|
||||
mov r0+1,r2 ; mov r1,r2
|
||||
mov r1+7,r2 ; error: too large
|
||||
; R 58 000066 016702 000010' mov r1+7,r2 ; too large
|
||||
|
||||
Reference in New Issue
Block a user