Xavier Martorell

215 papers A* 7A 24B 13C 24Misc 7Journal 57Unranked 80
YearRankTypeTitle / Venue / Authors
2025 A* conf
MICRO
Lucas Morais, Juan Miguel De Haro Ruiz, Alfredo Goldman, Guido Araujo, Giacomo Pedretti, Jim Ignowski, Michael Frank, Xavier Martorell, Daniel Jiménez-González, Carlos Álvarez
2025 J jnl
ACM Trans. Archit. Code Optim.
Omar Shaaban Ibrahim ali, Juliette Fournis d'Albiat, Isabel Piedrahita, Vicenç Beltran, Xavier Martorell, Paul M. Carpenter, Eduard Ayguadé, Jesús Labarta
2025 conf
MEMSYS
Elias Perdomo, Joan Teruel, Sajjad Ahmed, Behzad Salami, Teresa Cervero, Xavier Martorell
2025 J jnl
J. Parallel Distributed Comput.
Pascal Bouvry, Mats Brorsson, Ramon Canal, Aryan Eftekhari, Siegfried Höfinger, Didier Smets, Harald Köstler, Tomás Kozubek, Ezhilmathi Krishnasamy, Josep Llosa, Alexandra Lukas-Rother, Xavier Martorell, Dirk Pleiter, Ana Proykova, Maria-Ribera Sancho, Olaf Schenk, Cristina Silvano
2025 J jnl
CoRR
David Oro, Carles Fernández, Xavier Martorell, Javier Hernando
2024 J jnl
IEEE Trans. Computers
Pouya Esmaili-Dokht, Miquel Guiot, Petar Radojkovic, Xavier Martorell, Eduard Ayguadé, Jesús Labarta, Jason Adlard, Paolo Amato, Marco Sforzin
2024 A* conf
MICRO
Pouya Esmaili-Dokht, Francesco Sgherzi, Valéria Soldera Girelli, Isaac Boixaderas, Mariana Carmin, Alireza Monemi, Adrià Armejach, Estanislao Mercadal, Germán Llort, Petar Radojkovic, Miquel Moretó, Judit Giménez, Xavier Martorell, Eduard Ayguadé, Jesús Labarta, Emanuele Confalonieri, Rishabh Dubey, Jason Adlard
2024 J jnl
CoRR
Pouya Esmaili-Dokht, Francesco Sgherzi, Valéria Soldera Girelli, Isaac Boixaderas, Mariana Carmin, Alireza Momeni, Adrià Armejach, Estanislao Mercadal, Germán Llort, Petar Radojkovic, Miquel Moretó, Judit Giménez, Xavier Martorell, Eduard Ayguadé, Jesús Labarta, Emanuele Confalonieri, Rishabh Dubey, Jason Adlard
2024 conf
DCIS
David Castells-Rufas, David Novo, Xavier Martorell
2024 J jnl
Future Gener. Comput. Syst.
Juan Miguel De Haro Ruiz, Carlos Álvarez-Martínez, Daniel Jiménez-González, Xavier Martorell, Tomohiro Ueno, Kentaro Sano, Burkhard Ringlein, François Abel, Beat Weiss
2024 C conf
PDP
Andrea Giordano, Alessio De Rango, Donato D'Ambrosio, Marisa Gil, Davide Macrì, Xavier Martorell, Rocco Rongo, Gladys Utrera, Giuseppe Mendicino, William Spataro
2024 Misc conf
EDCC
Isabelly Rocha, Pascal Felber, Xavier Martorell, Marcelo Pasin, Valerio Schiavoni, Osman S. Unsal
2024 J jnl
IEEE Trans. Computers
Lucas Morais, Carlos Álvarez, Daniel Jiménez-González, Juan Miguel De Haro Ruiz, Guido Araujo, Michael Frank, Alfredo Goldman, Xavier Martorell
2024 J jnl
CoRR
Elias Perdomo, Alexander Kropotov, Francelly Cano, Syed Zafar, Teresa Cervero, Xavier Martorell, Behzad Salami
2024 C conf
SBAC-PAD
Elias Perdomo, Xavier Martorell, Teresa Cervero, Behzad Salami
2024 C conf
PDP
Alessio De Rango, Gladys Utrera, Marisa Gil, Xavier Martorell, Andrea Giordano, Donato D'Ambrosio, Giuseppe Mendicino
2024 C conf
DSD
Antonio Filgueras, Giovanni Agosta, Marco Aldinucci, Carlos Álvarez, Pasqua D'Ambra, Massimo Bernaschi, Andrea Biagioni, Daniele Cattaneo, Alessandro Celestini, Massimo Celino, Carlotta Chiarini, Francesca Lo Cicero, Paolo Cretaro, William Fornaciari, Ottorino Frezza, Andrea Galimberti, Francesco Giacomini, Juan Miguel De Haro Ruiz, Francesco Iannone, Daniel Jaschke, Daniel Jiménez-González, Michal Kulczewski, Alberto Leva, Alessandro Lonardo, Michele Martinelli, Xavier Martorell, Simone Montangero, Lucas Morais, Ariel Oleksiak, Paolo Palazzari, Luca Pontisso, Federico Reghenzani, Cristian Rossi, Sergio Saponara, Carlo Saverio Lodi, Francesco Simula, Federico Terraneo, Piero Vicini, Miquel Vidal, Davide Zoni, Giuseppe Zummo
2023 B conf
FPL
José Oliver, Carlos Álvarez, Teresa Cervero, Xavier Martorell, John D. Davis, Eduard Ayguadé
2023 conf
DCIS
David Castells-Rufas, Xavier Martorell, Aleix Roca, Alexander Kropotov, Xavier Teruel, Teresa Cervero, John D. Davis
2023 conf
NUMTA (3)
Gladys Utrera, Marisa Gil, Xavier Martorell, William Spataro, Andrea Giordano
2023 conf
ICFPT
Antonio Filgueras, Miquel Vidal, Daniel Jiménez-González, Carlos Álvarez, Xavier Martorell
2023 Misc conf
FCCM
Antonio Filgueras, Miquel Vidal, Daniel Jiménez-González, Carlos Álvarez, Xavier Martorell
2023 Misc conf
FCCM
José Oliver, Carlos Álvarez, Teresa Cervero, Xavier Martorell, John D. Davis, Eduard Ayguadé
2022 C conf
PDP
Gladys Utrera, Marisa Gil, Xavier Martorell
2022 conf
EduHPC@SC
Apan Qasem, Hartwig Anzt, Eduard Ayguadé, Katharine J. Cahill, Ramon Canal, Jany Chan, Eric Fosler-Lussier, Fritz Göbel, Arpan Jain, Marcel Koch, Mateusz Kuzak, Josep Llosa, Raghu Machiraju, Xavier Martorell, Pratik Nayak, Shameema Oottikkal, Marcin Ostasz, Dhabaleswar K. Panda, Dirk Pleiter, Rajiv Ramnath, Maria-Ribera Sancho, Alessio Sclocco, Aamir Shafi, Hanno Spreeuw, Hari Subramoni, Karen Tomko
2022 A conf
IPDPS
Juan Miguel De Haro Ruiz, Rubén Cano, Carlos Álvarez, Daniel Jiménez-González, Xavier Martorell, Eduard Ayguadé, Jesús Labarta, François Abel, Burkhard Ringlein, Beat Weiss
2022 J jnl
Microprocess. Microsystems
Giovanni Agosta, Marco Aldinucci, Carlos Álvarez, Roberto Ammendola, Yasir Arfat, Olivier Beaumont, Massimo Bernaschi, Andrea Biagioni, Tommaso Boccali, Bérenger Bramas, Carlo Brandolese, Barbara Cantalupo, Mauro Carrozzo, Daniele Cattaneo, Alessandro Celestini, Massimo Celino, Iacopo Colonnelli, Paolo Cretaro, Pasqua D'Ambra, Marco Danelutto, Roberto Esposito, Lionel Eyraud-Dubois, Antonio Filgueras, William Fornaciari, Ottorino Frezza, Andrea Galimberti, Francesco Giacomini, Brice Goglin, Daniele Gregori, Abdou Guermouche, Francesco Iannone, Michal Kulczewski, Francesca Lo Cicero, Alessandro Lonardo, Alberto Riccardo Martinelli, Michele Martinelli, Xavier Martorell, Giuseppe Massari, Simone Montangero, Gianluca Mittone, Raymond Namyst, Ariel Oleksiak, Paolo Palazzari, Pier Stanislao Paolucci, Federico Reghenzani, Cristian Rossi, Sergio Saponara, Francesco Simula, Federico Terraneo, Samuel Thibault, Massimo Torquati, Matteo Turisini, Piero Vicini, Miquel Vidal, Davide Zoni, Giuseppe Zummo
2022 J jnl
Comput. J.
David Oro, Carles Fernández, Xavier Martorell, Javier Hernando
2021 J jnl
CoRR
Guillermo Oyarzun, Daniel Peyrolon, Carlos Álvarez, Xavier Martorell
2021 J jnl
IEEE Trans. Computers
Juan Miguel De Haro Ruiz, Jaume Bosch, Antonio Filgueras, Miquel Vidal, Daniel Jiménez-González, Carlos Álvarez, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2021 J jnl
CoRR
Manuel Arenaz, Xavier Martorell
2021 conf
Euro-Par
Nicolas L. Guidotti, Pedro Ceyrat, João Barreto, José Monteiro, Rodrigo Rodrigues, Ricardo Fonseca, Xavier Martorell, Antonio J. Peña
2021 J jnl
CoRR
Nicolas L. Guidotti, Pedro Ceyrat, João Barreto, José Monteiro, Rodrigo Rodrigues, Ricardo Fonseca, Xavier Martorell, Antonio J. Peña
2021 C conf
DSD
Giovanni Agosta, Daniele Cattaneo, William Fornaciari, Andrea Galimberti, Giuseppe Massari, Federico Reghenzani, Federico Terraneo, Davide Zoni, Carlo Brandolese, Massimo Celino, Francesco Iannone, Paolo Palazzari, Giuseppe Zummo, Massimo Bernaschi, Pasqua D'Ambra, Sergio Saponara, Marco Danelutto, Massimo Torquati, Marco Aldinucci, Yasir Arfat, Barbara Cantalupo, Iacopo Colonnelli, Roberto Esposito, Alberto Riccardo Martinelli, Gianluca Mittone, Olivier Beaumont, Bérenger Bramas, Lionel Eyraud-Dubois, Brice Goglin, Abdou Guermouche, Raymond Namyst, Samuel Thibault, Antonio Filgueras, Miquel Vidal, Carlos Álvarez, Xavier Martorell, Ariel Oleksiak, Michal Kulczewski, Alessandro Lonardo, Piero Vicini, Francesca Lo Cicero, Francesco Simula, Andrea Biagioni, Paolo Cretaro, Ottorino Frezza, Pier Stanislao Paolucci, Matteo Turisini, Francesco Giacomini, Tommaso Boccali, Simone Montangero, Roberto Ammendola
2021 conf
ARC
Jaume Bosch, Miquel Vidal, Antonio Filgueras, Daniel Jiménez-González, Carlos Álvarez, Xavier Martorell, Eduard Ayguadé
2021 J jnl
IEEE Des. Test
Antonio Filgueras, Miquel Vidal, Marc Mateu, Daniel Jiménez-González, Carlos Álvarez, Xavier Martorell, Eduard Ayguadé, Dimitrios Theodoropoulos, Dionisios N. Pnevmatikatos, Paolo Gai, Stefano Garzarella, David Oro, Javier Hernando, Nicola Bettin, Alberto Pomella, Marco Procaccini, Roberto Giorgi
2020 J jnl
CoRR
Jaume Bosch, Carlos Álvarez, Daniel Jiménez-González, Xavier Martorell, Eduard Ayguadé
2020 J jnl
Parallel Comput.
Jaume Bosch, Carlos Álvarez, Daniel Jiménez-González, Xavier Martorell, Eduard Ayguadé
2020 B conf
PPoPP
Jaume Bosch, Miquel Vidal, Antonio Filgueras, Carlos Álvarez, Daniel Jiménez-González, Xavier Martorell, Eduard Ayguadé
2020 A conf
DATE
Behzad Salami, Konstantinos Parasyris, Adrián Cristal, Osman S. Unsal, Xavier Martorell, Paul Carpenter, Raúl de la Cruz, Leonardo Bautista-Gomez, Daniel A. Jiménez, Carlos Álvarez, Seyed Saber Nabavi Larimi, Sergi Madonar, Miquel Pericàs, Pedro Trancoso, Mustafa Abduljabbar, Jing Chen, Pirah Noor Soomro, Madhavan Manivannan, Micha vor dem Berge, Stefan Krupop, Frank Klawonn, Al Mekhlafi, Sigrun May, Tobias Becker, Georgi Gaydadjiev, Hans Salomonsson, Devdatt P. Dubhashi, Oron Port, Yoav Etsion, Do Le Quoc, Christof Fetzer, Martin Kaiser, Nils Kucza, Jens Hagemeyer, René Griessl, Lennart Tigges, Kevin Mika, A. Hüffmeier, Marcelo Pasin, Valerio Schiavoni, Isabelly Rocha, Christian Göttel, Pascal Felber
2020 conf
IWOMP
Sandra Catalán, Tetsuzo Usui, Leonel Toledo, Xavier Martorell, Jesús Labarta, Pedro Valero-Lara
2020 J jnl
J. Parallel Distributed Comput.
Pedro Valero-Lara, Sandra Catalán, Xavier Martorell, Tetsuzo Usui, Jesús Labarta
2019 B ed.
FPL
Ioannis Sourdis, Christos-Savvas Bouganis, Carlos Álvarez, Leonel Antonio Toledo Díaz, Pedro Valero-Lara, Xavier Martorell
2019 conf
NUMTA(1)
Gladys Utrera, Marisa Gil, Xavier Martorell
2019 C conf
PDCAT
Sandra Catalán, Xavier Martorell, Jesús Labarta, Tetsuzo Usui, Leonel Antonio Toledo Díaz, Pedro Valero-Lara
2019 J jnl
J. Parallel Distributed Comput.
Borja Pérez, Esteban Stafford, José Luis Bosque, Ramón Beivide, Sergi Mateo, Xavier Teruel, Xavier Martorell, Eduard Ayguadé
2019 C conf
PDP
Pedro Valero-Lara, Sandra Catalán, Xavier Martorell, Jesús Labarta
2019 J jnl
CoRR
Rajiv Nishtala, Vinicius Petrucci, Paul M. Carpenter, Xavier Martorell
2019 J jnl
CoRR
Behzad Salami, Konstantinos Parasyris, Adrián Cristal, Osman S. Unsal, Xavier Martorell, Paul Carpenter, Raúl de la Cruz, Leonardo Bautista-Gomez, Daniel A. Jiménez, Carlos Álvarez, S. Nabavi, Sergi Madonar, Miquel Pericàs, Pedro Trancoso, Mustafa Abduljabbar, Jing Chen, Pirah Noor Soomro, Madhavan Manivannan, Micha vor dem Berge, Stefan Krupop, Frank Klawonn, Al Mekhlafi, Sigrun May, Tobias Becker, Georgi Gaydadjiev, Daniel Ödman, Hans Salomonsson, Devdatt P. Dubhashi, Oron Port, Yoav Etsion, Do Le Quoc, Christof Fetzer, Martin Kaiser, Nils Kucza, Jens Hagemeyer, René Griessl, Lennart Tigges, Kevin Mika, A. Hüffmeier, Th. Jungeblu, Marcelo Pasin, Valerio Schiavoni, Isabelly Rocha, Christian Göttel, Pascal Felber
2019 conf
ISC Workshops
Manuel Arenaz, Xavier Martorell
2018 C conf
PDP
Gladys Utrera, Marisa Gil, Xavier Martorell
2018 J jnl
Concurr. Comput. Pract. Exp.
Gladys Utrera, Marisa Gil, Xavier Martorell
2018 conf
FPT
Jaume Bosch, Xubin Tan, Antonio Filgueras, Miquel Vidal, Marc Mateu, Daniel Jiménez-González, Carlos Álvarez, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2018 ed.
IWOMP
Bronis R. de Supinski, Pedro Valero-Lara, Xavier Martorell, Sergi Mateo Bellido, Jesús Labarta
2018 J jnl
Comput. J.
Edans Flavius de Oliveira Sandes, George Luiz Medeiros Teodoro, Maria Emília M. T. Walter, Xavier Martorell, Eduard Ayguadé, Alba Cristina Magalhaes Alves de Melo
2018 conf
SAMOS
Adrián Cristal, Osman S. Unsal, Xavier Martorell, Paul Carpenter, Raúl de la Cruz, Leonardo Bautista-Gomez, Daniel Jiménez-González, Carlos Álvarez, Behzad Salami, Sergi Madonar, Miquel Pericàs, Pedro Trancoso, Micha vor dem Berge, Gunnar Billung-Meyer, Stefan Krupop, Wolfgang Christmann, Frank Klawonn, Amani Mihklafi, Tobias Becker, Georgi Gaydadjiev, Hans Salomonsson, Devdatt P. Dubhashi, Oron Port, Elad Hadar, Yoav Etsion, Christof Fetzer, Jens Hagemeyer, Thorsten Jungeblut, Nils Kucza, Martin Kaiser, Mario Porrmann, Marcelo Pasin, Valerio Schiavoni, Isabelly Rocha, Christian Göttel, Pascal Felber
2018 conf
CF
Adrián Cristal, Osman S. Unsal, Xavier Martorell, Paul Carpenter, Raúl de la Cruz, Leonardo Bautista-Gomez, Daniel Jiménez-González, Carlos Álvarez, Behzad Salami, Sergi Madonar, Miquel Pericàs, Pedro Trancoso, Micha vor dem Berge, Gunnar Billung-Meyer, Stefan Krupop, Wolfgang Christmann, Frank Klawonn, Amani Mihklafi, Tobias Becker, Georgi Gaydadjiev, Hans Salomonsson, Devdatt P. Dubhashi, Oron Port, Yoav Etsion, Vesna Nowack, Christof Fetzer, Jens Hagemeyer, Thorsten Jungeblut, Nils Kucza, Martin Kaiser, Mario Porrmann, Marcelo Pasin, Valerio Schiavoni, Isabelly Rocha, Christian Göttel, Pascal Felber
2018 C conf
EuroMPI
Pedro Valero-Lara, Raül Sirvent, Antonio J. Peña, Xavier Martorell, Jesús Labarta
2018 J jnl
J. Supercomput.
Helena Caminal, Diego Caballero, Juan M. Cebrian, Roger Ferrer, Marc Casas, Miquel Moretó, Xavier Martorell, Mateo Valero
2018 Misc conf
Ada-Europe
Sara Royuela, Xavier Martorell, Eduardo Quiñones, Luís Miguel Pinho
2018 C conf
PDP
Pedro Valero-Lara, Ivan Martínez-Pérez, Sergi Mateo, Raül Sirvent, Vicenç Beltran, Xavier Martorell, Jesús Labarta
2018 J jnl
Concurr. Comput. Pract. Exp.
Pedro Valero-Lara, Ivan Martínez-Pérez, Raül Sirvent, Xavier Martorell, Antonio J. Peña
2017 conf
IWOMP
Sara Royuela, Alejandro Duran, Maria A. Serrano, Eduardo Quiñones, Xavier Martorell
2017 conf
SBAC-PAD (Workshops)
Maicol Zegarra, Márcio Machado Pereira, Xavier Martorell, Guido Araujo
2017 conf
IPDPS Workshops
Jaume Bosch, Xubin Tan, Carlos Álvarez, Daniel Jiménez-González, Xavier Martorell, Eduard Ayguadé
2017 conf
ANDARE@PACT
Jaume Bosch, Antonio Filgueras, Miquel Vidal, Daniel Jiménez-González, Carlos Álvarez, Xavier Martorell
2017 C conf
SBAC-PAD
Borja Pérez, Esteban Stafford, José Luis Bosque, Ramón Beivide, Sergi Mateo, Xavier Teruel, Xavier Martorell, Eduard Ayguadé
2017 A* conf
HPCA
Rajiv Nishtala, Paul M. Carpenter, Vinicius Petrucci, Xavier Martorell
2017 conf
PARCO
Ying hao Xu, Miquel Vidal, Beñat Arejita, Javier Díaz, Carlos Álvarez, Daniel Jiménez-González, Xavier Martorell, Filippo Mantovani
2017 conf
PPAM (1)
Pedro Valero-Lara, Ivan Martínez-Pérez, Raül Sirvent, Xavier Martorell, Antonio J. Peña
2017 Misc conf
Ada-Europe
Sara Royuela, Xavier Martorell, Eduardo Quiñones, Luís Miguel Pinho
2017 J jnl
Microprocess. Microsystems
Dimitris Theodoropoulos, Somnath Mazumdar, Eduard Ayguadé, Nicola Bettin, Javier Bueno, Sara Ermini, Antonio Filgueras, Daniel Jiménez-González, Carlos Álvarez-Martínez, Xavier Martorell, Francesco Montefoschi, David Oro, Dionisis N. Pnevmatikatos, Antonio Rizzo, Paolo Gai, Stefano Garzarella, Bruno Morelli, Alberto Pomella, Roberto Giorgi
2017 J jnl
ACM Trans. Comput. Syst.
Rajiv Nishtala, Paul M. Carpenter, Vinicius Petrucci, Xavier Martorell
2017 Misc conf
ICCS
Pedro Valero-Lara, Ivan Martínez-Pérez, Antonio J. Peña, Xavier Martorell, Raül Sirvent, Jesús Labarta
2016 conf
ASP-DAC
Roberto Vargas, Sara Royuela, Maria A. Serrano, Xavier Martorell, Eduardo Quiñones
2016 C conf
DSD
Somnath Mazumdar, Eduard Ayguadé, Nicola Bettin, Javier Bueno, Sara Ermini, Antonio Filgueras, Daniel Jiménez-González, Carlos Álvarez-Martínez, Xavier Martorell, Francesco Montefoschi, David Oro, Dionisios N. Pnevmatikatos, Antonio Rizzo, Dimitris Theodoropoulos, Roberto Giorgi
2016 C conf
PDP
Gladys Utrera, Marisa Gil, Xavier Martorell
2016 J jnl
IEEE Trans. Parallel Distributed Syst.
Edans Flavius de Oliveira Sandes, Guillermo Miranda, Xavier Martorell, Eduard Ayguadé, George Teodoro, Alba Cristina Magalhaes Alves de Melo
2016 J jnl
IEEE Trans. Parallel Distributed Syst.
Michail Alvanos, Montse Farreras, Ettore Tiotto, José Nelson Amaral, Xavier Martorell
2016 J jnl
ACM Trans. Parallel Comput.
Edans Flavius de Oliveira Sandes, Guillermo Miranda, Xavier Martorell, Eduard Ayguadé, George Teodoro, Alba Cristina Magalhaes Alves de Melo
2016 C conf
SBAC-PAD
Rajiv Nishtala, Xavier Martorell, Vinicius Petrucci, Daniel Mossé
2016 conf
IGSC
Rajiv Nishtala, Xavier Martorell
2016 conf
IWOMP
Jan Ciesko, Sergi Mateo, Xavier Teruel, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2016 J jnl
Microprocess. Microsystems
Carlos Álvarez, Eduard Ayguadé, Jaume Bosch, Javier Bueno, Artem Cherkashin, Antonio Filgueras, Daniel Jiménez-González, Xavier Martorell, Nacho Navarro, Miquel Vidal, Dimitris Theodoropoulos, Dionisios N. Pnevmatikatos, Davide Catani, David Oro, Carles Fernández, Carlos Segura, Javier Rodríguez Saeta, Javier Hernando, Claudio Scordino, Paolo Gai, Pierluigi Passera
2016 conf
IWOMP
Germán Llort, Antonio Filgueras, Daniel Jiménez-González, Harald Servat, Xavier Teruel, Estanislao Mercadal, Carlos Álvarez, Judit Giménez, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2016 A conf
SC
Nikola Rajovic, Alejandro Rico, Filippo Mantovani, Daniel Ruiz, Josep Oriol Vilarrubi, Constantino Gómez, Luna Backes, Diego Nieto, Harald Servat, Xavier Martorell, Jesús Labarta, Eduard Ayguadé, Chris Adeniyi-Jones, Said Derradji, Hervé Gloaguen, Piero Lanucara, Nico Sanna, Jean-François Méhaut, Kevin Pouget, Brice Videau, Eric Boyer, Momme Allalen, Axel Auweter, David Brayford, Daniele Tafani, Volker Weinberg, Dirk Brömmel, René Halver, Jan H. Meinke, Ramón Beivide, Mariano Benito, Enrique Vallejo, Mateo Valero, Alex Ramírez
2016 J jnl
Parallel Comput.
Michail Alvanos, Ettore Tiotto, José Nelson Amaral, Montse Farreras, Xavier Martorell
2016 Misc conf
ICASSP
David Oro, Carles Fernández, Xavier Martorell, Javier Hernando
2015 conf
ICPP Workshops
Rajiv Nishtala, Marc González Tallada, Xavier Martorell
2015 conf
HPEC
Jan Ciesko, Sergi Mateo, Xavier Teruel, Vicenç Beltran, Xavier Martorell, Jesús Labarta
2015 J jnl
CoRR
Daniel Jiménez-González, Carlos Álvarez, Antonio Filgueras, Xavier Martorell, Jan Langer, Juanjo Noguera, Kees A. Vissers
2015 A* conf
ISCA
Lluc Alvarez, Lluís Vilanova, Miquel Moretó, Marc Casas, Marc González, Xavier Martorell, Nacho Navarro, Eduard Ayguadé, Mateo Valero
2015 conf
Conf. Computing Frontiers
Sara Royuela, Roger Ferrer, Diego Caballero, Xavier Martorell
2015 J jnl
Supercomput. Front. Innov.
Rabab Alomairy, Guillermo Miranda, Hatem Ltaief, Rosa M. Badia, Xavier Martorell, Jesús Labarta, David E. Keyes
2015 conf
IWOMP
Raul Vidal, Marc Casas, Miquel Moretó, Dimitrios Chasapis, Roger Ferrer, Xavier Martorell, Eduard Ayguadé, Jesús Labarta, Mateo Valero
2015 C conf
PDP
Gladys Utrera, Marisa Gil, Xavier Martorell
2015 conf
PPAM (1)
Isil Öz, Marisa Gil, Gladys Utrera, Xavier Martorell
2015 J jnl
IEEE Trans. Computers
Lluc Alvarez, Lluís Vilanova, Marc González, Xavier Martorell, Nacho Navarro, Eduard Ayguadé
2015 conf
HPCS
Gladys Utrera, Marisa Gil, Xavier Martorell
2015 B conf
ICPP
Jie Shen, Ana Lucia Varbanescu, Xavier Martorell, Henk J. Sips
2015 A conf
ICS
Diego Caballero, Sara Royuela, Roger Ferrer, Alejandro Duran, Xavier Martorell
2015 J jnl
ACM Trans. Embed. Comput. Syst.
Martin Tillenius, Elisabeth Larsson, Rosa M. Badia, Xavier Martorell
2015 B conf
PACT
Lluc Alvarez, Miquel Moretó, Marc Casas, Emilio Castillo, Xavier Martorell, Jesús Labarta, Eduard Ayguadé, Mateo Valero
2015 C conf
DSD
Carlos Álvarez, Eduard Ayguadé, Javier Bueno, Antonio Filgueras, Daniel Jiménez-González, Xavier Martorell, Nacho Navarro, Dimitris Theodoropoulos, Dionisios N. Pnevmatikatos, Davide Catani, Claudio Scordino, Paolo Gai, Carlos Segura, Carles Fernández, David Oro, Javier Rodríguez Saeta, Pierluigi Passera, Alberto Pomella, Antonio Rizzo, Roberto Giorgi
2015 conf
SAMOS
Dimitris Theodoropoulos, Dionisios N. Pnevmatikatos, Carlos Álvarez, Eduard Ayguadé, Javier Bueno, Antonio Filgueras, Daniel Jiménez-González, Xavier Martorell, Nacho Navarro, Carlos Segura, Carles Fernández, David Oro, Javier Rodríguez Saeta, Paolo Gai, Antonio Rizzo, Roberto Giorgi
2015 conf
IWOMP
Jan Ciesko, Sergi Mateo, Xavier Teruel, Xavier Martorell, Eduard Ayguadé, Jesús Labarta, Alex Duran, Bronis R. de Supinski, Stephen Olivier, Kelvin Li, Alexandre E. Eichenberger
2014 conf
HPCS
Gladys Utrera, Marisa Gil, Xavier Martorell
2014 B conf
CCGRID
Edans F. de O. Sandes, Guillermo Miranda, Alba Cristina Magalhaes Alves de Melo, Xavier Martorell, Eduard Ayguadé
2014 B conf
PPoPP
Edans F. de O. Sandes, Guillermo Miranda, Alba Cristina Magalhaes Alves de Melo, Xavier Martorell, Eduard Ayguadé
2014 C conf
SBAC-PAD
Florentino Sainz, Sergi Mateo, Vicenç Beltran, José Luis Bosque, Xavier Martorell, Eduard Ayguadé
2014 A conf
FPGA
Antonio Filgueras, Eduard Gil, Daniel Jiménez-González, Carlos Álvarez, Xavier Martorell, Jan Langer, Juanjo Noguera, Kees A. Vissers
2014 C conf
SBAC-PAD
Michail Alvanos, José Nelson Amaral, Ettore Tiotto, Montse Farreras, Xavier Martorell
2014 conf
Euro-Par Workshops (2)
Alejandro Fernández, Vicenç Beltran, Xavier Martorell, Rosa M. Badia, Eduard Ayguadé, Jesús Labarta
2014 conf
IWOMP
Jan Ciesko, Sergi Mateo, Xavier Teruel, Vicenç Beltran, Xavier Martorell, Rosa M. Badia, Eduard Ayguadé, Jesús Labarta
2013 conf
IWOMP
Xavier Teruel, Michael Klemm, Kelvin Li, Xavier Martorell, Stephen L. Olivier, Christian Terboven
2013 J jnl
IEEE Trans. Computers
Ramon Bertran, Marc González, Xavier Martorell, Nacho Navarro, Eduard Ayguadé
2013 conf
IWOMP
Diego Caballero, Alejandro Duran, Xavier Martorell
2013 J jnl
Comput. J.
Ramon Bertran, Marc González, Xavier Martorell, Nacho Navarro, Eduard Ayguadé
2013 C conf
VLSI-SoC
Antonio Filgueras, Eduard Gil, Carlos Álvarez, Daniel Jiménez-González, Xavier Martorell, Jan Langer, Juanjo Noguera
2013 A conf
ICS
Javier Bueno, Xavier Martorell, Rosa M. Badia, Eduard Ayguadé, Jesús Labarta
2013 A conf
ICS
Michail Alvanos, Montse Farreras, Ettore Tiotto, José Nelson Amaral, Xavier Martorell
2013 A conf
ICS
Michail Alvanos, Gabriel Tanase, Montse Farreras, Ettore Tiotto, José Nelson Amaral, Xavier Martorell
2013 J jnl
J. WSCG
Raquel Concheiro, Margarita Amor, Marisa Gil, Emilio J. Padrón, Xavier Martorell
2012 conf
AHS
Fisnik Kraja, Arndt Bode, Xavier Martorell
2012 B conf
ICPP
David Oro, Carles Fernández, Carlos Segura, Xavier Martorell, Javier Hernando
2012 conf
CASCON
Michail Alvanos, Montse Farreras, Ettore Tiotto, Xavier Martorell
2012 conf
LCPC
Sara Royuela, Alejandro Duran, Xavier Martorell
2012 J jnl
IEEE Trans. Computers
Nikola Vujic, Felipe Cabarcas, Marc González Tallada, Alex Ramírez, Xavier Martorell, Eduard Ayguadé
2012 conf
Conf. Computing Frontiers
Nikola Vujic, Lluc Alvarez, Marc González, Xavier Martorell, Eduard Ayguadé
2012 J jnl
Future Gener. Comput. Syst.
Ramon Bertran, Yolanda Becerra, David Carrera, Vicenç Beltran, Marc González, Xavier Martorell, Nacho Navarro, Jordi Torres, Eduard Ayguadé
2012 conf
IWOMP
Michael Klemm, Alejandro Duran, Xinmin Tian, Hideki Saito, Diego Caballero, Xavier Martorell
2012 A conf
SC
Lluc Alvarez, Lluís Vilanova, Marc González, Xavier Martorell, Nacho Navarro, Eduard Ayguadé
2012 conf
Euro-Par Workshops
Harald Servat, Xavier Teruel, Germán Llort, Alejandro Duran, Judit Giménez, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2012 A* conf
SIGMETRICS
Ramon Bertran, Marc González, Xavier Martorell, Nacho Navarro, Eduard Ayguadé
2012 A conf
IPDPS
Javier Bueno, Judit Planas, Alejandro Duran, Rosa M. Badia, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2011 J jnl
Int. J. Parallel Program.
Harm Munk, Eduard Ayguadé, Cédric Bastoul, Paul M. Carpenter, Zbigniew Chamski, Albert Cohen, Marco Cornero, Philippe Dumont, Marc Duranton, Mohammed Fellahi, Roger Ferrer, Razya Ladelsky, Menno Lindwer, Xavier Martorell, Cupertino Miranda, Dorit Nuzman, Andrea C. Ornstein, Antoniu Pop, Sebastian Pop, Louis-Noël Pouchet, Alex Ramírez, David Ródenas, Erven Rohou, Ira Rosen, Uzi Shvadron, Konrad Trifunovic, Ayal Zaks
2011 A conf
HPDC
Lluc Alvarez, Ramon Bertran, Marc González, Xavier Martorell, Nacho Navarro, Eduard Ayguadé
2011 conf
IA3@SC
Miquel Pericàs, Xavier Martorell, Yoav Etsion
2011 J jnl
Comput. J.
Ramon Bertran, Marc González, Xavier Martorell, Nacho Navarro, Eduard Ayguadé
2011 J jnl
Parallel Process. Lett.
Alejandro Duran, Eduard Ayguadé, Rosa M. Badia, Jesús Labarta, Luis Martinell, Xavier Martorell, Judit Planas
2011 A conf
ICS
Javier Bueno, Alejandro Duran, Xavier Martorell, Eduard Ayguadé, Rosa M. Badia, Jesús Labarta
2011 conf
Euro-Par (1)
Javier Bueno, Luis Martinell, Alejandro Duran, Montse Farreras, Xavier Martorell, Rosa M. Badia, Eduard Ayguadé, Jesús Labarta
2011 conf
ICCV Workshops
David Oro, Carles Fernández, Javier Rodríguez Saeta, Xavier Martorell, Javier Hernando
2011 conf
ARCS
Catalin Bogdan Ciobanu, Xavier Martorell, Georgi Kuzmanov, Alex Ramírez, Georgi Gaydadjiev
2010 conf
GRID
Ramon Bertran, Yolanda Becerra, David Carrera, Vicenç Beltran, Marc González, Xavier Martorell, Jordi Torres, Eduard Ayguadé
2010 conf
HiPEAC
Roger Ferrer, Vicenç Beltran, Marc González, Xavier Martorell, Eduard Ayguadé
2010 J jnl
IEEE Trans. Parallel Distributed Syst.
Nikola Vujic, Marc González, Xavier Martorell, Eduard Ayguadé
2010 A* conf
HPCA
Nikola Vujic, Marc González, Felipe Cabarcas, Alex Ramírez, Xavier Martorell, Eduard Ayguadé
2010 A conf
ICS
Ramon Bertran, Marc González, Xavier Martorell, Nacho Navarro, Eduard Ayguadé
2010 ed.
HiPEAC
Yale N. Patt, Pierfrancesco Foglia, Evelyn Duesterwald, Paolo Faraboschi, Xavier Martorell
2010 conf
LCPC
Roger Ferrer, Judit Planas, Pieter Bellens, Alejandro Duran, Marc González, Xavier Martorell, Rosa M. Badia, Eduard Ayguadé, Jesús Labarta
2010 conf
CASCON
Javier Bueno, Xavier Martorell, Juan José Costa, Toni Cortes, Eduard Ayguadé, Guansong Zhang, Christopher Barton, Raúl Silvera
2010 C conf
PDCAT
Juan José Costa, Toni Cortes, Xavier Martorell, Javier Bueno, Eduard Ayguadé
2009 conf
IWOMP
Eduard Ayguadé, Rosa M. Badia, Daniel Cabrera, Alejandro Duran, Marc González, Francisco D. Igual, Daniel Jiménez-González, Jesús Labarta, Xavier Martorell, Rafael Mayo, Josep M. Pérez, Enrique S. Quintana-Ortí
2009 conf
MEDEA@PACT
Roger Ferrer, Vicenç Beltran, Marc González, Xavier Martorell, Eduard Ayguadé
2009 conf
LCPC
Nikola Vujic, Lluc Alvarez, Marc González Tallada, Xavier Martorell, Eduard Ayguadé
2009 B conf
ICPP
Alejandro Duran, Xavier Teruel, Roger Ferrer, Xavier Martorell, Eduard Ayguadé
2009 conf
ICSAMOS
Daniel Cabrera, Xavier Martorell, Georgi Gaydadjiev, Eduard Ayguadé, Daniel Jiménez-González
2009 conf
CASCON
Xavier Teruel, Christopher Barton, Alejandro Duran, Xavier Martorell, Eduard Ayguadé, Priya Unnikrishnan, Guansong Zhang, Raúl Silvera
2009 conf
LCPC
Roger Ferrer, Alejandro Duran, Xavier Martorell, Eduard Ayguadé
2008 conf
LCPC
Nikola Vujic, Marc González, Xavier Martorell, Eduard Ayguadé
2008 conf
MEDEA@PACT
Roger Ferrer, Marc González, Federico Silla, Xavier Martorell, Eduard Ayguadé
2008 B conf
PACT
Marc González, Nikola Vujic, Xavier Martorell, Eduard Ayguadé, Alexandre E. Eichenberger, Tong Chen, Zehra Sura, Tao Zhang, Kevin O'Brien, Kathryn M. O'Brien
2008 conf
CASCON
Xavier Teruel, Priya Unnikrishnan, Xavier Martorell, Eduard Ayguadé, Raúl Silvera, Guansong Zhang, Ettore Tiotto
2007 conf
LCPC
Jairo Balart, Marc González, Xavier Martorell, Eduard Ayguadé, Zehra Sura, Tong Chen, Tao Zhang, Kevin O'Brien, Kathryn M. O'Brien
2007 J jnl
Int. J. Parallel Program.
Alejandro Duran, Roger Ferrer, Juan José Costa, Marc González, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2007 conf
SAMOS
Paul M. Carpenter, David Ródenas, Xavier Martorell, Alex Ramírez, Eduard Ayguadé
2007 J jnl
Trans. High Perform. Embed. Archit. Compil.
Koen De Bosschere, Wayne Luk, Xavier Martorell, Nacho Navarro, Michael F. P. O'Boyle, Dionisios N. Pnevmatikatos, Alex Ramírez, Pascal Sainrat, André Seznec, Per Stenström, Olivier Temam
2007 B conf
ISPASS
Daniel Jiménez-González, Xavier Martorell, Alex Ramírez
2007 conf
CASCON
Xavier Teruel, Xavier Martorell, Alejandro Duran, Roger Ferrer, Eduard Ayguadé
2007 conf
IWOMP
Milos Milovanovic, Roger Ferrer, Osman S. Unsal, Adrián Cristal, Xavier Martorell, Eduard Ayguadé, Jesús Labarta, Mateo Valero
2006 conf
IWOMP
Alejandro Duran, Roger Ferrer, Juan José Costa, Marc González, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2006 J jnl
J. Parallel Distributed Comput.
Eduard Ayguadé, Marc González, Xavier Martorell, Gabriele Jost
2006 J jnl
J. Embed. Comput.
David Ródenas, Xavier Martorell, Eduard Ayguadé, Jesús Labarta, George Almási, Calin Cascaval, José G. Castaños, José E. Moreira
2006 J jnl
J. Parallel Distributed Comput.
Juan José Costa, Toni Cortes, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2006 conf
LCPC
Jairo Balart, Marc González, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2006 A conf
IPDPS
Xavier Martorell, Marc González, Alejandro Duran, Jairo Balart, Roger Ferrer, Eduard Ayguadé, Jesús Labarta
2005 J jnl
IBM J. Res. Dev.
Xavier Martorell, Nils Smeds, Robert Walkup, José R. Brunheroto, George Almási, John A. Gunnels, Luiz De Rose, Jesús Labarta, Francesc Escalé, Judit Giménez, Harald Servat, José E. Moreira
2005 J jnl
IBM J. Res. Dev.
George Almási, Charles Archer, José G. Castaños, John A. Gunnels, C. Christopher Erway, Philip Heidelberger, Xavier Martorell, José E. Moreira, Kurt W. Pinnow, Joe Ratterman, Burkhard D. Steinmacher-Burow, William Gropp, Brian R. Toonen
2005 conf
IWOMP
Jairo Balart, Alejandro Duran, Marc González, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2005 A conf
ICS
George Almási, Philip Heidelberger, Charles Archer, Xavier Martorell, C. Christopher Erway, José E. Moreira, Burkhard D. Steinmacher-Burow, Yili Zheng
2005 A conf
IPDPS
David Ródenas, Xavier Martorell, Eduard Ayguadé, Jesús Labarta, George Almási, Calin Cascaval, José G. Castaños, José E. Moreira
2005 J jnl
IEEE Trans. Parallel Distributed Syst.
Julita Corbalán, Xavier Martorell, Jesús Labarta
2004 conf
PVM/MPI
George Almási, Charles Archer, John A. Gunnels, Philip Heidelberger, Xavier Martorell, José E. Moreira
2004 A conf
IPDPS
Eduard Ayguadé, Marc González, Xavier Martorell, Gabriele Jost
2004 conf
Euro-Par
George Almási, Charles Archer, José G. Castaños, C. Christopher Erway, Philip Heidelberger, Xavier Martorell, José E. Moreira, Kurt W. Pinnow, Joe Ratterman, Nils Smeds, Burkhard D. Steinmacher-Burow, William Gropp, Brian R. Toonen
2004 J jnl
Int. J. Parallel Program.
Julita Corbalán, Xavier Martorell, Jesús Labarta
2004 A conf
IPDPS
Juan José Costa, Toni Cortes, Xavier Martorell, Eduard Ayguadé, Jesús Labarta
2003 J jnl
Parallel Process. Lett.
George Almási, Ralph Bellofatto, José R. Brunheroto, Calin Cascaval, José G. Castaños, Paul Crumley, C. Christopher Erway, Derek Lieber, Xavier Martorell, José E. Moreira, Ramendra K. Sahoo, Alda Sanomiya, Luis Ceze, Karin Strauss
2003 conf
Euro-Par
George Almási, Ralph Bellofatto, José R. Brunheroto, Calin Cascaval, José G. Castaños, Luis Ceze, Paul Crumley, C. Christopher Erway, Joseph Gagliano, Derek Lieber, Xavier Martorell, José E. Moreira, Alda Sanomiya, Karin Strauss
2003 A conf
IPDPS
Jordi Guitart, Xavier Martorell, Jordi Torres, Eduard Ayguadé
2003 J jnl
Sci. Program.
Haoqiang Jin, Gabriele Jost, Jerry C. Yan, Eduard Ayguadé, Marc González, Xavier Martorell
2003 C conf
SBAC-PAD
George S. Almási, Leonardo R. Bachega, Siddhartha Chatterjee, Manish Gupta, Derek Lieber, Xavier Martorell, José E. Moreira
2003 conf
WOMPAT
George Almási, Eduard Ayguadé, Calin Cascaval, José G. Castaños, Jesús Labarta, Francisco Martínez, Xavier Martorell, José E. Moreira
2003 A conf
ICS
Julita Corbalán, Xavier Martorell, Jesús Labarta
2003 conf
WOMPAT
Eduard Ayguadé, Bob Blainey, Alejandro Duran, Jesús Labarta, Francisco Martínez, Xavier Martorell, Raúl Silvera
2003 conf
PVM/MPI
George Almási, Charles Archer, José G. Castaños, Manish Gupta, Xavier Martorell, José E. Moreira, William Gropp, Silvius Vasile Rus, Brian R. Toonen
2002 conf
ISHPC
Marc González, Eduard Ayguadé, Xavier Martorell, Jesús Labarta, Phu V. Luong
2001 B conf
ICPP
Marc González, Eduard Ayguadé, Xavier Martorell, Jesús Labarta
2001 conf
WOMPAT
Marc González, Eduard Ayguadé, Xavier Martorell, Jesús Labarta
2001 A conf
ICS
Julita Corbalán, Xavier Martorell, Jesús Labarta
2000 C conf
JSSPP
Xavier Martorell, Julita Corbalán, Dimitrios S. Nikolopoulos, Nacho Navarro, Eleftherios D. Polychronopoulos, Theodore S. Papatheodorou, Jesús Labarta
2000 A conf
IPDPS
Marc González, Albert Serra, Xavier Martorell, José Oliver, Eduard Ayguadé, Jesús Labarta, Nacho Navarro
2000 J jnl
Concurr. Pract. Exp.
Marc González, Eduard Ayguadé, Xavier Martorell, Jesús Labarta, Nacho Navarro, José Oliver
2000 conf
LCPC
Marc González, José Oliver, Xavier Martorell, Eduard Ayguadé, Jesús Labarta, Nacho Navarro
2000 A* conf
OSDI
Julita Corbalán, Xavier Martorell, Jesús Labarta
1999
Xavier Martorell
1999 B conf
ICPP
Eduard Ayguadé, Xavier Martorell, Jesús Labarta, Marc González, Nacho Navarro
1999 A conf
International Conference on Supercomputing
Xavier Martorell, Eduard Ayguadé, Nacho Navarro, Julita Corbalán, Marc González, Jesús Labarta
1998 C conf
PDP
Ernest Artiaga, Xavier Martorell, Yolanda Becerra, Nacho Navarro
1998 A conf
International Conference on Supercomputing
Eleftherios D. Polychronopoulos, Xavier Martorell, Dimitrios S. Nikolopoulos, Jesús Labarta, Theodore S. Papatheodorou, Nacho Navarro
1997 conf
IPPS
Xavier Martorell, Jesús Labarta, Nacho Navarro, Eduard Ayguadé
1997 conf
LCPC
Eduard Ayguadé, Xavier Martorell, Jesús Labarta, Marc González, Nacho Navarro
1996 conf
Euro-Par, Vol. II
Xavier Martorell, Jesús Labarta, Nacho Navarro, Eduard Ayguadé
1995 conf
Parallel and Distributed Computing and Systems
Marisa Gil, Xavier Martorell, Nacho Navarro
redb/extractors/decompiler/_archive/GhidraDecompilerScript.java
← Index redb/extractors/decompiler/_archive/GhidraDecompilerScript.java java
import ghidra.app.script.GhidraScript;
import ghidra.program.model.listing.*;
import ghidra.app.decompiler.*;
import ghidra.program.model.address.*;
import org.json.JSONObject;
import org.json.JSONArray;
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
import ghidra.program.model.lang.OperandType;
import java.util.*;
import ghidra.program.model.block.*;
import ghidra.util.exception.CancelledException;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolTable;
import java.util.Arrays;
import com.sangupta.murmur.Murmur3;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Executors;

public class GhidraDecompilerScript extends GhidraScript {
    private Listing listing;
    private BasicBlockModel basicBlockModel;
    private JSONArray errors;
    private DecompInterface decompInterface;  

    private enum InstructionType {
        // Data Movement
        GENERAL_DATA_MOVEMENT,    // mov, lea, xchg
        STACK_MANAGEMENT,         // push, pop, enter, leave
        STRING_MANIPULATION,      // movs, lods, stos, cmps
        
        // Arithmetic
        BASIC_ARITHMETIC,         // add, sub, inc, dec
        MULTIPLICATION_DIVISION,  // mul, div, imul, idiv
        CARRY_ARITHMETIC,         // adc, sbb
        
        // Logical
        BITWISE_LOGIC,           // and, or, xor, not
        CONDITIONAL_LOGIC,        // test, cmp, setX
        
        // Control Flow
        UNCONDITIONAL_JUMP,      // jmp
        CONDITIONAL_JUMP,        // je, jne, jl, jg, etc
        FUNCTION_CONTROL,        // call, ret
        LOOPING,                 // loop, loopz, loopnz
        
        // System
        SYSTEM_CALLS,            // syscall, int, sysenter
        PRIVILEGED_INSTRUCTIONS, // hlt, cli, sti
        CPU_FEATURES,            // cpuid, rdtsc
        
        // SIMD & FPU
        SSE_SIMD,               // SSE instructions
        AVX_SIMD,               // AVX instructions
        BASIC_FPU,              // fld, fst, fstp
        FPU_ARITHMETIC,         // fadd, fsub, etc
        
        // Bit Operations
        SHIFT_ROTATE,           // shl, shr, rol, ror
        BIT_TEST_MODIFY,        // bt, bts, btr, btc
        
        // Special
        CRYPTOGRAPHIC_OPS,      // aesenc, aesdec, sha1rnds4
        MISC_OPS               // nop, ud2, etc
    }

    private enum BranchType {
        DIRECT, CONDITIONAL, CALL, RETURN, FALLTHROUGH, UNKNOWN
    }

    private enum ApiCategory {
        FILE_OP(Arrays.asList("CreateFile", "ReadFile", "WriteFile", "DeleteFile", "SetFilePointer", "CopyFile", "MoveFile", "FindFirstFile", "FindNextFile")),
        MEMORY_OP(Arrays.asList("VirtualAlloc", "VirtualFree", "HeapAlloc", "HeapFree", "LocalAlloc", "GlobalAlloc", "MapViewOfFile", "VirtualProtect")),
        NETWORK_OP(Arrays.asList("socket", "connect", "bind", "send", "recv", "WSAStartup", "InternetOpen", "InternetConnect", "HttpOpenRequest", "HttpSendRequest", "InternetReadFile", "URLDownloadToFile")),
        REGISTRY_OP(Arrays.asList("RegOpenKey", "RegCreateKey", "RegSetValue", "RegQueryValue", "RegDeleteKey", "RegEnumKey", "RegFlushKey")),
        PROCESS_OP(Arrays.asList("CreateProcess", "OpenProcess", "TerminateProcess", "GetProcessId", "CreateProcessAsUser", "NtCreateProcess")),
        THREAD_OP(Arrays.asList("CreateThread", "SuspendThread", "ResumeThread", "CreateRemoteThread", "SetThreadContext", "GetThreadContext")),
        INJECTION_OP(Arrays.asList("WriteProcessMemory", "VirtualAllocEx", "NtWriteVirtualMemory", "SetWindowsHookEx", "QueueUserAPC", "NtMapViewOfSection")),
        EVASION_OP(Arrays.asList("IsDebuggerPresent", "CheckRemoteDebuggerPresent", "NtQueryInformationProcess", "GetTickCount", "OutputDebugString", "Sleep", "QueryPerformanceCounter")),
        SPYING_OP(Arrays.asList("GetAsyncKeyState", "GetKeyboardState", "GetKeyState", "GetForegroundWindow", "SetWindowsHookEx", "BitBlt", "GetClipboardData")),
        SYSTEM_OP(Arrays.asList("CreateToolhelp32Snapshot", "EnumDeviceDrivers", "EnumProcesses", "GetSystemDirectoryA", "GetLogicalDrives")),
        SERVICE_OP(Arrays.asList("CreateServiceA", "OpenServiceA", "StartServiceA", "DeleteService", "OpenSCManagerA", "ControlService")),
        CRYPTO_OP(Arrays.asList("CryptAcquireContext", "CryptGenKey", "CryptEncrypt", "CryptDecrypt", "CryptCreateHash", "CryptHashData", "CryptGenRandom")),
        DLL_OP(Arrays.asList("LoadLibrary", "GetProcAddress", "FreeLibrary", "LdrLoadDll")),
        UNKNOWN_OP(Collections.emptyList());

        private final List<String> apis;

        ApiCategory(List<String> apis) {
            this.apis = apis;
        }

        public static ApiCategory fromApi(String apiName) {
            for (ApiCategory category : values()) {
                if (category.apis.stream().anyMatch(api -> apiName.startsWith(api))) {
                    return category;
                }
            }
            return UNKNOWN_OP;
        }
    }

    private static final String[] COMMON_OPCODES = {
        // Core instructions (tracked individually)
        "MOV", "PUSH", "POP", "LEA", "CALL", "RET",         // Data movement and control
        "ADD", "SUB", "MUL", "DIV",                         // Basic arithmetic
        "AND", "OR", "XOR", "NOT",                          // Logical operations
        "JMP", "JE", "JNE",                                 // Basic jumps
        "TEST", "CMP",                                      // Comparisons
        
        // Grouped categories (aggregated tracking)
        "SIMD_MOVE",      // MOVAPS, MOVDQA, MOVDQU, etc.
        "COND_JUMP_EXT",  // Other conditional jumps (JG, JL, JGE, etc.)
        "STRING_OP",      // MOVS, STOS, LODS, SCAS, CMPS
        "STACK_ADV",      // ENTER, LEAVE, PUSHA, POPA
        "ARITHMETIC_ADV", // IMUL, IDIV, ADC, SBB
        "BIT_OP",        // SHL, SHR, SAR, ROL, ROR, etc.
        "FPU_OP",        // FLD, FST, FADD, etc.
        "SYSTEM_OP",     // SYSCALL, INT, SYSENTER
        "CRYPTO_OP",     // AES*, SHA* instructions
        "MISC_OP"        // Rare but interesting (CPUID, RDTSC, etc.)
    };
    private Map<String, Integer> opcodeIndex;
    private Map<String, String> opcodeCategories;

    private void initializeOpcodeMaps() {
        opcodeIndex = new HashMap<>();
        opcodeCategories = new HashMap<>();
        
        for (int i = 0; i < COMMON_OPCODES.length; i++) {
            opcodeIndex.put(COMMON_OPCODES[i], i);
            
            // Categorize opcodes
            String opcode = COMMON_OPCODES[i];
            
            // String Operations (checking these first to avoid MOV confusion)
            if (opcode.matches("MOVS.*|STOS.*|LODS.*|SCAS.*|CMPS.*|REP.*") && 
                !opcode.startsWith("MOVSX") && !opcode.startsWith("MOVZX")) {
                opcodeCategories.put(opcode, "STRING_MANIPULATION");
            }
            
            // Data Movement (after string ops to avoid MOVS confusion)
            else if ((opcode.startsWith("MOV")) || 
                     opcode.equals("LEA") || opcode.equals("XCHG")) {
                opcodeCategories.put(opcode, "DATA_MOVEMENT");
            }
            
            // Stack Operations
            else if (opcode.matches("PUSH|POP|ENTER|LEAVE|PUSHA|POPA")) {
                opcodeCategories.put(opcode, "STACK_MANAGEMENT");
            }
            
            // Control Flow (non-conditional)
            else if (opcode.matches("JMP|CALL|RET")) {
                opcodeCategories.put(opcode, "CONTROL_FLOW");
            }
            
            // Conditional Jumps and Loops
            else if (opcode.startsWith("J") || opcode.startsWith("LOOP")) {
                opcodeCategories.put(opcode, "CONDITIONAL_JUMP");
            }
            
            // Arithmetic
            else if (opcode.matches("ADD|SUB|MUL|DIV|I?MUL|I?DIV|ADC|SBB|INC|DEC|NEG")) {
                opcodeCategories.put(opcode, "ARITHMETIC");
            }
            
            // Logical
            else if (opcode.matches("AND|OR|XOR|NOT|TEST|CMP")) {
                opcodeCategories.put(opcode, "LOGICAL");
            }
            
            // Shifts & Rotates
            else if (opcode.matches("SHL|SHR|SAR|SAL|ROL|ROR|RCL|RCR")) {
                opcodeCategories.put(opcode, "SHIFT_ROTATE");
            }
            
            // System & Interrupts
            else if (opcode.matches("SYSCALL|INT.*|SYSENTER|SYSEXIT|SGDT|SIDT|SLDT|WRMSR|RDMSR")) {
                opcodeCategories.put(opcode, "SYSTEM_CALLS");
            }
            
            // Floating Point
            else if (opcode.matches("F.*")) {
                opcodeCategories.put(opcode, "FPU_ARITHMETIC");
            }
            
            // System Information and Random Number Generation
            else if (opcode.matches("PUSHF|POPF|CPUID|RDTSC|RDRAND|RDSEED")) {
                opcodeCategories.put(opcode, "CPU_FEATURES");
            }
            
            // Cryptography
            else if (opcode.startsWith("AES") || opcode.startsWith("SHA")) {
                opcodeCategories.put(opcode, "CRYPTOGRAPHIC");
            }
            
            // Miscellaneous (including flag operations)
            else {
                opcodeCategories.put(opcode, "MISC");
            }
        }
    }

    private static final int MIN_FUNCTION_SIZE = 10;  // instructions
    private static final int MIN_BLOCK_SIZE = 4;      // instructions
    private static final int INVALID_STACK_SIZE = -1;

    private void logError(String message, String functionName, String address, Exception e, String errorLocation) {
        String errorMsg = String.format("Error in function %s at %s: %s%s", 
            functionName, 
            address, 
            message,
            e != null ? " - " + e.getMessage() : ""  // Only add exception message if e is not null
        );
        println(errorMsg);
        
        // Add to errors array
        JSONObject error = new JSONObject();
        error.put("function_name", functionName);
        error.put("function_address", address);
        error.put("error_location", errorLocation);
        error.put("error_message", message);
        error.put("error_details", e != null ? e.getMessage() : "");
        error.put("error_type", e != null ? e.getClass().getSimpleName() : "Unknown");
        error.put("timestamp", System.currentTimeMillis());
        errors.put(error);
    }

    private String calculateSha256(String input) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
        StringBuilder hexString = new StringBuilder();
        for (byte b : hash) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }

    @Override
    public void run() throws Exception {
        ExecutorService mainExecutor = null;
        final int FUNCTION_TIMEOUT_SECONDS = 90;  // 1.5 minutes per function
        final int GLOBAL_TIMEOUT_SECONDS = 1080 ;    // 18 minutes global, 20 is the total timeout from Python

        try {
            // Initialize listing
            listing = currentProgram.getListing();
            initializeOpcodeMaps();
            
            // // Validate input arguments (expecting SHA256 of binary)
            String[] args = getScriptArgs();
            if (args.length < 1) {
                println("Error: SHA256 argument is required");
                return;
            }
            String binarySha256 = args[0];
            
            // Initialize decompiler interface
            decompInterface = new DecompInterface();
            DecompileOptions options = new DecompileOptions();
            // DecompInterface decompInterface = new DecompInterface();
            decompInterface.setOptions(options);
            
            // Open the current program
            if (!decompInterface.openProgram(currentProgram)) {
                println("Error: Could not open program for decompilation");
                return;
            }
            
            basicBlockModel = new BasicBlockModel(currentProgram);

            // Create main executor for the whole analysis
            mainExecutor = Executors.newSingleThreadExecutor();

            Future<?> analysisTask = mainExecutor.submit(() -> {
                try {

                    // Create main JSON object
                    JSONObject outputJson = new JSONObject();
                    outputJson.put("sha256", binarySha256);
                    JSONArray decompiled = new JSONArray();
                    outputJson.put("decompiled", decompiled);
                    JSONArray disassembled = new JSONArray();
                    outputJson.put("disassembled", disassembled);
                    JSONArray cfg = new JSONArray();
                    outputJson.put("cfg", cfg);

                    // Initialize the errors array
                    errors = new JSONArray();
                    outputJson.put("errors", errors);

                    // Iterate through all functions
                    FunctionIterator functions = currentProgram.getFunctionManager().getFunctions(true);
                    for (Function function : functions) {
                        try {
                            // Create executor service for timeouts
                            ExecutorService executor = Executors.newSingleThreadExecutor();
                            // final int TIMEOUT_SECONDS = 60;  // 1 minute timeout

                            // 1. Decompile block with timeout
                            Future<?> decompileFuture = executor.submit(() -> {
                                try {
                                    DecompileResults results = decompInterface.decompileFunction(function, 30, monitor);
                                    if (results.decompileCompleted()) {
                                        String decompiledCode = results.getDecompiledFunction().getC();
                                        JSONObject functionJson = new JSONObject();
                                        String contentHash = calculateSha256(decompiledCode);
                                        functionJson.put("decompiled_content_hash", contentHash);
                                        functionJson.put("decompiled_function", decompiledCode);
                                        functionJson.put("decompiled_function_name", function.getName());
                                        functionJson.put("decompiled_function_address", function.getEntryPoint().toString());
                                        functionJson.put("function_type", determineFunctionType(function));
                                        decompiled.put(functionJson);
                                    }
                                } catch (Exception e) {
                                    logError("Failed in decompilation block", function.getName(), 
                                            function.getEntryPoint().toString(), e, "decompile");
                                }
                            });

                            try {
                                decompileFuture.get(FUNCTION_TIMEOUT_SECONDS, TimeUnit.SECONDS);
                            } catch (TimeoutException e) {
                                logError("Timeout in decompilation block", function.getName(), 
                                        function.getEntryPoint().toString(), null, "decompile");
                                decompileFuture.cancel(true);
                            }

                            // 2. Disassembly block with timeout
                            Future<?> disassemblyFuture = executor.submit(() -> {
                                try {
                                    JSONObject disassemblyJson = extractDisassembly(function);
                                    if (disassemblyJson != null) {
                                        disassemblyJson.put("function_type", determineFunctionType(function));
                                        disassembled.put(disassemblyJson);
                                    }
                                } catch (Exception e) {
                                    logError("Failed in disassembly block", function.getName(), 
                                            function.getEntryPoint().toString(), e, "disassembly");
                                }
                            });

                            try {
                                disassemblyFuture.get(FUNCTION_TIMEOUT_SECONDS, TimeUnit.SECONDS);
                            } catch (TimeoutException e) {
                                logError("Timeout in disassembly block", function.getName(), 
                                        function.getEntryPoint().toString(), null, "disassembly");
                                disassemblyFuture.cancel(true);
                            }

                            // 3. CFG block with timeout
                            Future<?> cfgFuture = executor.submit(() -> {
                                try {
                                    CodeBlockIterator blocks = basicBlockModel.getCodeBlocksContaining(function.getBody(), monitor);
                                    while (blocks.hasNext()) {
                                        CodeBlock block = blocks.next();
                                        JSONObject blockJson = extractBasicBlock(block, function);
                                        if (blockJson != null) {
                                            cfg.put(blockJson);
                                        }
                                    }
                                } catch (Exception e) {
                                    logError("Failed in CFG block", function.getName(), 
                                            function.getEntryPoint().toString(), e, "cfg");
                                }
                            });

                            try {
                                cfgFuture.get(FUNCTION_TIMEOUT_SECONDS, TimeUnit.SECONDS);
                            } catch (TimeoutException e) {
                                logError("Timeout in CFG block", function.getName(), 
                                        function.getEntryPoint().toString(), null, "cfg");
                                cfgFuture.cancel(true);
                            }

                            // Shutdown executor
                            executor.shutdownNow();

                        } catch (Exception e) {
                            logError("Failed to process function", function.getName(), 
                                    function.getEntryPoint().toString(), e, "unknown");
                            // Continue with next function
                        }
                    }
                    
                    try {
                        // Print the final JSON to stdout for Python to capture
                        System.out.println(outputJson.toString());
                    } catch (Exception e) {
                        System.out.println("Error: Failed to output final JSON: " + e.getMessage()); 
                    }
                } catch (Exception e) {
                        System.out.println("Fatal error in analysis: " + e.getMessage());
                }
            });

            // Wait for completion with a global timeout
            try {
                analysisTask.get(GLOBAL_TIMEOUT_SECONDS, TimeUnit.SECONDS); // 5 minute global timeout
            } catch (TimeoutException e) {
                println("Global analysis timeout reached");
                Thread.sleep(5000);  // 5 second grace period
            }
        } finally {
            // Cleanup section
            println("Starting cleanup process...");
            if (mainExecutor != null) {
                mainExecutor.shutdownNow(); // Force shutdown of all tasks
                try {
                    if (!mainExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
                        println("Warning: Some tasks did not terminate");
                    }
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                }
            }

            cleanup();

            // // Print thread state for debugging
            // println("Active threads after cleanup:");
            // Thread.getAllStackTraces().forEach((thread, stackTrace) -> {
            //     println("Thread: " + thread.getName() + " - State: " + thread.getState());
            // });
            
            // Force exit if we're still hanging
            println("Analysis complete, forcing exit...");
            System.exit(0);  // This is a bit aggressive but will ensure termination
        }
    }

    private void cleanup() {
        println("Executing cleanup...");
        try {
            // Force cleanup of any remaining resources
            if (decompInterface != null) {
                println("Closing decompiler interface...");
                decompInterface.closeProgram();
                decompInterface.dispose();
            }
            
            // Clear any thread locals or static resources
            decompInterface = null;
            listing = null;
            basicBlockModel = null;
            errors = null;
            
            // Request garbage collection
            // System.gc();
            
            println("Cleanup completed successfully");
        } catch (Exception e) {
            println("Error during cleanup: " + e.getMessage());
        }
    }

    private JSONObject extractDisassembly(Function function) throws Exception {
        if (function.isExternal() || 
            function.isThunk() || 
            function.getSymbol().isExternal() ||
            function.getEntryPoint().toString().startsWith("00105")) {  // Your external functions all start with 00105
            return null;
        }
        // Add debug for non-external functions that fail
        if (!function.isExternal() && listing.getInstructionAt(function.getEntryPoint()) == null) {
            println(String.format("Debug: Function %s at %s has no instructions but is not external", 
                function.getName(), function.getEntryPoint().toString()));
            return null;
        }

        JSONObject disassemblyJson = new JSONObject();
        try {
            // Check minimum function size first
            int instructionCount = 0;
            AddressSetView functionBody = function.getBody();
            Instruction instruction = listing.getInstructionAt(function.getEntryPoint());
            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                instructionCount++;
                instruction = instruction.getNext();
            }
            
            if (instructionCount < MIN_FUNCTION_SIZE) {
                return null;  // Skip functions that are too small
            }

            StringBuilder disassemblyBuilder = new StringBuilder();
            StringBuilder[] normalizedBuilders = new StringBuilder[3];  // One for each normalization level
            for (int i = 0; i < 3; i++) {
                normalizedBuilders[i] = new StringBuilder();
            }
            // int instructionCount = 0;

            // Get function body
            instruction = null;
            // AddressSetView functionBody = function.getBody();
            // Instruction instruction = null;

            // Iterate through instructions
            try {
                instruction = listing.getInstructionAt(function.getEntryPoint());
            } catch (Exception e) {
                logError("Failed to get first instruction", function.getName(), 
                        function.getEntryPoint().toString(), e, "extractDisassembly");
                return null;
            }

            if (instruction == null) {
                // Don't log error for external functions
                if (!function.isExternal()) {
                    logError("Failed to get first instruction", function.getName(),
                            function.getEntryPoint().toString(), null, "extractDisassembly");
                }
                return null;
            }

            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                try {
                    // Original disassembly with addresses
                    disassemblyBuilder.append(instruction.getAddress().toString())
                                    .append(": ")
                                    .append(instruction.toString())
                                    .append("\n");
                    
                    // Normalized disassembly (just mnemonics and generic operands)
                    try {
                        String[] normalizedVersions = normalizeInstructionAllLevels(instruction);
                        for (int i = 0; i < 3; i++) {
                            normalizedBuilders[i].append(normalizedVersions[i]);
                            if (isControlFlowInstruction(instruction)) {
                                normalizedBuilders[i].append(" <TARGET>");
                            }
                            normalizedBuilders[i].append("\n");
                        }
                        // normalizedBuilder.append(normalizeInstruction(instruction));
                        // if (isControlFlowInstruction(instruction)) {
                        //     normalizedBuilder.append(" <TARGET>");  // Abstract away specific targets
                        // }
                        // normalizedBuilder.append("\n");
                    } catch (Exception e) {
                        logError("Failed to normalize instruction", function.getName(), 
                                instruction.getAddress().toString(), e, "extractDisassembly");
                        // Continue with next instruction
                    }

                    // instructionCount++;
                    instruction = instruction.getNext();
                } catch (Exception e) {
                    logError("Failed processing instruction", function.getName(), 
                            instruction.getAddress().toString(), e, "extractDisassembly");
                    break; // Exit loop if we can't process further instructions
                }
            }

            String disassemblyStr = disassemblyBuilder.toString();
            try {
                disassemblyJson.put("disassembled_content_hash", calculateSha256(disassemblyStr));
                disassemblyJson.put("fully_normalized_content_hash", calculateSha256(normalizedBuilders[0].toString()));
                disassemblyJson.put("api_normalized_content_hash", calculateSha256(normalizedBuilders[1].toString()));
                disassemblyJson.put("category_normalized_content_hash", calculateSha256(normalizedBuilders[2].toString()));
                disassemblyJson.put("disassembled_function", disassemblyStr);
                disassemblyJson.put("fully_normalized_disassembly", normalizedBuilders[0].toString());
                disassemblyJson.put("api_normalized_disassembly", normalizedBuilders[1].toString());
                disassemblyJson.put("category_normalized_disassembly", normalizedBuilders[2].toString());
                disassemblyJson.put("disassembled_function_name", function.getName());
                disassemblyJson.put("disassembled_function_address", function.getEntryPoint().toString());
                disassemblyJson.put("instruction_count", instructionCount);
                Map<String, Integer> typeFrequencies = collectInstructionTypes(function);
                disassemblyJson.put("instruction_types", new JSONArray(typeFrequencies.keySet()));

                disassemblyJson.put("control_flow_count", countControlFlowInstructions(function));
                disassemblyJson.put("memory_access_pattern", new JSONArray(collectMemoryPatterns(function)));
                disassemblyJson.put("register_usage", new JSONArray(collectRegisterUsage(function)));
                disassemblyJson.put("data_references_count", countDataReferences(function));
                // disassemblyJson.put("opcode_frequency_vector", new JSONArray(computeOpcodeFrequency(function)));
                // disassemblyJson.put("api_calls_vector", new JSONArray(computeApiCallsVector(function)));
                // disassemblyJson.put("minhash_signature", new JSONArray(computeMinHash(function, 16)));  // 16 hashes
                disassemblyJson.put("max_block_size", computeMaxBlockSize(function));
                disassemblyJson.put("num_calls", computeNumCalls(function));
                disassemblyJson.put("stack_size", estimateStackSize(function));
                // Map<String, Double> ratios = calculateInstructionTypeRatios(typeFrequencies);
                // disassemblyJson.put("instruction_type_ratios", new JSONArray(convertRatiosToArray(ratios)));

                // String picHash = calculatePicHash(function);
                // if (picHash != null) {
                //     disassemblyJson.put("pic_hash", picHash);
                // }
  
            } catch (Exception e) {
                logError("Failed to create JSON object", function.getName(), 
                        function.getEntryPoint().toString(), e, "extractDisassembly");
                return null;
            }
            
            return disassemblyJson;
        } catch (Exception e) {
            logError("Fatal error in disassembly extraction", function.getName(), 
                    function.getEntryPoint().toString(), e, "extractDisassembly");
            return null;
        }
    }


    private String[] normalizeInstructionAllLevels(Instruction instruction) {
        StringBuilder[] normalized = new StringBuilder[3];
        for (int i = 0; i < 3; i++) {
            normalized[i] = new StringBuilder();
        }

        try {
            String mnemonic = instruction.getMnemonicString();
            for (int i = 0; i < 3; i++) {
                normalized[i].append(mnemonic);
            }

            for (int i = 0; i < instruction.getNumOperands(); i++) {
                String operand = instruction.getDefaultOperandRepresentation(i);
                String[] normalizedOps = normalizeOperandAllLevels(operand, instruction, i);
                
                for (int level = 0; level < 3; level++) {
                    normalized[level].append(" ").append(normalizedOps[level]);
                }
            }
        } catch (Exception e) {
            // If normalization fails, return simple mnemonic
            String fallback = instruction.getMnemonicString() + " op";
            return new String[]{fallback, fallback, fallback};
        }

        return new String[]{
            normalized[0].toString(),
            normalized[1].toString(),
            normalized[2].toString()
        };
    }

    private String[] normalizeOperandAllLevels(String operand, Instruction instruction, int opIndex) {
        // Returns [fullyNormalized, apiNormalized, categoryNormalized]
        String[] normalizations = new String[3];
        
        operand = operand.trim().toUpperCase();
        
        // Handle API calls
        if (instruction.getOperandType(opIndex) == OperandType.ADDRESS || 
            (operand.startsWith("0X") && isLikelyApi(operand))) {
            
            String apiName = resolveApiName(operand, instruction);
            if (apiName != null) {
                normalizations[0] = "DATA_REF";  // Most abstract
                normalizations[1] = "API_" + apiName;  // Preserve exact API
                normalizations[2] = "API_" + ApiCategory.fromApi(apiName).name();  // Use category
                return normalizations;
            }
        }

        // Handle immediate values
        if (instruction.getOperandType(opIndex) == OperandType.SCALAR) {
            // Level 0: Most abstract
            normalizations[0] = "CONST";
            
            // Level 1: Keep small constants, normalize large ones
            try {
                long value = Long.decode(operand);
                if (value >= -16 && value <= 16) {
                    normalizations[1] = "CONST_" + value;
                } else {
                    normalizations[1] = "CONST_LARGE";
                }
            } catch (NumberFormatException e) {
                normalizations[1] = "CONST";
            }
            
            // Level 2: Distinguish between different types of constants
            if (operand.startsWith("0X")) {
                normalizations[2] = "CONST_HEX";
            } else {
                normalizations[2] = "CONST_DEC";
            }
            return normalizations;
        }
        
        // Handle registers
        if (instruction.getOperandType(opIndex) == OperandType.REGISTER) {
            // Level 0: Most abstract - just register type
            normalizations[0] = normalizeRegister(operand);
            
            // Level 1: Preserve register class but normalize within class
            if (operand.matches("E?[ABCD]X|R\\d+")) {
                normalizations[1] = "GPR_DATA";
            } else if (operand.matches("E?SI|E?DI")) {
                normalizations[1] = "GPR_INDEX";
            } else if (operand.matches("E?[BS]P|R?SP")) {
                normalizations[1] = "GPR_STACK";
            } else if (operand.matches("XMM\\d+")) {
                normalizations[1] = "XMM_REG";
            } else if (operand.matches("ST\\d+")) {
                normalizations[1] = "FPU_REG";
            } else {
                normalizations[1] = "OTHER_REG";
            }
            
            // Level 2: More specific register categorization
            if (operand.startsWith("R")) {
                normalizations[2] = "REG_64";
            } else if (operand.startsWith("E")) {
                normalizations[2] = "REG_32";
            } else if (operand.matches("[ABCD][XHL]|SI|DI|SP|BP")) {
                normalizations[2] = "REG_16_8";
            } else {
                normalizations[2] = "REG_SPECIAL";
            }
            return normalizations;
        }
        
        // Handle memory references
        if (operand.contains("[")) {
            // Level 0: Most abstract
            normalizations[0] = operand.matches(".*\\[.*[+-].*\\]") ? "MEM_OFF" : "MEM";
            
            // Level 1: Distinguish base register types
            String memContent = operand.replaceAll(".*\\[(.*?)\\].*", "$1");
            if (memContent.contains("ESP") || memContent.contains("EBP")) {
                normalizations[1] = "MEM_STACK";
            } else if (memContent.contains("ESI") || memContent.contains("EDI")) {
                normalizations[1] = "MEM_STRING";
            } else {
                normalizations[1] = "MEM_GENERAL";
            }
            
            // Level 2: More detailed memory access pattern
            if (memContent.contains("+") && memContent.contains("*")) {
                normalizations[2] = "MEM_SCALED_INDEX";
            } else if (memContent.contains("+") || memContent.contains("-")) {
                normalizations[2] = "MEM_BASE_OFFSET";
            } else {
                normalizations[2] = "MEM_DIRECT";
            }
            return normalizations;
        }
        
        // Handle string/data references that aren't APIs
        if (instruction.getOperandType(opIndex) == OperandType.ADDRESS || 
            operand.startsWith("0X") || 
            operand.matches(".*_.*")) {
            normalizations[0] = "DATA_REF";
            normalizations[1] = "DATA_" + (operand.startsWith("0X") ? "ADDR" : "SYM");
            normalizations[2] = "DATA_" + (operand.contains("str") || operand.contains("STR") ? "STRING" : "OTHER");
            return normalizations;
        }
        
        // Default case - keep original for all levels if we can't categorize
        normalizations[0] = normalizations[1] = normalizations[2] = operand;
        return normalizations;
    }

    private boolean isLikelyApi(String operand) {
        // Check for common API function patterns
        return operand.matches(".*_[A-Za-z].*") ||  // Has underscore followed by letters
            operand.matches("^[A-Z][a-z]+[A-Z].*") || // PascalCase pattern typical of Win32 APIs
            operand.matches(".*@.*") ||  // Has @ symbol (common in decorated names)
            operand.matches("^_.*[A-Z].*"); // Starts with underscore and has uppercase
    }

    // Helper method to resolve API names
    private String resolveApiName(String operand, Instruction instruction) {
        // Try to get symbol name if available
        Reference[] refs = instruction.getReferencesFrom();
        if (refs != null && refs.length > 0) {
            for (Reference ref : refs) {
                Address toAddr = ref.getToAddress();
                SymbolTable symbolTable = currentProgram.getSymbolTable();
                Symbol[] symbols = symbolTable.getSymbols(toAddr);
                if (symbols != null && symbols.length > 0) {
                    // First try to find a symbol that matches our API patterns
                    for (Symbol sym : symbols) {
                        String name = sym.getName();
                        if (isLikelyApi(name)) {  // reuse your existing API detection
                            name = name.replaceAll("^_*", "")  // Remove leading underscores
                                    .replaceAll("@.*$", "");  // Remove @ decorations
                            return name;
                        }
                    }
                    // If no API-like symbol found, fall back to first symbol
                    String name = symbols[0].getName()
                        .replaceAll("^_*", "")
                        .replaceAll("@.*$", "");
                    return name;
                }
            }
        }
        return null;
    }

    private String normalizeRegister(String register) {
        // Convert to uppercase for consistent matching
        register = register.toUpperCase();
        
        // General purpose registers
        if (register.matches("E?[ABCD]X|E?SI|E?DI|R\\d+")) {
            return "GPR";
        }
        // Stack/base pointers
        if (register.matches("E?[BS]P|R?SP")) {
            return "PTR";
        }
        // SIMD registers
        if (register.matches("XMM\\d+")) {
            return "XMM";
        }
        // FPU registers
        if (register.matches("ST\\d+")) {
            return "FPU";
        }
        // Any other register
        return "REG";
    }

    private boolean isControlFlowInstruction(Instruction instruction) {
        String mnemonic = instruction.getMnemonicString().toUpperCase();
        return mnemonic.startsWith("J") ||
               mnemonic.equals("CALL") ||
               mnemonic.equals("RET") ||
               mnemonic.equals("LOOP");
    }

    private Map<String, Integer> collectInstructionTypes(Function function) {
        Map<String, Integer> typeFrequencies = new HashMap<>();
        try {
            AddressSetView functionBody = function.getBody();
            Instruction instruction = listing.getInstructionAt(function.getEntryPoint());
            
            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                try {
                    String mnemonic = instruction.getMnemonicString().toUpperCase();
                    
                    // Data Movement Categories
                    if (mnemonic.matches("MOV|LEA|XCHG")) {
                        incrementFrequency(typeFrequencies, InstructionType.GENERAL_DATA_MOVEMENT.name());
                    }
                    else if (mnemonic.matches("PUSH|POP|ENTER|LEAVE|PUSHA|POPA")) {
                        incrementFrequency(typeFrequencies, InstructionType.STACK_MANAGEMENT.name());
                    }
                    else if (mnemonic.matches("MOVS|LODS|STOS|CMPS|SCAS|REP.*")) {
                        incrementFrequency(typeFrequencies, InstructionType.STRING_MANIPULATION.name());
                    }
                    
                    // Arithmetic Categories
                    else if (mnemonic.matches("ADD|SUB|INC|DEC")) {
                        incrementFrequency(typeFrequencies, InstructionType.BASIC_ARITHMETIC.name());
                    }
                    else if (mnemonic.matches("MUL|DIV|IMUL|IDIV")) {
                        incrementFrequency(typeFrequencies, InstructionType.MULTIPLICATION_DIVISION.name());
                    }
                    else if (mnemonic.matches("ADC|SBB")) {
                        incrementFrequency(typeFrequencies, InstructionType.CARRY_ARITHMETIC.name());
                    }
                    
                    // Logical Categories
                    else if (mnemonic.matches("AND|OR|XOR|NOT")) {
                        incrementFrequency(typeFrequencies, InstructionType.BITWISE_LOGIC.name());
                    }
                    else if (mnemonic.matches("TEST|CMP|SET[A-Z]+")) {
                        incrementFrequency(typeFrequencies, InstructionType.CONDITIONAL_LOGIC.name());
                    }
                    
                    // Control Flow Categories
                    else if (mnemonic.equals("JMP")) {
                        incrementFrequency(typeFrequencies, InstructionType.UNCONDITIONAL_JUMP.name());
                    }
                    else if (mnemonic.matches("J[A-Z]+") && !mnemonic.equals("JMP")) {
                        incrementFrequency(typeFrequencies, InstructionType.CONDITIONAL_JUMP.name());
                    }
                    else if (mnemonic.matches("CALL|RET")) {
                        incrementFrequency(typeFrequencies, InstructionType.FUNCTION_CONTROL.name());
                    }
                    else if (mnemonic.matches("LOOP.*")) {
                        incrementFrequency(typeFrequencies, InstructionType.LOOPING.name());
                    }
                    
                    // System Categories
                    else if (mnemonic.matches("SYSCALL|SYSENTER|INT")) {
                        incrementFrequency(typeFrequencies, InstructionType.SYSTEM_CALLS.name());
                    }
                    else if (mnemonic.matches("HLT|CLI|STI")) {
                        incrementFrequency(typeFrequencies, InstructionType.PRIVILEGED_INSTRUCTIONS.name());
                    }
                    else if (mnemonic.matches("CPUID|RDTSC|RDTSCP")) {
                        incrementFrequency(typeFrequencies, InstructionType.CPU_FEATURES.name());
                    }
                    
                    // SIMD & FPU Categories
                    else if (mnemonic.startsWith("V") && (
                        mnemonic.contains("PS") || mnemonic.contains("PD") || 
                        mnemonic.contains("SS") || mnemonic.contains("SD"))) {
                        incrementFrequency(typeFrequencies, InstructionType.AVX_SIMD.name());
                    }
                    else if (mnemonic.matches(".*(?:PS|PD|SS|SD).*") || 
                            mnemonic.startsWith("MM") || mnemonic.startsWith("P")) {
                        incrementFrequency(typeFrequencies, InstructionType.SSE_SIMD.name());
                    }
                    else if (mnemonic.matches("FLD|FST|FSTP")) {
                        incrementFrequency(typeFrequencies, InstructionType.BASIC_FPU.name());
                    }
                    else if (mnemonic.matches("FADD|FSUB|FMUL|FDIV|FSQRT")) {
                        incrementFrequency(typeFrequencies, InstructionType.FPU_ARITHMETIC.name());
                    }
                    
                    // Bit Operation Categories
                    else if (mnemonic.matches("SHL|SHR|SAR|SAL|ROR|ROL|RCR|RCL")) {
                        incrementFrequency(typeFrequencies, InstructionType.SHIFT_ROTATE.name());
                    }
                    else if (mnemonic.matches("BT|BTS|BTR|BTC|BSF|BSR")) {
                        incrementFrequency(typeFrequencies, InstructionType.BIT_TEST_MODIFY.name());
                    }
                    
                    // Special Categories
                    else if (mnemonic.matches("AES.*|SHA.*|RDRAND|RDSEED")) {
                        incrementFrequency(typeFrequencies, InstructionType.CRYPTOGRAPHIC_OPS.name());
                    }
                    else if (mnemonic.matches("NOP|UD2|INT3")) {
                        incrementFrequency(typeFrequencies, InstructionType.MISC_OPS.name());
                    }
                    
                    instruction = instruction.getNext();
                } catch (Exception e) {
                    logError("Failed to process instruction type", function.getName(), 
                            instruction.getAddress().toString(), e, "collectInstructionTypes");
                }
            }
        } catch (Exception e) {
            logError("Failed to collect instruction types", function.getName(), 
                    function.getEntryPoint().toString(), e, "collectInstructionTypes");
        }
        
        return typeFrequencies;
    }

    private void incrementFrequency(Map<String, Integer> frequencies, String type) {
        frequencies.put(type, frequencies.getOrDefault(type, 0) + 1);
    }

    /**
     * Collect memory access patterns in the function
     */
    private List<String> collectMemoryPatterns(Function function) {
        Set<String> patterns = new HashSet<>();
        try {
            AddressSetView functionBody = function.getBody();
            Instruction instruction = listing.getInstructionAt(function.getEntryPoint());
            
            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                try {
                    for (int i = 0; i < instruction.getNumOperands(); i++) {
                        String opRep = instruction.getDefaultOperandRepresentation(i);
                        // Check if operand uses memory (indicated by square brackets)
                        if (opRep.contains("[")) {
                            if (opRep.contains("+") || opRep.contains("-")) {
                                patterns.add("BASE_PLUS_OFFSET");
                            } else if (opRep.contains("*")) {
                                patterns.add("SCALED_INDEX");
                            } else {
                                patterns.add("DIRECT_MEMORY");
                            }
                        }
                    }
                    instruction = instruction.getNext();
                } catch (Exception e) {
                    logError("Failed to process memory pattern", function.getName(), 
                            instruction.getAddress().toString(), e, "collectMemoryPatterns");
                }
            }
        } catch (Exception e) {
            logError("Failed to collect memory patterns", function.getName(), 
                    function.getEntryPoint().toString(), e, "collectMemoryPatterns");
        }
        return new ArrayList<>(patterns);
    }

    /**
     * Collect register usage information
     */
    private List<String> collectRegisterUsage(Function function) {
        Set<String> registers = new HashSet<>();
        try {
            AddressSetView functionBody = function.getBody();
            Instruction instruction = listing.getInstructionAt(function.getEntryPoint());
            
            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                try {
                    for (int i = 0; i < instruction.getNumOperands(); i++) {
                        if ((instruction.getOperandType(i) & OperandType.REGISTER) != 0) {
                            String reg = instruction.getDefaultOperandRepresentation(i).toUpperCase();
                            // Categorize register type
                            if (reg.matches("E?[ABCD]X|R\\d+")) registers.add("GPR");
                            else if (reg.matches("E?[BS]P|R?SP")) registers.add("STACK_PTR");
                            else if (reg.matches("E?[SD]I")) registers.add("INDEX_PTR");
                            else if (reg.matches("XMM\\d+")) registers.add("SIMD");
                            else if (reg.matches("ST\\d+")) registers.add("FPU");
                            else registers.add("OTHER");
                        }
                    }
                    instruction = instruction.getNext();
                } catch (Exception e) {
                    logError("Failed to process register usage", function.getName(), 
                            instruction.getAddress().toString(), e, "collectRegisterUsage");
                }
            }
        } catch (Exception e) {
            logError("Failed to collect register usage", function.getName(), 
                    function.getEntryPoint().toString(), e, "collectRegisterUsage");
        }
        return new ArrayList<>(registers);
    }

    /**
     * Count references to data section
     */
    private int countDataReferences(Function function) {
        int count = 0;
        try {
            AddressSetView functionBody = function.getBody();
            Instruction instruction = listing.getInstructionAt(function.getEntryPoint());
            
            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                try {
                    // Count operands that access data
                    for (int i = 0; i < instruction.getNumOperands(); i++) {
                        String opRep = instruction.getDefaultOperandRepresentation(i);
                        // Look for data references like symbols, constants
                        if (instruction.getOperandType(i) == OperandType.SCALAR || 
                            opRep.matches(".*_[A-Za-z].*") ||  // Named references
                            (opRep.startsWith("0x") && !opRep.contains("[")) // Direct address without memory indirection
                        ) {
                            count++;
                        }
                    }
                    instruction = instruction.getNext();
                } catch (Exception e) {
                    logError("Failed to process data reference", function.getName(), 
                            instruction.getAddress().toString(), e, "countDataReferences");
                }
            }
        } catch (Exception e) {
            logError("Failed to count data references", function.getName(), 
                    function.getEntryPoint().toString(), e, "countDataReferences");
        }
        return count;
    }

    /**
     * Count control flow instructions (jumps, calls, returns)
     */
    private int countControlFlowInstructions(Function function) {
        int count = 0;
        try {
            AddressSetView functionBody = function.getBody();
            Instruction instruction = listing.getInstructionAt(function.getEntryPoint());
            
            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                try {
                    String mnemonic = instruction.getMnemonicString().toUpperCase();
                    // Check for jumps, calls, returns
                    if (mnemonic.startsWith("J") ||     // All jumps
                        mnemonic.equals("CALL") ||      // Calls
                        mnemonic.equals("RET") ||       // Returns
                        mnemonic.equals("LOOP")) {      // Loop instructions
                        count++;
                    }
                    instruction = instruction.getNext();
                } catch (Exception e) {
                    logError("Failed to process control flow instruction", function.getName(), 
                            instruction.getAddress().toString(), e, "countControlFlowInstructions");
                }
            }
        } catch (Exception e) {
            logError("Failed to count control flow instructions", function.getName(), 
                    function.getEntryPoint().toString(), e, "countControlFlowInstructions");
        }
        return count;
    }

    private JSONObject extractBasicBlock(CodeBlock block, Function function) {
        try {
            // Check minimum block size first
            int blockSize = 0;
            AddressIterator addrs = block.getAddresses(true);
            while (addrs.hasNext()) {
                Address addr = addrs.next();
                if (listing.getInstructionAt(addr) != null) {
                    blockSize++;
                }
            }
            
            if (blockSize < MIN_BLOCK_SIZE) {
                return null;  // Skip blocks that are too small
            }

            JSONObject blockJson = new JSONObject();
            String blockInstructions = getBlockInstructions(block);
            
            // Calculate block_id
            String blockIdInput = blockInstructions + 
                                block.getMinAddress().toString() +
                                block.getMaxAddress().toString() +
                                function.getEntryPoint().toString();
            String blockId = calculateSha256(blockIdInput);

            blockJson.put("block_id", blockId);
            blockJson.put("function_address", function.getEntryPoint().toString());
            blockJson.put("block_start_address", block.getMinAddress().toString());
            blockJson.put("block_end_address", block.getMaxAddress().toString());
            blockJson.put("block_instructions", blockInstructions);
            blockJson.put("block_size", blockSize);
            
            // Get predecessor blocks
            JSONArray predecessors = new JSONArray();
            CodeBlockReferenceIterator preds = block.getSources(monitor);
            while (preds.hasNext()) {
                CodeBlockReference ref = preds.next();
                predecessors.put(ref.getSourceAddress().toString());
            }
            if (predecessors.length() > 0) {
                blockJson.put("predecessor_blocks", predecessors);
            }

            // Get successor blocks
            JSONArray successors = new JSONArray();
            CodeBlockReferenceIterator succs = block.getDestinations(monitor);
            while (succs.hasNext()) {
                CodeBlockReference ref = succs.next();
                successors.put(ref.getDestinationAddress().toString());
            }
            if (successors.length() > 0) {
                blockJson.put("successor_blocks", successors);
            }

            // Determine if entry/exit block
            blockJson.put("is_entry_block", block.getMinAddress().equals(function.getEntryPoint()));
            blockJson.put("is_exit_block", successors.length() == 0);

            BranchType branchType = determineBranchType(block);
            blockJson.put("branch_type", branchType.name());

            // Add normalized instructions
            StringBuilder[] normalizedBuilders = new StringBuilder[3];  // One for each level
            for (int i = 0; i < 3; i++) {
                normalizedBuilders[i] = new StringBuilder();
            }

            addrs = block.getAddresses(true);
            while (addrs.hasNext()) {
                Address addr = addrs.next();
                Instruction instr = listing.getInstructionAt(addr);
                if (instr != null) {
                    String[] normalizedVersions = normalizeInstructionAllLevels(instr);
                    for (int i = 0; i < 3; i++) {
                        normalizedBuilders[i].append(normalizedVersions[i]);
                        if (isControlFlowInstruction(instr)) {
                            normalizedBuilders[i].append(" <TARGET>");
                        }
                        normalizedBuilders[i].append("\n");
                    }
                }
            }

            blockJson.put("fully_normalized_instructions", normalizedBuilders[0].toString());
            blockJson.put("api_normalized_instructions", normalizedBuilders[1].toString());
            blockJson.put("category_normalized_instructions", normalizedBuilders[2].toString());

            Set<String> constants = extractConstantReferences(block);
            if (!constants.isEmpty()) {
                blockJson.put("referenced_constants", new JSONArray(constants));
            }
            
            return blockJson;
        } catch (Exception e) {
            logError("Failed to process basic block", function.getName(), 
                    block.getMinAddress().toString(), e, "extractBasicBlock");
            return null;
        }
    }

    private String getBlockInstructions(CodeBlock block) {
        StringBuilder instructions = new StringBuilder();
        AddressIterator addresses = block.getAddresses(true);
        while (addresses.hasNext()) {
            Address addr = addresses.next();
            Instruction instr = listing.getInstructionAt(addr);
            if (instr != null) {
                instructions.append(addr.toString())
                        .append(": ")
                        .append(instr.toString())
                        .append("\n");
            }
        }
        return instructions.toString();
    }

    private BranchType determineBranchType(CodeBlock block) {
        try {
            Address lastInstrAddr = block.getMaxAddress();
            Instruction lastInstr = listing.getInstructionAt(lastInstrAddr);
            if (lastInstr == null) {
                return BranchType.UNKNOWN;
            }

            String mnemonic = lastInstr.getMnemonicString().toUpperCase();
            
            // Check for return instructions
            if (mnemonic.equals("RET") || mnemonic.equals("RETN")) {
                return BranchType.RETURN;
            }
            
            // Check for call instructions
            if (mnemonic.equals("CALL")) {
                return BranchType.CALL;
            }
            
            // Check for jumps
            if (mnemonic.startsWith("J")) {
                // Unconditional jumps
                if (mnemonic.equals("JMP")) {
                    return BranchType.DIRECT;
                }
                // Conditional jumps (JE, JNE, JG, JLE, etc.)
                return BranchType.CONDITIONAL;
            }
            
            // Check number of successors
            CodeBlockReferenceIterator succs = block.getDestinations(monitor);
            if (succs.hasNext()) {
                return BranchType.FALLTHROUGH;
            }
            
            return BranchType.UNKNOWN;
        } catch (Exception e) {
            logError("Failed to determine branch type", "", block.getMinAddress().toString(), e, "determineBranchType");
            return BranchType.UNKNOWN;
        }
    }

    private Set<String> extractConstantReferences(CodeBlock block) {
        Set<String> constants = new HashSet<>();
        try {
            AddressIterator addresses = block.getAddresses(true);
            while (addresses.hasNext()) {
                Address addr = addresses.next();
                Instruction instr = listing.getInstructionAt(addr);
                if (instr == null) continue;

                // Process each operand
                for (int i = 0; i < instr.getNumOperands(); i++) {
                    int opType = instr.getOperandType(i);
                    String opRep = instr.getDefaultOperandRepresentation(i);
                    
                    // Immediate values
                    if ((opType & OperandType.SCALAR) != 0) {
                        constants.add("IMM:" + opRep);
                    }
                    
                    // Memory offsets
                    if (opRep.contains("[")) {
                        String offset = opRep.replaceAll(".*\\[(.*?)\\].*", "$1");
                        if (offset.matches("^[+-]?\\d+$") || offset.startsWith("0x")) {
                            constants.add("OFF:" + offset);
                        }
                    }
                    
                    // Data references
                    Reference[] refs = instr.getOperandReferences(i);
                    if (refs != null) {
                        for (Reference ref : refs) {
                            if (ref.getReferenceType().isData()) {
                                constants.add("DATA:" + ref.getToAddress());
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            logError("Failed to extract constants", "", block.getMinAddress().toString(), e, "extractConstantReferences");
        }
        return constants;
    }

    private String determineFunctionType(Function function) {
        try {
            if (function.isExternal()) {
                return "EXTERNAL";
            }
            if (function.isThunk()) {
                return "THUNK";
            }
            // Check if it's a library function by name pattern or location
            String name = function.getName();
            if (name.startsWith("__") || 
                name.contains("@") || 
                function.getEntryPoint().toString().startsWith("00105")) {
                return "LIBRARY";
            }
            return "USER";
        } catch (Exception e) {
            logError("Failed to determine function type", function.getName(), 
                    function.getEntryPoint().toString(), e, "determineFunctionType");
            return "UNKNOWN";
        }
    }

    private float[] computeOpcodeFrequency(Function function) {
        float[] frequencies = new float[COMMON_OPCODES.length];
        int totalInstructions = 0;
        
        try {
            AddressSetView functionBody = function.getBody();
            Instruction instruction = listing.getInstructionAt(function.getEntryPoint());
            
            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                String mnemonic = instruction.getMnemonicString();
                String normalized = normalizeOpcode(mnemonic);
                
                Integer index = opcodeIndex.get(normalized);
                if (index != null) {
                    frequencies[index]++;
                }
                
                totalInstructions++;
                instruction = instruction.getNext();
            }
            
            // Normalize
            if (totalInstructions > 0) {
                for (int i = 0; i < frequencies.length; i++) {
                    frequencies[i] /= totalInstructions;
                }
            }
            
        } catch (Exception e) {
            logError("Failed to compute opcode frequencies", function.getName(), 
                function.getEntryPoint().toString(), e, "computeOpcodeFrequency");
        }
        
        return frequencies;
    }


    private String normalizeOpcode(String mnemonic) {
        String normalized = mnemonic.trim().toUpperCase();
        
        // Handle prefixes
        if (normalized.startsWith("REP") || normalized.startsWith("REPE") || normalized.startsWith("REPNE")) {
            normalized = normalized.substring(normalized.indexOf(' ') + 1);
        }
        
        // Direct matches first
        if (opcodeIndex.containsKey(normalized)) {
            return normalized;
        }
        
        // Group categorization
        if (normalized.matches("MOV[AU]PS|MOVDQ[AU]|VMOVDQ[AU]|VMOV[AU]PS")) {
            return "SIMD_MOVE";
        }
        
        if (normalized.matches("J[GLABE][E]?|JG?[EZSC]|JN[GLABE][E]?|JN[EZSC]")) {
            return "COND_JUMP_EXT";
        }
        
        if (normalized.matches("MOVS|STOS|LODS|SCAS|CMPS|MOVSB|MOVSW|MOVSD")) {
            return "STRING_OP";
        }
        
        if (normalized.matches("ENTER|LEAVE|PUSHA|POPA")) {
            return "STACK_ADV";
        }
        
        if (normalized.matches("IMUL|IDIV|ADC|SBB|NEG|BSWAP")) {
            return "ARITHMETIC_ADV";
        }
        
        if (normalized.matches("SHL|SHR|SAR|SAL|ROL|ROR|RCL|RCR|BT[SR]?|BSF|BSR")) {
            return "BIT_OP";
        }
        
        if (normalized.startsWith("F")) {
            return "FPU_OP";
        }
        
        if (normalized.matches("SYSCALL|INT|SYSENTER|SYSEXIT")) {
            return "SYSTEM_OP";
        }
        
        if (normalized.matches("AES.*|SHA.*|RDRAND|RDSEED")) {
            return "CRYPTO_OP";
        }
        
        if (normalized.matches("CPUID|RDTSC|UD2|HLT|PAUSE")) {
            return "MISC_OP";
        }
        
        return normalized;  // Keep as is if no categorization matches
    }


    // method for API calls vector
    private float[] computeApiCallsVector(Function function) {
        // Initialize vector with one position per API category
        float[] apiVector = new float[ApiCategory.values().length];
        int totalCalls = 0;
        
        AddressSetView functionBody = function.getBody();
        Instruction instruction = listing.getInstructionAt(function.getEntryPoint());
        
        while (instruction != null && functionBody.contains(instruction.getAddress())) {
            if (instruction.getMnemonicString().equals("CALL")) {
                for (int i = 0; i < instruction.getNumOperands(); i++) {
                    String apiName = resolveApiName(
                        instruction.getDefaultOperandRepresentation(i), 
                        instruction
                    );
                    if (apiName != null) {
                        ApiCategory category = ApiCategory.fromApi(apiName);
                        apiVector[category.ordinal()]++;
                        totalCalls++;
                    }
                }
            }
            instruction = instruction.getNext();
        }
        
        // Normalize to frequencies
        if (totalCalls > 0) {
            for (int i = 0; i < apiVector.length; i++) {
                apiVector[i] /= totalCalls;
            }
        }
        
        return apiVector;
    }

    private long[] computeMinHash(Function function, int numHashes) {
        long[] signature = new long[numHashes];
        Arrays.fill(signature, Long.MAX_VALUE);
        
        AddressSetView functionBody = function.getBody();
        Instruction instruction = listing.getInstructionAt(function.getEntryPoint());

        while (instruction != null && functionBody.contains(instruction.getAddress())) {
            String[] normalizedVersions = normalizeInstructionAllLevels(instruction);
            String token = normalizedVersions[0];  // Fully normalized instruction
            
            // Hash token using numHashes different hash functions
            for (int i = 0; i < numHashes; i++) {
                long hash = murmurHash64(token, i) & Long.MAX_VALUE;  // Ensure non-negative
                signature[i] = Math.min(signature[i], hash);
            }

            instruction = instruction.getNext();
        }

        return signature;
    }

    // MurmurHash3 function for better MinHashing
    private long murmurHash64(String token, int seed) {
        return Murmur3.hash_x64_128(token.getBytes(StandardCharsets.UTF_8), token.length(), seed)[0];
    }

    private long calculateTokenHash(String token, long seed) {
        // MurmurHash3-like hashing
        long h = seed;
        
        for (char c : token.toCharArray()) {
            h ^= c;
            h *= 0x5bd1e995;
            h ^= h >>> 13;
        }
        
        return h;
    }

    /*
    PicHash calculation which:
    - Uses the fully normalized instruction representation
    - Creates a position-independent hash by normalizing addresses
    - Takes first 64 bits (16 chars) of SHA-256
    */
    private String calculatePicHash(Function function) {
        try {
            StringBuilder normalizedFunction = new StringBuilder();
            AddressSetView functionBody = function.getBody();
            Instruction instruction = listing.getInstructionAt(function.getEntryPoint());
            
            // Check minimum size threshold
            int instructionCount = 0;
            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                instructionCount++;
                instruction = instruction.getNext();
            }
            if (instructionCount < MIN_FUNCTION_SIZE) {
                return null;
            }
            
            // Reset to start of function for actual processing
            instruction = listing.getInstructionAt(function.getEntryPoint());
            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                String[] normalizedVersions = normalizeInstructionAllLevels(instruction);
                // Use fully normalized version (index 0) for PicHash
                normalizedFunction.append(normalizedVersions[0]).append("\n");
                instruction = instruction.getNext();
            }
            
            // Calculate SHA-256 and take first 16 characters (64 bits)
            return calculateSha256(normalizedFunction.toString()).substring(0, 16);
        } catch (Exception e) {
            logError("Failed to calculate PicHash", function.getName(), 
                    function.getEntryPoint().toString(), e, "calculatePicHash");
            return null;
        }
    }

    private int computeMaxBlockSize(Function function) {
        try {
            int maxSize = 0;
            CodeBlockIterator blocks = basicBlockModel.getCodeBlocksContaining(function.getBody(), monitor);
            while (blocks.hasNext()) {
                CodeBlock block = blocks.next();
                int blockSize = 0;
                AddressIterator addrs = block.getAddresses(true);
                while (addrs.hasNext()) {
                    Address addr = addrs.next();
                    if (listing.getInstructionAt(addr) != null) {
                        blockSize++;
                    }
                }
                maxSize = Math.max(maxSize, blockSize);
            }
            return maxSize;
        } catch (Exception e) {
            logError("Failed to compute max block size", function.getName(), 
                    function.getEntryPoint().toString(), e, "computeMaxBlockSize");
            return 0;
        }
    }

    private int computeNumCalls(Function function) {
        try {
            int callCount = 0;
            AddressSetView functionBody = function.getBody();
            Instruction instruction = listing.getInstructionAt(function.getEntryPoint());
            
            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                if (instruction.getMnemonicString().toUpperCase().equals("CALL")) {
                    callCount++;
                }
                instruction = instruction.getNext();
            }
            return callCount;
        } catch (Exception e) {
            logError("Failed to compute call count", function.getName(), 
                    function.getEntryPoint().toString(), e, "computeNumCalls");
            return 0;
        }
    }

    private int estimateStackSize(Function function) {
        try {
            // Look for stack adjustment in function prologue
            Instruction instruction = listing.getInstructionAt(function.getEntryPoint());
            AddressSetView functionBody = function.getBody();
            boolean foundProlog = false;
            int stackSize = INVALID_STACK_SIZE;
            
            // Look for common prolog patterns
            while (instruction != null && functionBody.contains(instruction.getAddress())) {
                String mnemonic = instruction.getMnemonicString().toUpperCase();
                
                // Look for PUSH EBP/RBP followed by MOV EBP/RBP, ESP/RSP
                if (mnemonic.equals("PUSH") && 
                    instruction.getDefaultOperandRepresentation(0).toUpperCase().matches(".*BP")) {
                    foundProlog = true;
                }
                // Look for SUB ESP/RSP, immediate
                else if (foundProlog && mnemonic.equals("SUB") && 
                        instruction.getDefaultOperandRepresentation(0).toUpperCase().matches(".*SP")) {
                    String immValue = instruction.getDefaultOperandRepresentation(1);
                    try {
                        // Handle hex values
                        if (immValue.startsWith("0x")) {
                            stackSize = Integer.parseInt(immValue.substring(2), 16);
                        } else {
                            stackSize = Integer.parseInt(immValue);
                        }
                        break;
                    } catch (NumberFormatException nfe) {
                        // If we can't parse the value, continue
                        continue;
                    }
                }
                instruction = instruction.getNext();
            }
            return stackSize;
        } catch (Exception e) {
            logError("Failed to estimate stack size", function.getName(), 
                    function.getEntryPoint().toString(), e, "estimateStackSize");
            return INVALID_STACK_SIZE;
        }
    }

    // Helper method to calculate instruction type ratios
    private Map<String, Double> calculateInstructionTypeRatios(Map<String, Integer> typeFrequencies) {
        Map<String, Double> ratios = new HashMap<>();
        if (typeFrequencies.isEmpty()) return ratios;
        
        // Calculate total instructions
        int total = typeFrequencies.values().stream().mapToInt(Integer::intValue).sum();
        
        // Calculate ratios
        for (Map.Entry<String, Integer> entry : typeFrequencies.entrySet()) {
            ratios.put(entry.getKey(), entry.getValue() / (double)total);
        }
        
        return ratios;
    }

    // Method to convert ratios to array format for storage
    private float[] convertRatiosToArray(Map<String, Double> ratios) {
        float[] array = new float[InstructionType.values().length];
        for (InstructionType type : InstructionType.values()) {
            array[type.ordinal()] = ratios.getOrDefault(type.name(), 0.0).floatValue();
        }
        return array;
    }
}