📄 gencode.c
字号:
/* gencode.c -- Motorola 68HC11 & 68HC12 Emulator Generator Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Written by Stephane Carrez (stcarrez@nerim.fr)This file is part of GDB, GAS, and the GNU binutils.GDB, GAS, and the GNU binutils are free software; you can redistributethem and/or modify them under the terms of the GNU General PublicLicense as published by the Free Software Foundation; either version2, or (at your option) any later version.GDB, GAS, and the GNU binutils are distributed in the hope that theywill be useful, but WITHOUT ANY WARRANTY; without even the impliedwarranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Seethe GNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <stdio.h>#include <string.h>#include <stdarg.h>#include <errno.h>#include "ansidecl.h"#include "opcode/m68hc11.h"#define TABLE_SIZE(X) (sizeof(X) / sizeof(X[0]))/* Combination of CCR flags. */#define M6811_ZC_BIT M6811_Z_BIT|M6811_C_BIT#define M6811_NZ_BIT M6811_N_BIT|M6811_Z_BIT#define M6811_NZV_BIT M6811_N_BIT|M6811_Z_BIT|M6811_V_BIT#define M6811_NZC_BIT M6811_N_BIT|M6811_Z_BIT|M6811_C_BIT#define M6811_NVC_BIT M6811_N_BIT|M6811_V_BIT|M6811_C_BIT#define M6811_ZVC_BIT M6811_Z_BIT|M6811_V_BIT|M6811_C_BIT#define M6811_NZVC_BIT M6811_ZVC_BIT|M6811_N_BIT#define M6811_HNZVC_BIT M6811_NZVC_BIT|M6811_H_BIT#define M6811_HNVC_BIT M6811_NVC_BIT|M6811_H_BIT#define M6811_VC_BIT M6811_V_BIT|M6811_C_BIT/* Flags when the insn only changes some CCR flags. */#define CHG_NONE 0,0,0#define CHG_Z 0,0,M6811_Z_BIT#define CHG_C 0,0,M6811_C_BIT#define CHG_ZVC 0,0,M6811_ZVC_BIT#define CHG_NZC 0,0,M6811_NZC_BIT#define CHG_NZV 0,0,M6811_NZV_BIT#define CHG_NZVC 0,0,M6811_NZVC_BIT#define CHG_HNZVC 0,0,M6811_HNZVC_BIT#define CHG_ALL 0,0,0xff/* The insn clears and changes some flags. */#define CLR_I 0,M6811_I_BIT,0#define CLR_C 0,M6811_C_BIT,0#define CLR_V 0,M6811_V_BIT,0#define CLR_V_CHG_ZC 0,M6811_V_BIT,M6811_ZC_BIT#define CLR_V_CHG_NZ 0,M6811_V_BIT,M6811_NZ_BIT#define CLR_V_CHG_ZVC 0,M6811_V_BIT,M6811_ZVC_BIT#define CLR_N_CHG_ZVC 0,M6811_N_BIT,M6811_ZVC_BIT /* Used by lsr */#define CLR_VC_CHG_NZ 0,M6811_VC_BIT,M6811_NZ_BIT/* The insn sets some flags. */#define SET_I M6811_I_BIT,0,0#define SET_C M6811_C_BIT,0,0#define SET_V M6811_V_BIT,0,0#define SET_Z_CLR_NVC M6811_Z_BIT,M6811_NVC_BIT,0#define SET_C_CLR_V_CHG_NZ M6811_C_BIT,M6811_V_BIT,M6811_NZ_BIT#define SET_Z_CHG_HNVC M6811_Z_BIT,0,M6811_HNVC_BIT#define _M 0xffstatic int cpu_type;struct m6811_opcode_pattern { const char *name; const char *pattern; const char *ccr_update;};/* * { "test", M6811_OP_NONE, 1, 0x00, 5, _M, CHG_NONE }, * Name -+ +---- Insn CCR changes * Format ------+ +---------- Max # cycles * Size -----------------+ +--------------- Min # cycles * +-------------------- Opcode */struct m6811_opcode_pattern m6811_opcode_patterns[] = { /* Move 8 and 16 bits. We need two implementations: one that sets the flags and one that preserve them. */ { "movtst8", "dst8 = src8", "cpu_ccr_update_tst8 (proc, dst8)" }, { "movtst16", "dst16 = src16", "cpu_ccr_update_tst16 (proc, dst16)" }, { "mov8", "dst8 = src8" }, { "mov16", "dst16 = src16" }, { "lea16", "dst16 = addr" }, /* Conditional branches. 'addr' is the address of the branch. */ { "bra", "cpu_set_pc (proc, addr)" }, { "bhi", "if ((cpu_get_ccr (proc) & (M6811_C_BIT|M6811_Z_BIT)) == 0)\n@ \ cpu_set_pc (proc, addr)" }, { "bls", "if ((cpu_get_ccr (proc) & (M6811_C_BIT|M6811_Z_BIT)))\n@ \ cpu_set_pc (proc, addr)" }, { "bcc", "if (!cpu_get_ccr_C (proc))\n@ cpu_set_pc (proc, addr)" }, { "bcs", "if (cpu_get_ccr_C (proc))\n@ cpu_set_pc (proc, addr)" }, { "bne", "if (!cpu_get_ccr_Z (proc))\n@ cpu_set_pc (proc, addr)" }, { "beq", "if (cpu_get_ccr_Z (proc))\n@ cpu_set_pc (proc, addr)" }, { "bvc", "if (!cpu_get_ccr_V (proc))\n@ cpu_set_pc (proc, addr)" }, { "bvs", "if (cpu_get_ccr_V (proc))\n@ cpu_set_pc (proc, addr)" }, { "bpl", "if (!cpu_get_ccr_N (proc))\n@ cpu_set_pc (proc, addr)" }, { "bmi", "if (cpu_get_ccr_N (proc))\n@ cpu_set_pc (proc, addr)" }, { "bge", "if ((cpu_get_ccr_N (proc) ^ cpu_get_ccr_V (proc)) == 0)\n@ cpu_set_pc (proc, addr)" }, { "blt", "if ((cpu_get_ccr_N (proc) ^ cpu_get_ccr_V (proc)))\n@ cpu_set_pc (proc, addr)" }, { "bgt", "if ((cpu_get_ccr_Z (proc) | (cpu_get_ccr_N (proc) ^ cpu_get_ccr_V (proc))) == 0)\n@ \ cpu_set_pc (proc, addr)" }, { "ble", "if ((cpu_get_ccr_Z (proc) | (cpu_get_ccr_N (proc) ^ cpu_get_ccr_V (proc))))\n@ \ cpu_set_pc (proc, addr)" }, /* brclr and brset perform a test and a conditional jump at the same time. Flags are not changed. */ { "brclr8", "if ((src8 & dst8) == 0)\n@ cpu_set_pc (proc, addr)" }, { "brset8", "if (((~src8) & dst8) == 0)\n@ cpu_set_pc (proc, addr)" }, { "rts11", "addr = cpu_m68hc11_pop_uint16 (proc); cpu_set_pc (proc, addr); cpu_return(proc)" }, { "rts12", "addr = cpu_m68hc12_pop_uint16 (proc); cpu_set_pc (proc, addr); cpu_return(proc)" }, { "mul16", "dst16 = ((uint16) src8 & 0x0FF) * ((uint16) dst8 & 0x0FF)", "cpu_set_ccr_C (proc, src8 & 0x80)" }, { "neg8", "dst8 = - src8", "cpu_set_ccr_C (proc, src8 == 0); cpu_ccr_update_tst8 (proc, dst8)" }, { "com8", "dst8 = ~src8", "cpu_set_ccr_C (proc, 1); cpu_ccr_update_tst8 (proc, dst8);" }, { "clr8", "dst8 = 0", "cpu_set_ccr (proc, (cpu_get_ccr (proc) & (M6811_S_BIT|M6811_X_BIT|M6811_H_BIT| \M6811_I_BIT)) | M6811_Z_BIT)"}, { "clr16","dst16 = 0", "cpu_set_ccr (proc, (cpu_get_ccr (proc) & (M6811_S_BIT|M6811_X_BIT|M6811_H_BIT| \M6811_I_BIR)) | M6811_Z_BIT)"}, /* 8-bits shift and rotation. */ { "lsr8", "dst8 = src8 >> 1", "cpu_set_ccr_C (proc, src8 & 1); cpu_ccr_update_shift8 (proc, dst8)" }, { "lsl8", "dst8 = src8 << 1", "cpu_set_ccr_C (proc, (src8 & 0x80) >> 7); cpu_ccr_update_shift8 (proc, dst8)" }, { "asr8", "dst8 = (src8 >> 1) | (src8 & 0x80)", "cpu_set_ccr_C (proc, src8 & 1); cpu_ccr_update_shift8 (proc, dst8)" }, { "ror8", "dst8 = (src8 >> 1) | (cpu_get_ccr_C (proc) << 7)", "cpu_set_ccr_C (proc, src8 & 1); cpu_ccr_update_shift8 (proc, dst8)" }, { "rol8", "dst8 = (src8 << 1) | (cpu_get_ccr_C (proc))", "cpu_set_ccr_C (proc, (src8 & 0x80) >> 7); cpu_ccr_update_shift8 (proc, dst8)" }, /* 16-bits shift instructions. */ { "lsl16", "dst16 = src16 << 1", "cpu_set_ccr_C (proc, (src16&0x8000) >> 15); cpu_ccr_update_shift16 (proc, dst16)"}, { "lsr16", "dst16 = src16 >> 1", "cpu_set_ccr_C (proc, src16 & 1); cpu_ccr_update_shift16 (proc, dst16)"}, { "dec8", "dst8 = src8 - 1", "cpu_ccr_update_tst8 (proc, dst8)" }, { "inc8", "dst8 = src8 + 1", "cpu_ccr_update_tst8 (proc, dst8)" }, { "tst8", 0, "cpu_set_ccr_C (proc, 0); cpu_ccr_update_tst8 (proc, src8)" }, { "sub8", "cpu_ccr_update_sub8 (proc, dst8 - src8, dst8, src8);\dst8 = dst8 - src8", 0 }, { "add8", "cpu_ccr_update_add8 (proc, dst8 + src8, dst8, src8);\dst8 = dst8 + src8", 0 }, { "sbc8", "if (cpu_get_ccr_C (proc))\n@ \{\n\ cpu_ccr_update_sub8 (proc, dst8 - src8 - 1, dst8, src8);\n\ dst8 = dst8 - src8 - 1;\n\}\n\else\n\{\n\ cpu_ccr_update_sub8 (proc, dst8 - src8, dst8, src8);\n\ dst8 = dst8 - src8;\n\}", 0 }, { "adc8", "if (cpu_get_ccr_C (proc))\n@ \{\n\ cpu_ccr_update_add8 (proc, dst8 + src8 + 1, dst8, src8);\n\ dst8 = dst8 + src8 + 1;\n\}\n\else\n\{\n\ cpu_ccr_update_add8 (proc, dst8 + src8, dst8, src8);\n\ dst8 = dst8 + src8;\n\}", 0 }, /* 8-bits logical operations. */ { "and8", "dst8 = dst8 & src8", "cpu_ccr_update_tst8 (proc, dst8)" }, { "eor8", "dst8 = dst8 ^ src8", "cpu_ccr_update_tst8 (proc, dst8)" }, { "or8", "dst8 = dst8 | src8", "cpu_ccr_update_tst8 (proc, dst8)" }, { "bclr8","dst8 = (~dst8) & src8", "cpu_ccr_update_tst8 (proc, dst8)" }, /* 16-bits add and subtract instructions. */ { "sub16", "cpu_ccr_update_sub16 (proc, dst16 - src16, dst16, src16);\dst16 = dst16 - src16", 0 }, { "add16", "cpu_ccr_update_add16 (proc, dst16 + src16, dst16, src16);\dst16 = dst16 + src16", 0 }, { "inc16", "dst16 = src16 + 1", "cpu_set_ccr_Z (proc, dst16 == 0)" }, { "dec16", "dst16 = src16 - 1", "cpu_set_ccr_Z (proc, dst16 == 0)" }, /* Special increment/decrement for the stack pointer: flags are not changed. */ { "ins16", "dst16 = src16 + 1" }, { "des16", "dst16 = src16 - 1" }, { "jsr_11_16", "cpu_m68hc11_push_uint16 (proc, cpu_get_pc (proc)); cpu_call (proc, addr)"}, { "jsr_12_16", "cpu_m68hc12_push_uint16 (proc, cpu_get_pc (proc)); cpu_call (proc, addr)"}, /* xgdx and xgdx patterns. Flags are not changed. */ { "xgdxy16", "dst16 = cpu_get_d (proc); cpu_set_d (proc, src16)"}, { "stop", "cpu_special (proc, M6811_STOP)"}, /* tsx, tsy, txs, tys don't affect the flags. Sp value is corrected by +/- 1. */ { "tsxy16", "dst16 = src16 + 1;"}, { "txys16", "dst16 = src16 - 1;"}, /* Add b to X or Y with an unsigned extension 8->16. Flags not changed. */ { "abxy16","dst16 = dst16 + (uint16) src8"}, /* After 'daa', the Z flag is undefined. Mark it as changed. */ { "daa8", "cpu_special (proc, M6811_DAA)" }, { "nop", 0 }, /* Integer divide: (parallel (set IX (div D IX)) (set D (mod D IX))) */ { "idiv16", "if (src16 == 0)\n{\n\dst16 = 0xffff;\}\nelse\n{\n\cpu_set_d (proc, dst16 % src16);\dst16 = dst16 / src16;\}", "cpu_set_ccr_Z (proc, dst16 == 0); cpu_set_ccr_V (proc, 0);\cpu_set_ccr_C (proc, src16 == 0)" }, /* Fractional divide: (parallel (set IX (div (mul D 65536) IX) (set D (mod (mul D 65536) IX)))) */ { "fdiv16", "if (src16 <= dst16 )\n{\n\dst16 = 0xffff;\n\cpu_set_ccr_Z (proc, 0);\n\cpu_set_ccr_V (proc, 1);\n\cpu_set_ccr_C (proc, dst16 == 0);\n\}\nelse\n{\n\unsigned long l = (unsigned long) (dst16) << 16;\n\cpu_set_d (proc, (uint16) (l % (unsigned long) (src16)));\n\dst16 = (uint16) (l / (unsigned long) (src16));\n\cpu_set_ccr_V (proc, 0);\n\cpu_set_ccr_C (proc, 0);\n\cpu_set_ccr_Z (proc, dst16 == 0);\n\}", 0 }, /* Operations to get/set the CCR. */ { "clv", 0, "cpu_set_ccr_V (proc, 0)" }, { "sev", 0, "cpu_set_ccr_V (proc, 1)" }, { "clc", 0, "cpu_set_ccr_C (proc, 0)" }, { "sec", 0, "cpu_set_ccr_C (proc, 1)" }, { "cli", 0, "cpu_set_ccr_I (proc, 0)" }, { "sei", 0, "cpu_set_ccr_I (proc, 1)" }, /* Some special instructions are implemented by 'cpu_special'. */ { "rti11", "cpu_special (proc, M6811_RTI)" }, { "rti12", "cpu_special (proc, M6812_RTI)" }, { "wai", "cpu_special (proc, M6811_WAI)" }, { "test", "cpu_special (proc, M6811_TEST)" }, { "swi", "cpu_special (proc, M6811_SWI)" }, { "syscall","cpu_special (proc, M6811_EMUL_SYSCALL)" }, { "page2", "cpu_page2_interp (proc)", 0 }, { "page3", "cpu_page3_interp (proc)", 0 }, { "page4", "cpu_page4_interp (proc)", 0 }, /* 68HC12 special instructions. */ { "bgnd", "cpu_special (proc, M6812_BGND)" }, { "call8", "cpu_special (proc, M6812_CALL)" }, { "call_ind", "cpu_special (proc, M6812_CALL_INDIRECT)" }, { "dbcc8", "cpu_dbcc (proc)" }, { "ediv", "cpu_special (proc, M6812_EDIV)" },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -