📄 writecode.c
字号:
/* generate instructions for Z8KSIM Copyright 1992, 1993, 2002 Free Software Foundation, Inc.This file is part of Z8KSIMZ8KSIM is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.Z8KSIM is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with Z8KZIM; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* This program generates the code which emulates each of the z8k instructions code goes into three files, tc-gen1.h, tc-gen2.h and tc-gen3.h. which file being made depends upon the options -1 tc-gen1.h contains the fully expanded code for some selected opcodes, (those in the quick.c list) -2 tc-gen2.h contains a list of pointers to functions, one for each opcode. It points to functions in tc-gen3.h and tc-gen1.h depending upon quick.c -3 tc-gen3.h contains all the opcodes in unexpanded form. -b3 tc-genb3.h same as -3 but for long pointers *//* steve chamberlain sac@cygnus.com */#include "config.h"#include <ansidecl.h>#include <stdio.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#else#ifdef HAVE_STRINGS_H#include <strings.h>#endif#endif#define NICENAMES#define DEFINE_TABLE#include "../opcodes/z8k-opc.h"#define NOPS 500struct opcode_value{ int n; struct opcode_value *next;};#define NICENAMESint BIG;static char *reg_names[] ={"bad", "src", "dst", "aux_a", "aux_b", "aux_r", "aux_x"};#define IS_DST(x) ((x & 0xf) == 2)#define IS_SRC(x) ((x & 0xf)==1)#define SIZE_ADDRESS (BIG ? 8 : 4) /* number of nibbles in a ptr*/static int file;static int nibs = 0;static char *current_size;static char *current_name;static char current_word0[40];static char current_byte0[40];static char current_byte1[40];static int indent;static char *p;static char *d;struct opcode_value *list[NOPS];static opcode_entry_type *lookup_inst (what) int what;{ static short *z8k_inv_list = NULL; const nr_z8k_inv_list_elements = 1 << 16; if (z8k_inv_list == NULL) { /* Initialize the list to 0xff == -1 */ z8k_inv_list = calloc (nr_z8k_inv_list_elements, sizeof (short)); memset (z8k_inv_list, 0xff, nr_z8k_inv_list_elements * sizeof (short)); } /* Entry empty? Fill it in. */ if (z8k_inv_list[what] == -1) { int nibl_index; int nibl_matched; unsigned short instr_nibl; unsigned short tabl_datum, datum_class, datum_value; char instr_nibbles[8]; opcode_entry_type *ptr = z8k_table; nibl_matched = 0; instr_nibbles[3] = (what >> 0) & 0xf; instr_nibbles[2] = (what >> 4) & 0xf; instr_nibbles[1] = (what >> 8) & 0xf; instr_nibbles[0] = (what >> 12) & 0xf; /* Assume it won't be found. */ z8k_inv_list[what] = -2; while (ptr->name) { nibl_matched = 1; for (nibl_index = 0; nibl_index < 4 && nibl_matched; nibl_index++) { instr_nibl = instr_nibbles[nibl_index]; tabl_datum = ptr->byte_info[nibl_index]; datum_class = tabl_datum & CLASS_MASK; datum_value = ~CLASS_MASK & tabl_datum; switch (datum_class) { case CLASS_BIT_1OR2: if (datum_value != (instr_nibl & ~0x2)) nibl_matched = 0; break; case CLASS_IGNORE: break; case CLASS_BIT: if (datum_value != instr_nibl) nibl_matched = 0; break; case CLASS_00II: if (!((~instr_nibl) & 0x4)) nibl_matched = 0; break; case CLASS_01II: if (!(instr_nibl & 0x4)) nibl_matched = 0; break; case CLASS_0CCC: if (!((~instr_nibl) & 0x8)) nibl_matched = 0; break; case CLASS_1CCC: if (!(instr_nibl & 0x8)) nibl_matched = 0; break; case CLASS_0DISP7: if (!((~instr_nibl) & 0x8)) nibl_matched = 0; nibl_index += 1; break; case CLASS_1DISP7: if (!(instr_nibl & 0x8)) nibl_matched = 0; nibl_index += 1; break; case CLASS_REGN0: if (instr_nibl == 0) nibl_matched = 0; break; default: break; } } if (nibl_matched) { z8k_inv_list[what] = ptr->idx; break; /* while */ } ptr++; } } if (z8k_inv_list[what] >= 0) return z8k_table + z8k_inv_list[what]; return 0;}static char *insn_4 (n) int n;{ switch (n) { case 1: return "((iwords_0>>8) & 0xf)"; case 2: return "((ibytes_1 >> 4) & 0xf)"; case 3: return "((ibytes_1) & 0xf)"; case 4: return "((ibytes_2>>4) & 0xf)"; case 5: return "((ibytes_2) & 0xf)"; case 6: return "((ibytes_3 >> 4) & 0xf)"; case 7: return "((ibytes_3) & 0xf)"; default: return "****"; }}char *ptr_mode (){ if (BIG) { return "ptr_long"; } return "word";}staticchar *ptr_size (){ if (BIG) return "4"; return "2";}static char *reg_n (x) unsigned int x;{ return reg_names[x & 0xf];}char *stack_ptr (){ return BIG ? "14" : "15";}char *mem (){#if 0 return BIG ? "segmem" : "unsegmem";#else return "mem";#endif}intmatch (a) char *a;{ if (strncmp (p, a, strlen (a)) == 0) { p += strlen (a); return 1; } return 0;}staticvoidsub (y) char *y;{ sprintf (d, "%s", y); d += strlen (d);}static char *insn_16 (n) int n;{ switch (n) { case 0: return "(iwords_0)"; case 4: return "(iwords_1)"; case 8: return "(iwords_2)"; case 12: return "(iwords_3)"; default: return "****"; }}staticchar *insn_32 (n) int n;{ switch (n) { case 0: return "((iwords_0<<16) | (iwords_1))"; case 4: return "((iwords_1<<16) | (iwords_2))"; case 8: return "((iwords_2<<16) | (iwords_3))"; default: return "****"; }}static char *size_name (x) int x;{ switch (x) { case 8: return "byte"; case 16: return "word"; case 32: return "long"; case 64: return "quad"; } return "!!";}/*VARARGS*/voidemit (string, a1, a2, a3, a4, a5) char *string; char* a1; char* a2; char* a3; char* a4; char* a5;{ int indent_inc = 0; int indent_dec = 0; int i; char buffer[1000]; d = buffer; p = string; while (*p) { if (match ("<fop>")) { if (BIG) { sub ("bfop"); } else { sub ("sfop"); } } else if (match ("<iptr>")) { if (BIG) { switch (nibs) { case 4: sub ("(((iwords_1 << 8) | (iwords_2)) & 0x7fffff)"); break; default: sub ("fail(context,124)"); break; } } else { switch (nibs) { case 4: sub ("iwords_1"); break; default: sub ("fail(context,123)"); break; } } } else if (match ("<name>")) { sub (current_name); } else if (match ("<size>")) { sub (current_size); } else if (match ("<insn_4>")) { sub (insn_4 (nibs)); } else if (match ("<insn_16>")) { sub (insn_16 (nibs)); } else if (match ("<insn_32>")) { sub (insn_32 (nibs)); } else if (match ("iwords_0")) { sub (current_word0); } else if (match ("ibytes_0")) { sub (current_byte0); } else if (match ("<ibytes_1>")) { sub (current_byte1); } else if (match ("<next_size>")) { if (strcmp (current_size, "word") == 0) sub ("long"); if (strcmp (current_size, "byte") == 0) sub ("word"); else if (strcmp (current_size, "long") == 0) sub ("quad"); else abort (); } else if (match ("<addr_type>")) { if (BIG) sub ("unsigned long"); else sub ("unsigned short"); } else if (match ("<c_size>")) { if (strcmp (current_size, "word") == 0) sub ("short"); else if (strcmp (current_size, "byte") == 0) sub ("char"); else if (strcmp (current_size, "long") == 0) sub ("long"); else abort (); } else if (match ("<pc>")) { sub ("pc"); } else if (match ("<mem>")) { sub (mem ()); } else if (match ("<sp>")) { sub (stack_ptr ()); } else if (match ("<ptr_size>")) { sub (ptr_size ()); } else if (match ("<ptr_mode>")) { sub (ptr_mode ()); } else if (match ("<insn_8>")) { switch (nibs) { case 2: sub ("(iwords_0&0xff)"); break; case 4: sub ("(iwords_1>>8)"); break; case 6: sub ("(iwords_1&0xff)"); break; case 8: sub ("(iwords_2>>8)"); break; case 12: sub ("(/* WHO */iwords_3&0xff)"); break; default: abort (); } } else { if (*p == '{') indent_inc++; if (*p == '}') indent_dec++; *d++ = *p; p++; } } *d++ = 0; indent -= indent_dec; for (i = 0; i < indent; i++) printf ("\t"); indent += indent_inc; printf (buffer, a1, a2, a3, a4, a5);}/* fetch the lvalues of the operands */voidinfo_args (p) opcode_entry_type *p;{ unsigned int *s; int done_one_imm8 = 0; /* int done_read = 4;*/ s = p->byte_info; nibs = 0; while (*s) { switch (*s & CLASS_MASK) { case CLASS_BIT_1OR2: emit ("register unsigned int imm_src=(<insn_4>& 2)?2:1;\n"); break; case CLASS_IGNORE: case CLASS_BIT: /* Just ignore these, we've already decoded this bit */ nibs++; break; case CLASS_REGN0: case CLASS_REG: /* this nibble tells us which register to use as an arg, if we've already gobbled the nibble we know what to use */ { int regname = *s & 0xf; emit ("register unsigned int reg_%s=<insn_4>;\n", reg_names[regname]); nibs++; } break; case CLASS_ADDRESS: emit ("register unsigned base_%s=<iptr>;\n", reg_n (*s)); nibs += SIZE_ADDRESS; break; case CLASS_01II: case CLASS_00II: emit ("register unsigned int imm_src=<insn_4>&0x2;\n"); nibs++; break; case CLASS_FLAGS: emit ("register unsigned int imm_src=<insn_4>;\n"); nibs++;break; case CLASS_IMM: /* Work out the size of the think to fetch */ { switch (*s & ~CLASS_MASK) { case ARG_IMM16: emit ("register unsigned imm_src=<insn_16>;\n"); nibs += 4; break; case ARG_IMM32: emit ("register unsigned int imm_src= %s;\n", insn_32 (nibs)); nibs += 8; break; case ARG_IMM4: emit ("register unsigned int imm_src=<insn_4>;\n"); nibs++; break; case ARG_NIM4: emit ("register unsigned int imm_src = - <insn_4>;\n"); nibs++; break; case ARG_IMM2: emit ("register unsigned int imm_src=<insn_4> & 0x2;\n"); nibs++; break; case ARG_IMM4M1: emit ("register unsigned int imm_src=(<insn_4> + 1);\n"); nibs++; break; case ARG_IMM_1: emit ("register unsigned int imm_src=1;\n"); break; case ARG_IMM_2: emit ("register unsigned int imm_src=2;\n"); break; case ARG_NIM8: emit ("register unsigned int imm_src=-<insn_8>;\n"); nibs += 2; break; case ARG_IMM8: if (!done_one_imm8) { emit ("register unsigned int imm_src=<insn_8>;\n"); nibs += 2; done_one_imm8 = 1; } break; default: emit ("register int fail%d=fail(context,1);\n", nibs); break; } break; case CLASS_DISP8: /* We can't use `(char)' since char might be unsigned. We can't use `(signed char)' because the compiler might be K&R. This seems safe, since it only assumes that bytes are 8 bits. */ emit ("register unsigned int oplval_dst=((ibytes_1 << (sizeof (int) * 8 - 8)) >> (sizeof (int) * 8 - 9)) + pc;\n");#if 0 /* Original code: fails if characters are unsigned. */ emit ("register unsigned int oplval_dst=(((char)ibytes_1)<<1) + pc;\n");#endif nibs += 2; break; case CLASS_CC: emit ("register unsigned int op_cc=<insn_4>;\n"); nibs++; break; default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -