/* -*-c-*- ------------------ mix_ins.c : * Implementation of the functions declared in mix_ins.h * ------------------------------------------------------------------ * Copyright (C) 1999, 2003 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "mix_ins.h" struct mix_ins_desc_ { mix_opcode_t opcode; mix_fspec_t def_fspec; const gchar *string_rep; gboolean is_ext; }; #define IDES_(c,f,s) {c,f,#s,FALSE} #define IDESX_(c,f,s) {c,f,#s,TRUE} static const struct mix_ins_desc_ id_to_desc_[] = { IDES_(0,0,NOP), IDES_(1,5,ADD), IDES_(2,5,SUB), IDES_(3,5,MUL), IDES_(4,5,DIV), IDESX_(5,0,NUM), IDESX_(5,1,CHAR), IDESX_(5,2,HLT), IDESX_(6,0,SLA), IDESX_(6,1,SRA), IDESX_(6,2,SLAX), IDESX_(6,3,SRAX), IDESX_(6,4,SLC), IDESX_(6,5,SRC), IDES_(7,1,MOVE), IDES_(8,5,LDA), IDES_(9,5,LD1), IDES_(10,5,LD2), IDES_(11,5,LD3), IDES_(12,5,LD4), IDES_(13,5,LD5), IDES_(14,5,LD6), IDES_(15,5,LDX), IDES_(16,5,LDAN), IDES_(17,5,LD1N), IDES_(18,5,LD2N), IDES_(19,5,LD3N), IDES_(20,5,LD4N), IDES_(21,5,LD5N), IDES_(22,5,LD6N), IDES_(23,5,LDXN), IDES_(24,5,STA), IDES_(25,5,ST1), IDES_(26,5,ST2), IDES_(27,5,ST3), IDES_(28,5,ST4), IDES_(29,5,ST5), IDES_(30,5,ST6), IDES_(31,5,STX), IDES_(32,2,STJ), IDES_(33,5,STZ), IDES_(34,0,JBUS), IDES_(35,0,IOC), IDES_(36,0,IN), IDES_(37,0,OUT), IDES_(38,0,JRED), IDESX_(39,0,JMP), IDESX_(39,1,JSJ), IDESX_(39,2,JOV), IDESX_(39,3,JNOV), IDESX_(39,4,JL), IDESX_(39,5,JE), IDESX_(39,6,JG), IDESX_(39,7,JGE), IDESX_(39,8,JNE), IDESX_(39,9,JLE), IDESX_(40,0,JAN), IDESX_(40,1,JAZ), IDESX_(40,2,JAP), IDESX_(40,3,JANN), IDESX_(40,4,JANZ), IDESX_(40,5,JANP), IDESX_(41,0,J1N), IDESX_(41,1,J1Z), IDESX_(41,2,J1P), IDESX_(41,3,J1NN), IDESX_(41,4,J1NZ), IDESX_(41,5,J1NP), IDESX_(42,0,J2N), IDESX_(42,1,J2Z), IDESX_(42,2,J2P), IDESX_(42,3,J2NN), IDESX_(42,4,J2NZ), IDESX_(42,5,J2NP), IDESX_(43,0,J3N), IDESX_(43,1,J3Z), IDESX_(43,2,J3P), IDESX_(43,3,J3NN), IDESX_(43,4,J3NZ), IDESX_(43,5,J3NP), IDESX_(44,0,J4N), IDESX_(44,1,J4Z), IDESX_(44,2,J4P), IDESX_(44,3,J4NN), IDESX_(44,4,J4NZ), IDESX_(44,5,J4NP), IDESX_(45,0,J5N), IDESX_(45,1,J5Z), IDESX_(45,2,J5P), IDESX_(45,3,J5NN), IDESX_(45,4,J5NZ), IDESX_(45,5,J5NP), IDESX_(46,0,J6N), IDESX_(46,1,J6Z), IDESX_(46,2,J6P), IDESX_(46,3,J6NN), IDESX_(46,4,J6NZ), IDESX_(46,5,J6NP), IDESX_(47,0,JXN), IDESX_(47,1,JXZ), IDESX_(47,2,JXP), IDESX_(47,3,JXNN), IDESX_(47,4,JXNZ), IDESX_(47,5,JXNP), IDESX_(48,0,INCA), IDESX_(48,1,DECA), IDESX_(48,2,ENTA), IDESX_(48,3,ENNA), IDESX_(49,0,INC1), IDESX_(49,1,DEC1), IDESX_(49,2,ENT1), IDESX_(49,3,ENN1), IDESX_(50,0,INC2), IDESX_(50,1,DEC2), IDESX_(50,2,ENT2), IDESX_(50,3,ENN2), IDESX_(51,0,INC3), IDESX_(51,1,DEC3), IDESX_(51,2,ENT3), IDESX_(51,3,ENN3), IDESX_(52,0,INC4), IDESX_(52,1,DEC4), IDESX_(52,2,ENT4), IDESX_(52,3,ENN4), IDESX_(53,0,INC5), IDESX_(53,1,DEC5), IDESX_(53,2,ENT5), IDESX_(53,3,ENN5), IDESX_(54,0,INC6), IDESX_(54,1,DEC6), IDESX_(54,2,ENT6), IDESX_(54,3,ENN6), IDESX_(55,0,INCX), IDESX_(55,1,DECX), IDESX_(55,2,ENTX), IDESX_(55,3,ENNX), IDES_(56,5,CMPA), IDES_(57,5,CMP1), IDES_(58,5,CMP2), IDES_(59,5,CMP3), IDES_(60,5,CMP4), IDES_(61,5,CMP5), IDES_(62,5,CMP6), IDES_(63,5,CMPX) }; static const gsize ID_TO_DESC_SIZE_= sizeof(id_to_desc_)/sizeof(id_to_desc_[0]); /* To look for the mix_ins_id corresponding to a pair (fspec,opcode) we use an array indexed by opcode with values (initial_ins, final_ins - initial_ins) */ struct mix_opcode_desc_ { mix_ins_id_t init_id; guchar inc; /* when inc == 0, the id does not depend on fspec */ }; static struct mix_opcode_desc_ opcode_to_id_[MIX_BYTE_MAX + 1]; /* a hash table mapping strings to mix_ins_id's */ static GHashTable *string_to_id_ = NULL; void mix_init_ins (void) { guint k; g_assert (ID_TO_DESC_SIZE_ == mix_INVALID_INS); for ( k = 0; k < MIX_BYTE_MAX + 1; ++k ) { opcode_to_id_[k].init_id = mix_INVALID_INS; opcode_to_id_[k].inc = 0; } for ( k = 0; k < ID_TO_DESC_SIZE_; ++k ) { if ( opcode_to_id_[id_to_desc_[k].opcode].init_id == mix_INVALID_INS ) opcode_to_id_[id_to_desc_[k].opcode].init_id = k; else ++opcode_to_id_[id_to_desc_[k].opcode].inc; } if ( string_to_id_ == NULL ) { string_to_id_ = g_hash_table_new (g_str_hash, g_str_equal); for ( k = 0; k < ID_TO_DESC_SIZE_; ++k) g_hash_table_insert (string_to_id_, (gpointer)id_to_desc_[k].string_rep, GUINT_TO_POINTER (k)); } } void mix_release_ins (void) { g_hash_table_destroy (string_to_id_); } /* Conversions between words and ins */ mix_word_t mix_ins_to_word (const mix_ins_t *ins) { g_return_val_if_fail (ins != NULL, MIX_WORD_ZERO); return (mix_word_t)((ins->address<<18)| ((ins->index&7)<<12)|(ins->fspec<<6)|(ins->opcode)); } mix_ins_id_t mix_word_to_ins (mix_word_t word, mix_ins_t *ins) { mix_ins_id_t result = mix_get_ins_id (mix_get_ins_opcode (word), mix_get_ins_fspec (word)); g_return_val_if_fail (ins != NULL, result); mix_word_to_ins_uncheck (word,*ins); return result; } /* Getting ins parameters */ mix_opcode_t mix_get_opcode_from_id (mix_ins_id_t id) { g_return_val_if_fail (id < ID_TO_DESC_SIZE_, MIX_BYTE_ZERO); return id_to_desc_[id].opcode; } gboolean mix_ins_id_is_extended (mix_ins_id_t id) { g_return_val_if_fail (id < ID_TO_DESC_SIZE_, FALSE); return id_to_desc_[id].is_ext; } mix_fspec_t mix_get_fspec_from_id (mix_ins_id_t id) { g_return_val_if_fail (id < ID_TO_DESC_SIZE_, MIX_BYTE_ZERO); return id_to_desc_[id].def_fspec; } const gchar * mix_get_string_from_id (mix_ins_id_t id) { g_return_val_if_fail (id < ID_TO_DESC_SIZE_, NULL); return id_to_desc_[id].string_rep; } mix_ins_id_t mix_get_id_from_string (const gchar *name) { gpointer key, value; if ( !g_hash_table_lookup_extended (string_to_id_, (gpointer)name, &key, &value) ) return mix_INVALID_INS; return (mix_ins_id_t)GPOINTER_TO_UINT (value); } mix_ins_id_t mix_get_ins_id (mix_opcode_t code, mix_fspec_t fspec) { if ( opcode_to_id_[code].inc == 0 ) return opcode_to_id_[code].init_id; else if ( opcode_to_id_[code].inc < fspec ) return mix_INVALID_INS; else return (opcode_to_id_[code].init_id + fspec); } /* Printable representation */ extern gchar * /* this pointer must be freed by caller */ mix_ins_to_string (const mix_ins_t *ins) { gboolean needs_f; gchar *result; mix_ins_id_t id; g_return_val_if_fail (ins != NULL, NULL); id = mix_ins_id_from_ins (*ins); needs_f = ins->fspec != id_to_desc_[id].def_fspec; if ( needs_f ) result = g_strdup_printf ("%s\t%s%d,%d(%d:%d)", mix_get_string_from_id (id), mix_short_is_negative (ins->address) ? "-" : "", mix_short_magnitude (ins->address), ins->index, mix_fspec_left (ins->fspec), mix_fspec_right (ins->fspec)); else result = g_strdup_printf ("%s\t%s%d,%d", mix_get_string_from_id (id), mix_short_is_negative (ins->address) ? "-" : "", mix_short_magnitude (ins->address), ins->index); return result; } extern void mix_ins_to_string_in_buffer (const mix_ins_t *ins, gchar *buf, guint len) { gboolean needs_f; mix_ins_id_t id; g_return_if_fail (ins != NULL); g_return_if_fail (buf != NULL); id = mix_ins_id_from_ins (*ins); needs_f = ins->fspec != id_to_desc_[id].def_fspec; if ( needs_f ) g_snprintf (buf, len, "%s\t%s%d,%d(%d:%d)", mix_get_string_from_id (id), mix_short_is_negative (ins->address) ? "-" : "", mix_short_magnitude (ins->address), ins->index, mix_fspec_left (ins->fspec), mix_fspec_right (ins->fspec)); else g_snprintf (buf, len, "%s\t%s%d,%d", mix_get_string_from_id (id), mix_short_is_negative (ins->address) ? "-" : "", mix_short_magnitude (ins->address), ins->index); } void mix_ins_print (const mix_ins_t *ins) { g_return_if_fail (ins != NULL); g_print (mix_get_string_from_id (mix_ins_id_from_ins (*ins))); g_print (" %s%d,%d(%d:%d)", mix_short_is_negative (ins->address) ? "-" : "+", mix_short_magnitude (ins->address), ins->index, mix_fspec_left (ins->fspec), mix_fspec_right (ins->fspec)); }