Skip to content

Commit c6099d3

Browse files
authored
iss: Move bi-endian condition evaluation to DisasContext creation (#925)
- If the memory definition is bi-endian, the DisasContext gets a new field `endian_cond`, which stores the value of the bi-endian condition - The condition is evaluated once per TB instead of per instruction (fetch and memory op) - Added IssStaticEndianConditionNode, which is translated to `ctx->endian_cond`
1 parent 28fc8df commit c6099d3

8 files changed

Lines changed: 90 additions & 17 deletions

File tree

vadl/main/resources/templates/iss/target/gen-arch/translate.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,17 @@ typedef struct DisasContext {
4747
[/][/]
4848
} tb_state;
4949

50+
[# th:if="${mem_bi_endian}"]bool endian_cond;[/]
51+
5052
} DisasContext;
5153

5254
static bool swap_insn(const DisasContext *ctx) {
5355
// default byte order is LE, but VDT assumes BE
5456
[# th:if="${mem_bi_endian}"]
5557
#if TARGET_BIG_ENDIAN
56-
return [# th:unless="${mem_big_endian}"]![/]([(${bi_endian_condition})]);
58+
return [# th:unless="${mem_big_endian}"]![/]ctx->endian_cond;
5759
#else
58-
return [# th:if="${mem_big_endian}"]![/]([(${bi_endian_condition})]);
60+
return [# th:if="${mem_big_endian}"]![/]ctx->endian_cond;
5961
#endif
6062
[/][# th:unless="${mem_bi_endian}"]
6163
return true;
@@ -233,6 +235,8 @@ static void [(${gen_arch_lower})]_tr_init_disas_context(DisasContextBase *db, CP
233235
ctx->tb_state.[(${reg.name_lower})] |= ((flags >> off) & [(${part.mask})]) << [(${part.lsb})];
234236
off += [(${part.width})];
235237
[/][/][/]
238+
239+
[# th:if="${mem_bi_endian}"]ctx->endian_cond = [(${bi_endian_condition})];[/]
236240
}
237241

238242
static void [(${gen_arch_lower})]_tr_tb_start(DisasContextBase *db, CPUState *cpu)

vadl/main/vadl/iss/codegen/IssCMixins.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import vadl.iss.passes.nodes.IssGhostCastNode;
2525
import vadl.iss.passes.nodes.IssMoveNode;
2626
import vadl.iss.passes.nodes.IssSelectNode;
27+
import vadl.iss.passes.nodes.IssStaticEndianConditionNode;
2728
import vadl.iss.passes.nodes.IssStaticPcRegNode;
2829
import vadl.iss.passes.nodes.IssStaticReadRegNode;
2930
import vadl.iss.passes.nodes.IssTempExprNode;
@@ -357,6 +358,11 @@ default void handler(CGenContext<Node> ctx, IssStaticPcRegNode node) {
357358
ctx.wr("(ctx->pc_curr)");
358359
}
359360

361+
@Handler
362+
default void handler(CGenContext<Node> ctx, IssStaticEndianConditionNode node) {
363+
ctx.wr("(ctx->endian_cond)");
364+
}
365+
360366
@Handler
361367
default void handle(CGenContext<Node> ctx, IssStaticReadRegNode node) {
362368
ctx.wr("(ctx->tb_state." + node.regTensor().simpleName().toLowerCase() + ")");

vadl/main/vadl/iss/codegen/IssInstrHelperGenerator.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import vadl.iss.passes.extensions.InstrInfo;
2727
import vadl.iss.passes.extensions.IssAccessorRegistry;
2828
import vadl.iss.passes.nodes.IssRegBitfieldWriteNode;
29+
import vadl.iss.passes.nodes.IssStaticEndianConditionNode;
2930
import vadl.iss.passes.nodes.IssStaticPcRegNode;
3031
import vadl.iss.passes.nodes.IssStaticReadRegNode;
3132
import vadl.iss.passes.tcgLowering.Tcg_32_64;
@@ -184,6 +185,12 @@ void handle(CGenContext<Node> ctx, IssStaticPcRegNode toHandle) {
184185
throw new UnsupportedOperationException("Type IssStaticPcRegNode not yet implemented");
185186
}
186187

188+
@Handler
189+
void handle(CGenContext<Node> ctx, IssStaticEndianConditionNode toHandle) {
190+
throw new UnsupportedOperationException(
191+
"Type IssStaticEndianConditionNode not yet implemented");
192+
}
193+
187194
@Handler
188195
void handle(CGenContext<Node> ctx, IssStaticReadRegNode toHandle) {
189196
throw new UnsupportedOperationException("Type ReadStaticRegTensorNode not yet implemented");

vadl/main/vadl/viam/passes/ApplyMemoryEndiannessPass.java renamed to vadl/main/vadl/iss/passes/IssApplyMemoryEndiannessPass.java

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText : © 2025 TU Wien <vadl@tuwien.ac.at>
1+
// SPDX-FileCopyrightText : © 2025-2026 TU Wien <vadl@tuwien.ac.at>
22
// SPDX-License-Identifier: GPL-3.0-or-later
33
//
44
// This program is free software: you can redistribute it and/or modify
@@ -14,7 +14,7 @@
1414
// You should have received a copy of the GNU General Public License
1515
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1616

17-
package vadl.viam.passes;
17+
package vadl.iss.passes;
1818

1919
import static java.util.Objects.requireNonNull;
2020
import static vadl.error.Diagnostic.error;
@@ -28,6 +28,7 @@
2828
import vadl.configuration.GeneralConfiguration;
2929
import vadl.error.Diagnostic;
3030
import vadl.error.DiagnosticList;
31+
import vadl.iss.passes.nodes.IssStaticEndianConditionNode;
3132
import vadl.pass.Pass;
3233
import vadl.pass.PassName;
3334
import vadl.pass.PassResults;
@@ -42,7 +43,6 @@
4243
import vadl.viam.graph.Graph;
4344
import vadl.viam.graph.control.AbstractEndNode;
4445
import vadl.viam.graph.control.ProcEndNode;
45-
import vadl.viam.graph.control.ReturnNode;
4646
import vadl.viam.graph.dependency.ExpressionNode;
4747
import vadl.viam.graph.dependency.ReadMemNode;
4848
import vadl.viam.graph.dependency.ReadRegTensorNode;
@@ -65,9 +65,11 @@
6565
* condition must be statically evaluated since register reads are not possible at that point.
6666
* Therefore, register values are taken from the default branch of the processor reset procedure and
6767
* must be constant.
68+
*
69+
* <p><b>Note: this adds ISS-specific nodes</b>
6870
*/
69-
public class ApplyMemoryEndiannessPass extends Pass {
70-
public ApplyMemoryEndiannessPass(GeneralConfiguration configuration) {
71+
public class IssApplyMemoryEndiannessPass extends Pass {
72+
public IssApplyMemoryEndiannessPass(GeneralConfiguration configuration) {
7173
super(configuration);
7274
}
7375

@@ -143,6 +145,7 @@ void run() {
143145
WriteRegTensorNode::value
144146
));
145147

148+
// FIXME: this does not account for changes to the register values during the procedure
146149
processor.memoryRegions().forEach(mr ->
147150
mr.behavior().getNodes(ReadRegTensorNode.class).forEach(read ->
148151
handleRead(read, resetVector, reset, mr.memoryRef())
@@ -199,7 +202,7 @@ private void handleRead(ReadMemNode read) {
199202
var mem = read.memory();
200203
if (mem.isBiEndian()) {
201204
read.replace(new SelectNode(
202-
getConditionCopy(mem),
205+
new IssStaticEndianConditionNode(),
203206
read.overwriteEndianness(mem.endianness()),
204207
read.overwriteEndianness(mem.endianness().other())
205208
));
@@ -215,7 +218,8 @@ private void handeWrite(WriteMemNode write) {
215218
var prev = requireNonNull(next.predecessor());
216219
prev.unlinkNext();
217220
prev.setNext(GraphUtils.ifElseSideEffect(
218-
behaviour, getConditionCopy(mem),
221+
behaviour,
222+
new IssStaticEndianConditionNode(),
219223
List.of(write.overwriteEndianness(mem.endianness())),
220224
List.of(write.overwriteEndianness(mem.endianness().other())),
221225
next,
@@ -224,10 +228,4 @@ behaviour, getConditionCopy(mem),
224228
write.safeDelete();
225229
}
226230
}
227-
228-
private ExpressionNode getConditionCopy(Memory mem) {
229-
return requireNonNull(mem.biEndianCondition())
230-
.getNodes(ReturnNode.class).findFirst().get()
231-
.value().copy();
232-
}
233231
}

vadl/main/vadl/iss/passes/IssNormalizationPass.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import vadl.iss.passes.nodes.IssConstExtractNode;
3737
import vadl.iss.passes.nodes.IssGhostCastNode;
3838
import vadl.iss.passes.nodes.IssSelectNode;
39+
import vadl.iss.passes.nodes.IssStaticEndianConditionNode;
3940
import vadl.iss.passes.nodes.IssStaticPcRegNode;
4041
import vadl.iss.passes.nodes.IssStaticReadRegNode;
4142
import vadl.iss.passes.nodes.IssTempExprNode;
@@ -255,6 +256,11 @@ void handle(IssStaticPcRegNode toHandle) {
255256
// do nothing
256257
}
257258

259+
@Handler
260+
void handle(IssStaticEndianConditionNode toHandle) {
261+
// do nothing
262+
}
263+
258264
@Handler
259265
void handle(IssStaticReadRegNode toHandle) {
260266
// do nothing
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// SPDX-FileCopyrightText : © 2026 TU Wien <vadl@tuwien.ac.at>
2+
// SPDX-License-Identifier: GPL-3.0-or-later
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
package vadl.iss.passes.nodes;
18+
19+
import vadl.types.Type;
20+
import vadl.viam.Memory;
21+
import vadl.viam.graph.Node;
22+
import vadl.viam.graph.dependency.ExpressionNode;
23+
24+
/**
25+
* Represents a static read of the bi-endianness condition value from
26+
* the {@code DisasContext} like this: {@code ctx->endian_cond}. The
27+
* condition determines whether memory ops are big- or little-endian.
28+
* The actual condition (from {@link Memory#biEndianCondition()}) is
29+
* evaluated once per TB during the creation of the {@code DisasContext}.
30+
*/
31+
public class IssStaticEndianConditionNode extends ExpressionNode {
32+
33+
public IssStaticEndianConditionNode() {
34+
super(Type.bool());
35+
}
36+
37+
@Override
38+
public ExpressionNode copy() {
39+
return new IssStaticEndianConditionNode();
40+
}
41+
42+
@Override
43+
public Node shallowCopy() {
44+
return new IssStaticEndianConditionNode();
45+
}
46+
}

vadl/main/vadl/iss/passes/tcgLowering/TcgOpLoweringPass.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import vadl.iss.passes.nodes.IssReadRegNode;
4040
import vadl.iss.passes.nodes.IssRegBitfieldWriteNode;
4141
import vadl.iss.passes.nodes.IssSelectNode;
42+
import vadl.iss.passes.nodes.IssStaticEndianConditionNode;
4243
import vadl.iss.passes.nodes.IssStaticPcRegNode;
4344
import vadl.iss.passes.nodes.IssStaticReadRegNode;
4445
import vadl.iss.passes.nodes.IssStoreNode;
@@ -728,6 +729,11 @@ void handle(IssStaticPcRegNode node) {
728729
// nothing to do
729730
}
730731

732+
@Handler
733+
void handle(IssStaticEndianConditionNode node) {
734+
// nothing to do
735+
}
736+
731737
@Handler
732738
void handle(IssStaticReadRegNode node) {
733739
// nothing to do

vadl/main/vadl/pass/PassOrders.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import vadl.gcb.passes.assembly.AssemblyConcatBuiltinMergingPass;
5252
import vadl.gcb.passes.encodingGeneration.GenerateFieldAccessEncodingAndPredicateFunctionsPass;
5353
import vadl.gcb.passes.operands.GenerateInstructionOperandsPass;
54+
import vadl.iss.passes.IssApplyMemoryEndiannessPass;
5455
import vadl.iss.passes.IssBitfieldWriteLoweringPass;
5556
import vadl.iss.passes.IssBuiltInArgTruncOptPass;
5657
import vadl.iss.passes.IssCFunctionExtractionPass;
@@ -160,7 +161,6 @@
160161
import vadl.vdt.passes.VdtLoweringPass;
161162
import vadl.vdt.passes.VdtVerificationPass;
162163
import vadl.viam.Specification;
163-
import vadl.viam.passes.ApplyMemoryEndiannessPass;
164164
import vadl.viam.passes.ControlFlowOptimizationPass;
165165
import vadl.viam.passes.DetectRegisterIndicesPass;
166166
import vadl.viam.passes.DuplicateWriteDetectionPass;
@@ -226,7 +226,6 @@ public static PassOrder viam(GeneralConfiguration configuration) throws IOExcept
226226
order.add(new NormalizeFieldsToFieldAccessFunctionsPass(configuration));
227227
order.add(new RenamingConflictingRegistersPass(configuration));
228228
order.add(new SnapshotInstructionBehaviorPass(configuration));
229-
order.add(new ApplyMemoryEndiannessPass(configuration));
230229

231230
order.add(new RemoveUnusedStatusFlagsFromBuiltinsPass(configuration));
232231
order.add(new StatusBuiltInInlinePass(configuration));
@@ -523,6 +522,7 @@ public static PassOrder iss(IssConfiguration config) throws IOException {
523522
order
524523
.add(new IssInfoRetrievalPass(config))
525524
.add(new IssConfigurationPass(config))
525+
.add(new IssApplyMemoryEndiannessPass(config))
526526
.add(new IssMemoryDetectionPass(config))
527527
.add(new IssRegisterAccessLoweringPass(config))
528528
.add(new IssExecStrategyPass(config))

0 commit comments

Comments
 (0)