diff --git a/Ghidra/Processors/tricore/data/languages/tricore.cspec b/Ghidra/Processors/tricore/data/languages/tricore.cspec
index a9c69243fe3..ec4038e5812 100644
--- a/Ghidra/Processors/tricore/data/languages/tricore.cspec
+++ b/Ghidra/Processors/tricore/data/languages/tricore.cspec
@@ -124,6 +124,85 @@
the correct return storage location when there are multiple return location types
-->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java b/Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java
new file mode 100644
index 00000000000..99f9691e749
--- /dev/null
+++ b/Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java
@@ -0,0 +1,112 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.plugin.core.analysis;
+
+import java.math.BigInteger;
+
+import ghidra.app.services.AbstractAnalyzer;
+import ghidra.app.services.AnalysisPriority;
+import ghidra.app.services.AnalyzerType;
+import ghidra.app.util.importer.MessageLog;
+import ghidra.program.model.address.AddressSetView;
+import ghidra.program.model.lang.Processor;
+import ghidra.program.model.lang.Register;
+import ghidra.program.model.lang.RegisterValue;
+import ghidra.program.model.listing.Function;
+import ghidra.program.model.listing.FunctionIterator;
+import ghidra.program.model.listing.Instruction;
+import ghidra.program.model.listing.InstructionIterator;
+import ghidra.program.model.listing.Program;
+import ghidra.program.model.symbol.SourceType;
+import ghidra.util.Msg;
+import ghidra.util.exception.CancelledException;
+import ghidra.util.exception.InvalidInputException;
+import ghidra.util.task.TaskMonitor;
+
+public class TricoreFCallAnalyzer extends AbstractAnalyzer {
+
+ private static final String NAME = "Tricore FCall Analyzer";
+ private static final String DESCRIPTION = "Analyzes Tricore programs to find routines called by FCALL opcode. This analyzer looks at the type of return used for the function to identify the calling convention.";
+
+ public TricoreFCallAnalyzer() {
+ super(NAME, DESCRIPTION, AnalyzerType.FUNCTION_ANALYZER);
+ setPriority(AnalysisPriority.FUNCTION_ANALYSIS);
+ setDefaultEnablement(true);
+ }
+
+ @Override
+ public boolean canAnalyze(Program program) {
+ // Only analyze Tricore Programs
+ Processor processor = program.getLanguage().getProcessor();
+
+ boolean canDo = processor.equals(Processor.findOrPossiblyCreateProcessor("tricore"));
+ return canDo;
+ }
+
+ void checkReturn(Program program, Instruction instr) {
+ String mnemonic = instr.getMnemonicString().toLowerCase();
+
+ if (instr == null || !instr.getFlowType().isTerminal()) {
+ return;
+ }
+ if (mnemonic.equals("fret")) {
+ setPrototypeModel(program, instr, "__fastcall");
+ return;
+ }
+ }
+
+ private void setPrototypeModel(Program program, Instruction instr, String convention) {
+ if (convention == null) {
+ return;
+ }
+
+ Function func = program.getFunctionManager().getFunctionContaining(instr.getMinAddress());
+ if (func == null) {
+ return;
+ }
+
+ if (func.getSignatureSource() != SourceType.DEFAULT) {
+ return;
+ }
+
+ try {
+ func.setCallingConvention(convention);
+ } catch (InvalidInputException e) {
+ Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
+ throws CancelledException {
+
+ // get all functions within the set
+ FunctionIterator functions = program.getFunctionManager().getFunctions(set, true);
+ for (Function function : functions) {
+
+ // for each function body, search instructions
+ AddressSetView body = function.getBody();
+ InstructionIterator instructions = program.getListing().getInstructions(body, true);
+ for (Instruction instr : instructions) {
+ if (instr.getFlowType().isTerminal()) {
+ checkReturn(program, instr);
+ }
+ }
+ }
+ return true;
+ }
+
+}