This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH]: Improve HC11 simulator to support HC12


Hi!

This patch improves the 68HC11 simulator to also support the 68HC12.
The 68HC12 is very close to the 68HC11, although the instructions are
not binary compatible and the HC12 has many more.  The gencode now
generates two simulators one for HC11 and one for HC12.  The simulator
is configured according to `STATE_ARCHITECTURE (sd)'.

This simulator has been used for a while now (see http://www.gnu-m68hc11.org
and http://groups.yahoo.com/group/gnu-m68hc11), and I was a quite lazy in the
CVS integration.

I've comitted this patch now.

	Stephane

2001-05-20  Stephane Carrez  <Stephane.Carrez@worldnet.fr>

	* Makefile.in (M68HC11_OBJS): Add m68hc12int.o.
	(m68hc12int.c): Generate using gencode -m6812.
	(m68hc11int.c): Likewise with -m6811.
	* gencode.c (m6811_opcode_patterns): New patterns for 68HC12.
	(m6811_page1_opcodes): Remove duplicate entries.
	(m6811_page2_opcodes): Likewise.
	(m6811_page3_opcodes): Likewise.
	(m6811_page4_opcodes): Likewise.
	(m6812_page1_opcodes): New table for 68HC12 instructions.
	(m6812_page2_opcodes): Likewise.
	(gen_fetch_operands): New modes [] and &[] for 68HC12 operands.
	(gen_save_result): Likewise.
	(gen_interpreter_for_table): Handle 68HC11 and 68HC12 opcodes.
	(cmp_opcode): New function for opcode comparision.
	(prepare_table): Sort the opcodes.
	(gen_interpreter): Prepare all the tables and generate either
	a 68HC11 or a 68HC12 simulator.
	(main): New options -m6811 and -m6812.

	* m68hc11_sim.c (cpu_single_step): Use pointer to cpu interpretor.
	(cpu_special): Simulation of some 68HC12 instructions.
	(cpu_exg): New function.
	(cpu_dbcc): Likewise.
	(cpu_fetch_relbranch16): Likewise.
	(cpu_push_all): Push according to 68HC11 or 68HC12.
	(cpu_move16): Likewise.
	(cpu_move8): Likewise.
	(cpu_get_indexed_operand16): Likewise.
	(cpu_get_indexed_operand8): Likewise.
	(cpu_get_indexed_operand_addr): Likewise.
	(cpu_set_reg, cpu_set_dst_reg, cpu_get_src_reg, cpu_get_reg): Likewise.
	(cpu_reset): Setup INIT register according to architecture.
	
	* sim-main.h (M6811_Special): Add 68HC12 specific instructions.
	(_sim_cpu): Keep track of the cpu being simulated.
	(cpu_get_tmp3, cpu_get_tmp2, cpu_set_tmp3, cpu_set_tmp2): New.
	(cpu_m68hc11_push_uintxx): Rename of cpu_push_uintxx.
	(cpu_m68hc11_pop_uint8): Likewise.
	(cpu_m68hc12_push_uintxx): New functions for 68HC12.
	(cpu_m68hc12_pop_uintxx): Likewise.
	(cpu_exg, cpu_dbcc, cpu_move8, cpu_move16): Likewise,
	(cpu_fetch_relbranch16): Likewise.
	(cpu_interp_m6811): Rename of cpu_interp.
	(cpu_interp_m6812): New function.	
	* interp.c (free_state): New function.
	(dev_list_68hc12): New table.
	(sim_board_reset): Reset depending on the cpu (HC11 or HC12).
	(sim_hw_configure): New function.
	(sim_prepare_for_program): New function.
	(sim_open): Use above new functions.
	(sim_close): Call free_state().
	(sim_info): Print info according to cpu.
	(sim_create_inferior): Use sim_prepare_for_program.
	(sim_do_command): Configure the hardware after a change of the
	architecture.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/sim/m68hc11/Makefile.in,v
retrieving revision 1.1
diff -u -p -r1.1 Makefile.in
--- Makefile.in	2000/09/12 18:55:37	1.1
+++ Makefile.in	2001/05/20 15:32:13
@@ -1,5 +1,5 @@
 #    Makefile template for Configure for the 68HC11 sim library.
-#    Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+#    Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
 #    Written by Cygnus Support.
 # 
 # This program is free software; you can redistribute it and/or modify
@@ -18,7 +18,8 @@
 
 ## COMMON_PRE_CONFIG_FRAG
 
-M68HC11_OBJS = interp.o m68hc11int.o emulos.o interrupts.o m68hc11_sim.o
+M68HC11_OBJS = interp.o m68hc11int.o m68hc12int.o \
+		emulos.o interrupts.o m68hc11_sim.o
 
 # List of main object files for `run'.
 SIM_RUN_OBJS = nrun.o
@@ -49,10 +50,13 @@ INCLUDE = $(srcdir)/../../include/callba
 ## COMMON_POST_CONFIG_FRAG
 
 m68hc11int.c: gencode
-	./gencode > $@
+	./gencode -m6811 > $@
 
+m68hc12int.c: gencode
+	./gencode -m6812 > $@
+
 gencode:	gencode.c
-	$(CC_FOR_BUILD) $(BUILD_CFLAGS) -o gencode $<
+	$(CC_FOR_BUILD) $(BUILD_CFLAGS) -o gencode gencode.c
 
 interp.o: interp.c $(INCLUDE)
 
Index: gencode.c
===================================================================
RCS file: /cvs/src/src/sim/m68hc11/gencode.c,v
retrieving revision 1.1
diff -u -p -r1.1 gencode.c
--- gencode.c	2000/07/27 11:23:39	1.1
+++ gencode.c	2001/05/20 15:32:27
@@ -1,5 +1,5 @@
-/* gencode.c -- Motorola 68hc11 Emulator Generator
-   Copyright 1999, 2000 Free Software Foundation, Inc.
+/* gencode.c -- Motorola 68HC11 & 68HC12 Emulator Generator
+   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
    Written by Stephane Carrez (stcarrez@worldnet.fr)
 
 This file is part of GDB, GAS, and the GNU binutils.
@@ -32,16 +32,20 @@ with this program; if not, write to the 
 #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
@@ -55,6 +59,7 @@ with this program; if not, write to the 
 #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
@@ -62,9 +67,11 @@ with this program; if not, write to the 
 #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 0xff
 
+static int cpu_type;
 
 struct m6811_opcode_pattern 
 {
@@ -87,6 +94,7 @@ struct m6811_opcode_pattern m6811_opcode
   { "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)" },
@@ -121,7 +129,8 @@ struct m6811_opcode_pattern m6811_opcode
     "if (((~src8) & dst8) == 0)\n@  cpu_set_pc (proc, addr)" },
   
 
-  { "rts",  "addr = cpu_pop_uint16 (proc); cpu_set_pc (proc, addr); cpu_return(proc)" },
+  { "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)" },
@@ -203,11 +212,12 @@ dst16 = dst16 + src16", 0 },
   { "ins16", "dst16 = src16 + 1" },
   { "des16", "dst16 = src16 - 1" },
   
-  { "jsr16", "cpu_push_uint16 (proc, cpu_get_pc (proc)); cpu_call (proc, addr)"},
+  { "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", ""},
+  { "stop", "cpu_special (proc, M6811_STOP)"},
 
   /* tsx, tsy, txs, tys don't affect the flags.	 Sp value is corrected
      by +/- 1.	*/
@@ -218,7 +228,7 @@ dst16 = dst16 + src16", 0 },
   { "abxy16","dst16 = dst16 + (uint16) src8"},
 
   /* After 'daa', the Z flag is undefined. Mark it as changed.	*/
-  { "daa8",  "" },
+  { "daa8",  "cpu_special (proc, M6811_DAA)" },
   { "nop",  0 },
 
 
@@ -260,7 +270,8 @@ cpu_set_ccr_Z (proc, dst16 == 0);\n\
   { "sei",  0, "cpu_set_ccr_I (proc, 1)" },
 
   /* Some special instructions are implemented by 'cpu_special'.  */
-  { "rti",  "cpu_special (proc, M6811_RTI)" },
+  { "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)" },
@@ -268,7 +279,45 @@ cpu_set_ccr_Z (proc, dst16 == 0);\n\
 
   { "page2", "cpu_page2_interp (proc)", 0 },
   { "page3", "cpu_page3_interp (proc)", 0 },
-  { "page4", "cpu_page4_interp (proc)", 0 }
+  { "page4", "cpu_page4_interp (proc)", 0 },
+
+  /* 68HC12 special instructions.  */
+  { "bgnd",  "cpu_special (proc, M6812_BGND)" },
+  { "call8", "cpu_special (proc, M6812_CALL)" },
+  { "dbcc8", "cpu_dbcc (proc)" },
+  { "ediv",  "cpu_special (proc, M6812_EDIV)" },
+  { "emul",  "{ uint32 src1 = (uint32) cpu_get_d (proc);\
+  uint32 src2 = (uint32) cpu_get_y (proc);\
+  src1 *= src2;\
+  cpu_set_d (proc, src1);\
+  cpu_set_y (proc, src1 >> 16);\
+  cpu_set_ccr_Z (proc, src1 == 0);\
+  cpu_set_ccr_C (proc, src1 & 0x08000);\
+  cpu_set_ccr_N (proc, src1 & 0x80000000);}" },
+  { "emuls",  "cpu_special (proc, M6812_EMULS)" },
+  { "mem",   "cpu_special (proc, M6812_MEM)" },
+  { "rtc",   "cpu_special (proc, M6812_RTC)" },
+  { "emacs", "cpu_special (proc, M6812_EMACS)" },
+  { "idivs", "cpu_special (proc, M6812_IDIVS)" },
+  { "edivs", "cpu_special (proc, M6812_EDIVS)" },
+  { "exg8",  "cpu_exg (proc, src8)" },
+  { "move8", "cpu_move8 (proc, op)" },
+  { "move16","cpu_move16 (proc, op)" },
+
+  { "max8",  "cpu_ccr_update_sub8 (proc, dst8 - src8, dst8, src8);\
+              if (dst8 < src8) dst8 = src8" },
+  { "min8",  "cpu_ccr_update_sub8 (proc, dst8 - src8, dst8, src8);\
+              if (dst8 > src8) dst8 = src8" },
+  { "max16", "cpu_ccr_update_sub16 (proc, dst16 - src16, dst16, src16);\
+              if (dst16 < src16) dst16 = src16" },
+  { "min16", "cpu_ccr_update_sub16 (proc, dst16 - src16, dst16, src16);\
+              if (dst16 > src16) dst16 = src16" },
+
+  { "rev",   "cpu_special (proc, M6812_REV);" },
+  { "revw",  "cpu_special (proc, M6812_REVW);" },
+  { "wav",   "cpu_special (proc, M6812_WAV);" },
+  { "tbl8",  "cpu_special (proc, M6812_ETBL);" },
+  { "tbl16", "cpu_special (proc, M6812_ETBL);" }
 };
 
 /* Definition of an opcode of the 68HC11.  */
@@ -306,14 +355,13 @@ struct m6811_opcode_def
  * (y)->a     src8 = (IND, Y)		a = dst8
  * ()->b      src8 = (EXT)		b = dst8
  */
-const struct m6811_opcode_def m6811_page1_opcodes[] = {
+struct m6811_opcode_def m6811_page1_opcodes[] = {
   { "test", 0,		0,	     1, 0x00,  5, _M,  CHG_NONE },
   { "nop",  0,		0,	     1, 0x01,  2,  2,  CHG_NONE },
   { "idiv", "x,d->x",	"idiv16",    1, 0x02,  3, 41,  CLR_V_CHG_ZC},
   { "fdiv", "x,d->x",	"fdiv16",    1, 0x03,  3, 41,  CHG_ZVC},
   { "lsrd", "d->d",	"lsr16",     1, 0x04,  3,  3,  CLR_N_CHG_ZVC },
   { "asld", "d->d",	"lsl16",     1, 0x05,  3,  3,  CHG_NZVC },
-  { "lsld", "d->d",	"lsl16",     1, 0x05,  3,  3,  CHG_NZVC },
   { "tap",  "a->ccr",	"mov8",	     1, 0x06,  2,  2,  CHG_ALL},
   { "tpa",  "ccr->a",	"mov8",	     1, 0x07,  2,  2,  CHG_NONE },
   { "inx",  "x->x",	"inc16",     1, 0x08,  3,  3,  CHG_Z },
@@ -349,9 +397,7 @@ const struct m6811_opcode_def m6811_page
   { "bhi",  "r",	0,	     2, 0x22,  3,  3, CHG_NONE },
   { "bls",  "r",	0,	     2, 0x23,  3,  3, CHG_NONE },
   { "bcc",  "r",	0,	     2, 0x24,  3,  3, CHG_NONE },
-  { "bhs",  "r",	0,	     2, 0x24,  3,  3, CHG_NONE },
   { "bcs",  "r",	0,	     2, 0x25,  3,  3, CHG_NONE },
-  { "blo",  "r",	0,	     2, 0x25,  3,  3, CHG_NONE },
   { "bne",  "r",	0,	     2, 0x26,  3,  3, CHG_NONE },
   { "beq",  "r",	0,	     2, 0x27,  3,  3, CHG_NONE },
   { "bvc",  "r",	0,	     2, 0x28,  3,  3, CHG_NONE },
@@ -372,9 +418,9 @@ const struct m6811_opcode_def m6811_page
   { "psha", "a->(sp)",	"mov8",	     1, 0x36,  3,  3, CHG_NONE },
   { "pshb", "b->(sp)",	"mov8",	     1, 0x37,  3,  3, CHG_NONE },
   { "pulx", "(sp)->x",	"mov16",     1, 0x38,  5,  5, CHG_NONE },
-  { "rts",  0,		0,	     1, 0x39,  5,  5, CHG_NONE },
+  { "rts",  0,		"rts11",     1, 0x39,  5,  5, CHG_NONE },
   { "abx",  "b,x->x",	"abxy16",    1, 0x3a,  3,  3, CHG_NONE },
-  { "rti",  0,		0,	     1, 0x3b, 12, 12, CHG_ALL},
+  { "rti",  0,		"rti11",     1, 0x3b, 12, 12, CHG_ALL},
   { "pshx", "x->(sp)",	"mov16",     1, 0x3c,  4,  4, CHG_NONE },
   { "mul",  "b,a->d",	"mul16",     1, 0x3d,  3, 10, CHG_C },
   { "wai",  0,		0,	     1, 0x3e, 14, _M, CHG_NONE },
@@ -386,7 +432,6 @@ const struct m6811_opcode_def m6811_page
   { "rora", "a->a",	"ror8",	     1, 0x46,  2,  2, CHG_NZVC },
   { "asra", "a->a",	"asr8",	     1, 0x47,  2,  2, CHG_NZVC },
   { "asla", "a->a",	"lsl8",	     1, 0x48,  2,  2, CHG_NZVC },
-  { "lsla", "a->a",	"lsl8",	     1, 0x48,  2,  2, CHG_NZVC },
   { "rola", "a->a",	"rol8",	     1, 0x49,  2,  2, CHG_NZVC },
   { "deca", "a->a",	"dec8",	     1, 0x4a,  2,  2, CHG_NZV },
   { "inca", "a->a",	"inc8",	     1, 0x4c,  2,  2, CHG_NZV },
@@ -398,7 +443,6 @@ const struct m6811_opcode_def m6811_page
   { "rorb", "b->b",	"ror8",	     1, 0x56,  2,  2, CHG_NZVC },
   { "asrb", "b->b",	"asr8",	     1, 0x57,  2,  2, CHG_NZVC },
   { "aslb", "b->b",	"lsl8",	     1, 0x58,  2,  2, CHG_NZVC },
-  { "lslb", "b->b",	"lsl8",	     1, 0x58,  2,  2, CHG_NZVC },
   { "rolb", "b->b",	"rol8",	     1, 0x59,  2,  2, CHG_NZVC },
   { "decb", "b->b",	"dec8",	     1, 0x5a,  2,  2, CHG_NZV },
   { "incb", "b->b",	"inc8",	     1, 0x5c,  2,  2, CHG_NZV },
@@ -410,7 +454,6 @@ const struct m6811_opcode_def m6811_page
   { "ror",  "(x)->(x)", "ror8",	     2, 0x66,  6,  6, CHG_NZVC },
   { "asr",  "(x)->(x)", "asr8",	     2, 0x67,  6,  6, CHG_NZVC },
   { "asl",  "(x)->(x)", "lsl8",	     2, 0x68,  6,  6, CHG_NZVC },
-  { "lsl",  "(x)->(x)", "lsl8",	     2, 0x68,  6,  6, CHG_NZVC },
   { "rol",  "(x)->(x)", "rol8",	     2, 0x69,  6,  6, CHG_NZVC },
   { "dec",  "(x)->(x)", "dec8",	     2, 0x6a,  6,  6, CHG_NZV },
   { "inc",  "(x)->(x)", "inc8",	     2, 0x6c,  6,  6, CHG_NZV },
@@ -423,7 +466,6 @@ const struct m6811_opcode_def m6811_page
   { "ror",  "()->()",	"ror8",	     3, 0x76,  6,  6, CHG_NZVC },
   { "asr",  "()->()",	"asr8",	     3, 0x77,  6,  6, CHG_NZVC },
   { "asl",  "()->()",	"lsl8",	     3, 0x78,  6,  6, CHG_NZVC },
-  { "lsl",  "()->()",	"lsl8",	     3, 0x78,  6,  6, CHG_NZVC },
   { "rol",  "()->()",	"rol8",	     3, 0x79,  6,  6, CHG_NZVC },
   { "dec",  "()->()",	"dec8",	     3, 0x7a,  6,  6, CHG_NZV },
   { "inc",  "()->()",	"inc8",	     3, 0x7c,  6,  6, CHG_NZV },
@@ -442,8 +484,7 @@ const struct m6811_opcode_def m6811_page
   { "oraa", "#,a->a",	"or8",	     2, 0x8a,  2,  2, CLR_V_CHG_NZ },
   { "adda", "#,a->a",	"add8",	     2, 0x8b,  2,  2, CHG_HNZVC },
   { "cmpx", "#,x",	"sub16",     3, 0x8c,  4,  4, CHG_NZVC },
-  { "cpx",  "#,x",	"sub16",     3, 0x8c,  4,  4, CHG_NZVC },
-  { "bsr",  "r",	"jsr16",     2, 0x8d,  6,  6, CHG_NONE },
+  { "bsr",  "r",	"jsr_11_16", 2, 0x8d,  6,  6, CHG_NONE },
   { "lds",  "#->sp",	"movtst16",  3, 0x8e,  3,  3, CLR_V_CHG_NZ },
   { "xgdx", "x->x",	"xgdxy16",   1, 0x8f,  3,  3, CHG_NONE },
   { "suba", "*,a->a",	"sub8",	     2, 0x90,  3,  3, CHG_NZVC },
@@ -459,8 +500,7 @@ const struct m6811_opcode_def m6811_page
   { "oraa", "*,a->a",	"or8",	     2, 0x9a,  3,  3, CLR_V_CHG_NZ },
   { "adda", "*,a->a",	"add8",	     2, 0x9b,  3,  3, CHG_HNZVC },
   { "cmpx", "*,x",	"sub16",     2, 0x9c,  5,  5, CHG_NZVC },
-  { "cpx",  "*,x",	"sub16",     2, 0x9c,  5,  5, CHG_NZVC },
-  { "jsr",  "*",	"jsr16",     2, 0x9d,  5,  5, CHG_NONE },
+  { "jsr",  "*",	"jsr_11_16", 2, 0x9d,  5,  5, CHG_NONE },
   { "lds",  "*->sp",	"movtst16",  2, 0x9e,  4,  4, CLR_V_CHG_NZ },
   { "sts",  "sp->*",	"movtst16",  2, 0x9f,  4,  4, CLR_V_CHG_NZ },
   { "suba", "(x),a->a", "sub8",	     2, 0xa0,  4,  4, CHG_NZVC },
@@ -476,8 +516,7 @@ const struct m6811_opcode_def m6811_page
   { "oraa", "(x),a->a", "or8",	     2, 0xaa,  4,  4, CLR_V_CHG_NZ },
   { "adda", "(x),a->a", "add8",	     2, 0xab,  4,  4, CHG_HNZVC },
   { "cmpx", "(x),x",	"sub16",     2, 0xac,  6,  6, CHG_NZVC },
-  { "cpx",  "(x),x",	"sub16",     2, 0xac,  6,  6, CHG_NZVC },
-  { "jsr",  "&(x)",	"jsr16",     2, 0xad,  6,  6, CHG_NONE },
+  { "jsr",  "&(x)",	"jsr_11_16", 2, 0xad,  6,  6, CHG_NONE },
   { "lds",  "(x)->sp",	"movtst16",  2, 0xae,  5,  5, CLR_V_CHG_NZ },
   { "sts",  "sp->(x)",	"movtst16",  2, 0xaf,  5,  5, CLR_V_CHG_NZ },
   { "suba", "(),a->a",	"sub8",	     3, 0xb0,  4,  4, CHG_NZVC },
@@ -493,8 +532,7 @@ const struct m6811_opcode_def m6811_page
   { "oraa", "(),a->a",	"or8",	     3, 0xba,  4,  4, CLR_V_CHG_NZ },
   { "adda", "(),a->a",	"add8",	     3, 0xbb,  4,  4, CHG_HNZVC },
   { "cmpx", "(),x",	"sub16",     3, 0xbc,  5,  5, CHG_NZVC },
-  { "cpx",  "(),x",	"sub16",     3, 0xbc,  5,  5, CHG_NZVC },
-  { "jsr",  "&()",	"jsr16",     3, 0xbd,  6,  6, CHG_NONE },
+  { "jsr",  "&()",	"jsr_11_16", 3, 0xbd,  6,  6, CHG_NONE },
   { "lds",  "()->sp",	"movtst16",  3, 0xbe,  5,  5, CLR_V_CHG_NZ },
   { "sts",  "sp->()",	"movtst16",  3, 0xbf,  5,  5, CLR_V_CHG_NZ },
   { "subb", "#,b->b",	"sub8",	     2, 0xc0,  2,  2, CHG_NZVC },
@@ -571,7 +609,7 @@ const struct m6811_opcode_def m6811_page
  * Pattern   -----------+	       +--------------- Min # cycles
  * Size	     -----------------+	  +-------------------- Opcode
  */
-const struct m6811_opcode_def m6811_page2_opcodes[] = {
+struct m6811_opcode_def m6811_page2_opcodes[] = {
   { "iny",  "y->y",	"inc16",     2, 0x08, 4, 4, CHG_Z },
   { "dey",  "y->y",	"dec16",     2, 0x09, 4, 4, CHG_Z },
   { "bset", "(y),#->(y)","or8",	     4, 0x1c, 8, 8, CLR_V_CHG_NZ },
@@ -589,7 +627,6 @@ const struct m6811_opcode_def m6811_page
   { "ror",  "(y)->(y)", "ror8",	     3, 0x66, 7, 7, CHG_NZVC },
   { "asr",  "(y)->(y)", "asr8",	     3, 0x67, 7, 7, CHG_NZVC },
   { "asl",  "(y)->(y)", "lsl8",	     3, 0x68, 7, 7, CHG_NZVC },
-  { "lsl",  "(y)->(y)", "lsl8",	     3, 0x68, 7, 7, CHG_NZVC },
   { "rol",  "(y)->(y)", "rol8",	     3, 0x69, 7, 7, CHG_NZVC },
   { "dec",  "(y)->(y)", "dec8",	     3, 0x6a, 7, 7, CHG_NZV },
   { "inc",  "(y)->(y)", "inc8",	     3, 0x6c, 7, 7, CHG_NZV },
@@ -597,10 +634,8 @@ const struct m6811_opcode_def m6811_page
   { "jmp",  "&(y)",	"bra",	     3, 0x6e, 4, 4, CHG_NONE },
   { "clr",  "->(y)",	"clr8",	     3, 0x6f, 7, 7, SET_Z_CLR_NVC },
   { "cmpy", "#,y",	"sub16",     4, 0x8c, 5, 5, CHG_NZVC },
-  { "cpy",  "#,y",	"sub16",     4, 0x8c, 5, 5, CHG_NZVC },
   { "xgdy", "y->y",	"xgdxy16",   2, 0x8f, 4, 4, CHG_NONE },
   { "cmpy", "*,y",	"sub16",     3, 0x9c, 6, 6, CHG_NZVC },
-  { "cpy",  "*,y",	"sub16",     3, 0x9c, 6, 6, CHG_NZVC },
   { "suba", "(y),a->a", "sub8",	     3, 0xa0, 5, 5, CHG_NZVC },
   { "cmpa", "(y),a",	"sub8",	     3, 0xa1, 5, 5, CHG_NZVC },
   { "sbca", "(y),a->a", "sbc8",	     3, 0xa2, 5, 5, CHG_NZVC },
@@ -614,12 +649,10 @@ const struct m6811_opcode_def m6811_page
   { "oraa", "(y),a->a", "or8",	     3, 0xaa, 5, 5, CLR_V_CHG_NZ },
   { "adda", "(y),a->a", "add8",	     3, 0xab, 5, 5, CHG_HNZVC },
   { "cmpy", "(y),y",	"sub16",     3, 0xac, 7, 7, CHG_NZVC },
-  { "cpy",  "(y),y",	"sub16",     3, 0xac, 7, 7, CHG_NZVC },
-  { "jsr",  "&(y)",	"jsr16",     3, 0xad, 6, 6, CHG_NONE },
+  { "jsr",  "&(y)",	"jsr_11_16", 3, 0xad, 6, 6, CHG_NONE },
   { "lds",  "(y)->sp",	"movtst16",  3, 0xae, 6, 6, CLR_V_CHG_NZ },
   { "sts",  "sp->(y)",	"movtst16",  3, 0xaf, 6, 6, CLR_V_CHG_NZ },
   { "cmpy", "(),y",	"sub16",     4, 0xbc, 7, 7, CHG_NZVC },
-  { "cpy",  "(),y",	"sub16",     4, 0xbc, 7, 7, CHG_NZVC },
   { "ldy",  "#->y",	"movtst16",  4, 0xce, 4, 4, CLR_V_CHG_NZ },
   { "ldy",  "*->y",	"movtst16",  3, 0xde, 5, 5, CLR_V_CHG_NZ },
   { "sty",  "y->*",	"movtst16",  3, 0xdf, 5, 5, CLR_V_CHG_NZ },
@@ -651,17 +684,12 @@ const struct m6811_opcode_def m6811_page
  * Pattern   -----------+	       +--------------- Min # cycles
  * Size	     -----------------+	  +-------------------- Opcode
  */
-const struct m6811_opcode_def m6811_page3_opcodes[] = {
+struct m6811_opcode_def m6811_page3_opcodes[] = {
   { "cmpd", "#,d",	"sub16",     4, 0x83, 5, 5, CHG_NZVC },
-  { "cpd",  "#,d",	"sub16",     4, 0x83, 5, 5, CHG_NZVC },
   { "cmpd", "*,d",	"sub16",     3, 0x93, 6, 6, CHG_NZVC },
-  { "cpd",  "*,d",	"sub16",     3, 0x93, 6, 6, CHG_NZVC },
   { "cmpd", "(x),d",	"sub16",     3, 0xa3, 7, 7, CHG_NZVC },
-  { "cpd",  "(x),d",	"sub16",     3, 0xa3, 7, 7, CHG_NZVC },
   { "cmpy", "(x),y",	"sub16",     3, 0xac, 7, 7, CHG_NZVC },
-  { "cpy",  "(x),y",	"sub16",     3, 0xac, 7, 7, CHG_NZVC },
   { "cmpd", "(),d",	"sub16",     4, 0xb3, 7, 7, CHG_NZVC },
-  { "cpd",  "(),d",	"sub16",     4, 0xb3, 7, 7, CHG_NZVC },
   { "ldy",  "(x)->y",	"movtst16",  3, 0xee, 6, 6, CLR_V_CHG_NZ },
   { "sty",  "y->(x)",	"movtst16",  3, 0xef, 6, 6, CLR_V_CHG_NZ }
 };
@@ -674,17 +702,440 @@ const struct m6811_opcode_def m6811_page
  * Pattern   -----------+	       +--------------- Min # cycles
  * Size	     -----------------+	  +-------------------- Opcode
  */
-const struct m6811_opcode_def m6811_page4_opcodes[] = {
+struct m6811_opcode_def m6811_page4_opcodes[] = {
   { "syscall", "",	"syscall",   2, 0x03, 6, 6, CHG_NONE },
   { "cmpd", "(y),d",	"sub16",     3, 0xa3, 7, 7, CHG_NZVC },
-  { "cpd",  "(y),d",	"sub16",     3, 0xa3, 7, 7, CHG_NZVC },
   { "cmpx", "(y),x",	"sub16",     3, 0xac, 7, 7, CHG_NZVC },
-  { "cpx",  "(y),x",	"sub16",     3, 0xac, 7, 7, CHG_NZVC },
   { "ldx",  "(y)->x",	"movtst16",  3, 0xee, 6, 6, CLR_V_CHG_NZ },
   { "stx",  "x->(y)",	"movtst16",  3, 0xef, 6, 6, CLR_V_CHG_NZ }
 };
+
+/* 68HC12 opcodes */
+/*
+ *  { "dex", "x->x", "dec16", 1, 0x00, 5, _M,  CHG_NONE },
+ * Name -+					 +----- Insn CCR changes
+ * Operands  ---+			  +------------ Max # cycles
+ * Pattern   -----------+	       +--------------- Min # cycles
+ * Size	     -----------------+	  +-------------------- Opcode
+ */
+struct m6811_opcode_def m6812_page1_opcodes[] = {
+  { "adca", "#,a->a",    "adc8",     2, 0x89,  1,  1,  CHG_HNZVC },
+  { "adca", "*,a->a",    "adc8",     2, 0x99,  3,  3,  CHG_HNZVC },
+  { "adca", "(),a->a",   "adc8",     3, 0xb9,  3,  3,  CHG_HNZVC },
+  { "adca", "[],a->a",   "adc8",     2, 0xa9,  3,  3,  CHG_HNZVC },
+
+  { "adcb", "#,b->b",    "adc8",     2, 0xc9,  1,  1,  CHG_HNZVC },
+  { "adcb", "*,b->b",    "adc8",     3, 0xd9,  3,  3,  CHG_HNZVC },
+  { "adcb", "(),b->b",   "adc8",     3, 0xf9,  3,  3,  CHG_HNZVC },
+  { "adcb", "[],b->b",   "adc8",     2, 0xe9,  3,  3,  CHG_HNZVC },
+
+  { "adda", "#,a->a",    "add8",     2, 0x8b,  1,  1,  CHG_HNZVC },
+  { "adda", "*,a->a",    "add8",     3, 0x9b,  3,  3,  CHG_HNZVC },
+  { "adda", "(),a->a",   "add8",     3, 0xbb,  3,  3,  CHG_HNZVC },
+  { "adda", "[],a->a",   "add8",     2, 0xab,  3,  3,  CHG_HNZVC },
+
+  { "addb", "#,b->b",    "add8",     2, 0xcb,  1,  1,  CHG_HNZVC },
+  { "addb", "*,b->b",    "add8",     3, 0xdb,  3,  3,  CHG_HNZVC },
+  { "addb", "(),b->b",   "add8",     3, 0xfb,  3,  3,  CHG_HNZVC },
+  { "addb", "[],b->b",   "add8",     2, 0xeb,  3,  3,  CHG_HNZVC },
+
+  { "addd", "#,d->d",    "add16",    3, 0xc3,  2,  2,  CHG_NZVC },
+  { "addd", "*,d->d",    "add16",    2, 0xd3,  3,  3,  CHG_NZVC },
+  { "addd", "(),d->d",   "add16",    3, 0xf3,  3,  3,  CHG_NZVC },
+  { "addd", "[],d->d",   "add16",    2, 0xe3,  3,  3,  CHG_NZVC },
+
+  { "anda", "#,a->a",    "and8",     2, 0x84,  1,  1,  CLR_V_CHG_NZ },
+  { "anda", "*,a->a",    "and8",     2, 0x94,  3,  3,  CLR_V_CHG_NZ },
+  { "anda", "(),a->a",   "and8",     3, 0xb4,  3,  3,  CLR_V_CHG_NZ },
+  { "anda", "[],a->a",   "and8",     2, 0xa4,  3,  3,  CLR_V_CHG_NZ },
+
+  { "andb", "#,b->b",    "and8",     2, 0xc4,  1,  1,  CLR_V_CHG_NZ },
+  { "andb", "*,b->b",    "and8",     2, 0xd4,  3,  3,  CLR_V_CHG_NZ },
+  { "andb", "(),b->b",   "and8",     3, 0xf4,  3,  3,  CLR_V_CHG_NZ },
+  { "andb", "[],b->b",   "and8",     2, 0xe4,  3,  3,  CLR_V_CHG_NZ },
+
+  { "andcc", "#,ccr->ccr", "and8",   2, 0x10,  1,  1,  CHG_ALL },
+
+  { "asl",  "()->()",    "lsl8",     3, 0x78,  4,  4,  CHG_NZVC },
+  { "asl",  "[]->[]",    "lsl8",     2, 0x68,  3,  3,  CHG_NZVC },
+
+  { "asla", "a->a",      "lsl8",     1, 0x48,  1,  1,  CHG_NZVC },
+  { "aslb", "b->b",      "lsl8",     1, 0x58,  1,  1,  CHG_NZVC },
+  { "asld", "d->d",      "lsl16",    1, 0x59,  1,  1,  CHG_NZVC },
+
+  { "asr",  "()->()",    "asr8",     3, 0x77,  4,  4,  CHG_NZVC },
+  { "asr",  "[]->[]",    "asr8",     2, 0x67,  3,  3,  CHG_NZVC },
+
+  { "asra", "a->a",      "asr8",     1, 0x47,  1,  1,  CHG_NZVC },
+  { "asrb", "b->b",      "asr8",     1, 0x57,  1,  1,  CHG_NZVC },
+
+  { "bcc",  "r",         0,          2, 0x24,  1,  3,  CHG_NONE },
+
+  { "bclr", "*,#->*",    "bclr8",    3, 0x4d,  4,  4,  CLR_V_CHG_NZ },
+  { "bclr", "(),#->()",  "bclr8",    4, 0x1d,  4,  4,  CLR_V_CHG_NZ },
+  { "bclr", "[],#->[]",  "bclr8",    3, 0x0d,  4,  4,  CLR_V_CHG_NZ },
+
+  { "bcs",  "r",         0,          2, 0x25,  1,  3, CHG_NONE },
+  { "beq",  "r",         0,          2, 0x27,  1,  3, CHG_NONE },
+  { "bge",  "r",         0,          2, 0x2c,  1,  3, CHG_NONE },
+
+  { "bgnd",  0,          0,          1, 0x00,  5,  5, CHG_NONE },
+
+  { "bgt",  "r",         0,          2, 0x2e,  1,  3, CHG_NONE },
+  { "bhi",  "r",         0,          2, 0x22,  1,  3, CHG_NONE },
+  
+  { "bita", "#,a",       "and8",     2, 0x85,  1,  1, CLR_V_CHG_NZ },
+  { "bita", "*,a",       "and8",     2, 0x95,  3,  3, CLR_V_CHG_NZ },
+  { "bita", "(),a",      "and8",     3, 0xb5,  3,  3, CLR_V_CHG_NZ },
+  { "bita", "[],a",      "and8",     2, 0xa5,  3,  3,  CLR_V_CHG_NZ },
+
+  { "bitb", "#,b",       "and8",     2, 0xc5,  1,  1, CLR_V_CHG_NZ },
+  { "bitb", "*,b",       "and8",     2, 0xd5,  3,  3, CLR_V_CHG_NZ },
+  { "bitb", "(),b",      "and8",     3, 0xf5,  3,  3, CLR_V_CHG_NZ },
+  { "bitb", "[],b",      "and8",     2, 0xe5,  3,  3,  CLR_V_CHG_NZ },
+
+  { "ble",  "r",          0,         2, 0x2f,  1,  3, CHG_NONE },
+  { "bls",  "r",          0,         2, 0x23,  1,  3, CHG_NONE },
+  { "blt",  "r",          0,         2, 0x2d,  1,  3, CHG_NONE },
+  { "bmi",  "r",          0,         2, 0x2b,  1,  3, CHG_NONE },
+  { "bne",  "r",          0,         2, 0x26,  1,  3, CHG_NONE },
+  { "bpl",  "r",          0,         2, 0x2a,  1,  3, CHG_NONE },
+  { "bra",  "r",          0,         2, 0x20,  1,  3, CHG_NONE },
+
+  { "brclr", "*,#,r",     "brclr8",  4, 0x4f,  4,  4,  CHG_NONE },
+  { "brclr", "(),#,r",    "brclr8",  5, 0x1f,  5,  5,  CHG_NONE },
+  { "brclr", "[],#,r",    "brclr8",  4, 0x0f,  4,  4,  CHG_NONE },
+
+  { "brn",  "r",          "nop",     2, 0x21,  1,  3,  CHG_NONE },
+
+  { "brset", "*,#,r",     "brset8",  4, 0x4e,  4,  4,  CHG_NONE },
+  { "brset", "(),#,r",    "brset8",  5, 0x1e,  5,  5,  CHG_NONE },
+  { "brset", "[],#,r",    "brset8",  4, 0x0e,  4,  4,  CHG_NONE },
+
+  { "bset",  "*,#->*",    "or8",     3, 0x4c,  4,  4,  CLR_V_CHG_NZ },
+  { "bset",  "(),#->()",  "or8",     4, 0x1c,  4,  4,  CLR_V_CHG_NZ },
+  { "bset",  "[],#->[]",  "or8",     3, 0x0c,  4,  4,  CLR_V_CHG_NZ },
+
+  { "bsr",   "r",         "jsr_12_16", 2, 0x07,  4,  4, CHG_NONE },
+
+  { "bvc",   "r",         0,         2, 0x28,  1,  3, CHG_NONE },
+  { "bvs",   "r",         0,         2, 0x29,  1,  3, CHG_NONE },
+
+  { "call",  "()",        "call8",   4, 0x4a,  8,  8,  CHG_NONE },
+  { "call",  "[]",        "call8",   2, 0x4b,  8,  8,  CHG_NONE },
+
+  { "clr",   "->()",      "clr8",    3, 0x79,  3,  3,  SET_Z_CLR_NVC },
+  { "clr",   "->[]",      "clr8",    2, 0x69,  2,  2,  SET_Z_CLR_NVC },
+
+  { "clra",  "->a",       "clr8",    1, 0x87,  1,  1,  SET_Z_CLR_NVC },
+  { "clrb",  "->b",       "clr8",    1, 0xc7,  1,  1,  SET_Z_CLR_NVC },
+
+  { "cpa",  "#,a",        "sub8",    2, 0x81,  1,  1,  CHG_NZVC },
+  { "cpa",  "*,a",        "sub8",    2, 0x91,  3,  3,  CHG_NZVC },
+  { "cpa",  "(),a",       "sub8",    3, 0xb1,  3,  3,  CHG_NZVC },
+  { "cpa",  "[],a",       "sub8",    2, 0xa1,  3,  3,  CHG_NZVC },
+
+  { "cpb",  "#,b",        "sub8",    2, 0xc1,  1,  1,  CHG_NZVC },
+  { "cpb",  "*,b",        "sub8",    2, 0xd1,  3,  3,  CHG_NZVC },
+  { "cpb",  "(),b",       "sub8",    3, 0xf1,  3,  3,  CHG_NZVC },
+  { "cpb",  "[],b",       "sub8",    2, 0xe1,  3,  3,  CHG_NZVC },
+
+  { "com",   "()->()",    "com8",    3, 0x71,  4,  4,  SET_C_CLR_V_CHG_NZ },
+  { "com",   "[]->[]",    "com8",    2, 0x61,  3,  3,  SET_C_CLR_V_CHG_NZ },
+
+  { "coma",  "a->a",      "com8",    1, 0x41,  1,  1,  SET_C_CLR_V_CHG_NZ },
+  { "comb",  "b->b",      "com8",    1, 0x51,  1,  1,  SET_C_CLR_V_CHG_NZ },
+
+  { "cpd",   "#,d",       "sub16",   3, 0x8c,  2,  2,  CHG_NZVC },
+  { "cpd",   "*,d",       "sub16",   2, 0x9c,  3,  3,  CHG_NZVC },
+  { "cpd",   "(),d",      "sub16",   3, 0xbc,  3,  3,  CHG_NZVC },
+  { "cpd",   "[],d",      "sub16",   2, 0xac,  3,  3,  CHG_NZVC },
+
+  { "cps",   "#,sp",      "sub16",   3, 0x8f,  2,  2,  CHG_NZVC },
+  { "cps",   "*,sp",      "sub16",   2, 0x9f,  3,  3,  CHG_NZVC },
+  { "cps",   "(),sp",     "sub16",   3, 0xbf,  3,  3,  CHG_NZVC },
+  { "cps",   "[],sp",     "sub16",   2, 0xaf,  3,  3,  CHG_NZVC },
+
+  { "cpx",   "#,x",       "sub16",   3, 0x8e,  2,  2,  CHG_NZVC },
+  { "cpx",   "*,x",       "sub16",   2, 0x9e,  3,  3,  CHG_NZVC },
+  { "cpx",   "(),x",      "sub16",   3, 0xbe,  3,  3,  CHG_NZVC },
+  { "cpx",   "[],x",      "sub16",   2, 0xae,  3,  3,  CHG_NZVC },
+
+  { "cpy",   "#,y",       "sub16",   3, 0x8d,  2,  2,  CHG_NZVC },
+  { "cpy",   "*,y",       "sub16",   2, 0x9d,  3,  3,  CHG_NZVC },
+  { "cpy",   "(),y",      "sub16",   3, 0xbd,  3,  3,  CHG_NZVC },
+  { "cpy",   "[],y",      "sub16",   2, 0xad,  3,  3,  CHG_NZVC },
+
+  /* dbeq, dbne, ibeq, ibne, tbeq, tbne */
+  { "dbeq",   0,          "dbcc8",   3, 0x04,  3,  3, CHG_NONE },
+
+  { "dec",   "()->()",    "dec8",    3, 0x73,  4,  4,  CHG_NZV },
+  { "dec",   "[]->[]",    "dec8",    2, 0x63,  3,  3,  CHG_NZV },
+
+  { "deca",  "a->a",      "dec8",    1, 0x43,  1,  1,  CHG_NZV },
+  { "decb",  "b->b",      "dec8",    1, 0x53,  1,  1,  CHG_NZV },
+
+  { "dex",   "x->x",      "dec16",   1, 0x09,  1,  1,  CHG_Z },
+  { "dey",   "y->y",      "dec16",   1, 0x03,  1,  1,  CHG_Z },
+
+  { "ediv",  0,           0,         1, 0x11,  11,  11,  CHG_NZVC },
+  { "emul",  0,           0,         1, 0x13,  3,  3,  CHG_NZC },
+
+  { "eora",  "#,a->a",    "eor8",    2, 0x88,  1,  1,  CLR_V_CHG_NZ },
+  { "eora",  "*,a->a",    "eor8",    2, 0x98,  3,  3,  CLR_V_CHG_NZ },
+  { "eora",  "(),a->a",   "eor8",    3, 0xb8,  3,  3,  CLR_V_CHG_NZ },
+  { "eora",  "[],a->a",   "eor8",    2, 0xa8,  3,  3,  CLR_V_CHG_NZ },
+
+  { "eorb",  "#,b->b",    "eor8",    2, 0xc8,  1,  1,  CLR_V_CHG_NZ },
+  { "eorb",  "*,b->b",    "eor8",    2, 0xd8,  3,  3,  CLR_V_CHG_NZ },
+  { "eorb",  "(),b->b",   "eor8",    3, 0xf8,  3,  3,  CLR_V_CHG_NZ },
+  { "eorb",  "[],b->b",   "eor8",    2, 0xe8,  3,  3,  CLR_V_CHG_NZ },
+
+  /* exg, sex, tfr */
+  { "exg",   "#",         "exg8",    2, 0xb7,  1,  1,  CHG_NONE },
+
+  { "inc",   "()->()",    "inc8",    3, 0x72,  4,  4,  CHG_NZV },
+  { "inc",   "[]->[]",    "inc8",    2, 0x62,  3,  3,  CHG_NZV },
+
+  { "inca",  "a->a",      "inc8",    1, 0x42,  1,  1,  CHG_NZV },
+  { "incb",  "b->b",      "inc8",    1, 0x52,  1,  1,  CHG_NZV },
+
+  { "inx",   "x->x",      "inc16",   1, 0x08,  1,  1,  CHG_Z },
+  { "iny",   "y->y",      "inc16",   1, 0x02,  1,  1,  CHG_Z },
+
+  { "jmp",   "&()",       "bra",     3, 0x06,  3,  3,  CHG_NONE },
+  { "jmp",   "&[]",       "bra",     2, 0x05,  3,  3,  CHG_NONE },
+
+  { "jsr",   "*",         "jsr_12_16",   2, 0x17,  4,  4,  CHG_NONE },
+  { "jsr",   "&()",       "jsr_12_16",   3, 0x16,  4,  4,  CHG_NONE },
+  { "jsr",   "&[]",       "jsr_12_16",   2, 0x15,  4,  4,  CHG_NONE },
+
+  { "ldaa", "#->a",       "movtst8", 2, 0x86,  1,  1,  CLR_V_CHG_NZ },
+  { "ldaa", "*->a",       "movtst8", 2, 0x96,  3,  3,  CLR_V_CHG_NZ },
+  { "ldaa", "()->a",      "movtst8", 3, 0xb6,  3,  3,  CLR_V_CHG_NZ },
+  { "ldaa", "[]->a",      "movtst8", 2, 0xa6,  3,  3,  CLR_V_CHG_NZ },
+
+  { "ldab", "#->b",       "movtst8", 2, 0xc6,  1,  1,  CLR_V_CHG_NZ },
+  { "ldab", "*->b",       "movtst8", 2, 0xd6,  3,  3,  CLR_V_CHG_NZ },
+  { "ldab", "()->b",      "movtst8", 3, 0xf6,  3,  3,  CLR_V_CHG_NZ },
+  { "ldab", "[]->b",      "movtst8", 2, 0xe6,  3,  3,  CLR_V_CHG_NZ },
+
+  { "ldd",  "#->d",       "movtst16", 3, 0xcc,  2,  2,  CLR_V_CHG_NZ },
+  { "ldd",  "*->d",       "movtst16", 2, 0xdc,  3,  3,  CLR_V_CHG_NZ },
+  { "ldd",  "()->d",      "movtst16", 3, 0xfc,  3,  3,  CLR_V_CHG_NZ },
+  { "ldd",  "[]->d",      "movtst16", 2, 0xec,  3,  3,  CLR_V_CHG_NZ },
+
+  { "lds",  "#->sp",      "movtst16", 3, 0xcf,  2,  2,  CLR_V_CHG_NZ },
+  { "lds",  "*->sp",      "movtst16", 2, 0xdf,  3,  3,  CLR_V_CHG_NZ },
+  { "lds",  "()->sp",     "movtst16", 3, 0xff,  3,  3,  CLR_V_CHG_NZ },
+  { "lds",  "[]->sp",     "movtst16", 2, 0xef,  3,  3,  CLR_V_CHG_NZ },
+
+  { "ldx",  "#->x",       "movtst16", 3, 0xce,  2,  2,  CLR_V_CHG_NZ },
+  { "ldx",  "*->x",       "movtst16", 2, 0xde,  3,  3,  CLR_V_CHG_NZ },
+  { "ldx",  "()->x",      "movtst16", 3, 0xfe,  3,  3,  CLR_V_CHG_NZ },
+  { "ldx",  "[]->x",      "movtst16", 2, 0xee,  3,  3,  CLR_V_CHG_NZ },
+
+  { "ldy",  "#->y",       "movtst16", 3, 0xcd,  2,  2,  CLR_V_CHG_NZ },
+  { "ldy",  "*->y",       "movtst16", 2, 0xdd,  3,  3,  CLR_V_CHG_NZ },
+  { "ldy",  "()->y",      "movtst16", 3, 0xfd,  3,  3,  CLR_V_CHG_NZ },
+  { "ldy",  "[]->y",      "movtst16", 2, 0xed,  3,  3,  CLR_V_CHG_NZ },
+
+  { "leas", "&[]->sp",    "lea16",   2, 0x1b,  2,  2,  CHG_NONE },
+  { "leax", "&[]->x",     "lea16",   2, 0x1a,  2,  2,  CHG_NONE },
+  { "leay", "&[]->y",     "lea16",   2, 0x19,  2,  2,  CHG_NONE },
+
+  { "lsr",  "()->()",     "lsr8",    3, 0x74,  4,  4,  CLR_N_CHG_ZVC },
+  { "lsr",  "[]->[]",     "lsr8",    2, 0x64,  3,  3,  CLR_N_CHG_ZVC },
+
+  { "lsra", "a->a",       "lsr8",    1, 0x44,  1,  1,  CLR_N_CHG_ZVC },
+  { "lsrb", "b->b",       "lsr8",    1, 0x54,  1,  1,  CLR_N_CHG_ZVC },
+  { "lsrd", "d->d",       "lsr16",   1, 0x49,  1,  1,  CLR_N_CHG_ZVC },
+
+  { "mem",  0,            0,         1, 0x01,  5,  5,  CHG_HNZVC },
 
-void fatal_error (const struct m6811_opcode_def*, const char*);
+  { "mul",  "b,a->d",     "mul16",   1, 0x12,  3,  3,  CHG_C },
+
+  { "neg",  "()->()",     "neg8",    3, 0x70,  4,  4,  CHG_NZVC },
+  { "neg",  "[]->[]",     "neg8",    2, 0x60,  3,  3,  CHG_NZVC },
+
+  { "nega", "a->a",       "neg8",    1, 0x40,  1,  1,  CHG_NZVC },
+  { "negb", "b->b",       "neg8",    1, 0x50,  1,  1,  CHG_NZVC },
+
+  { "nop",  "",           "nop",     1, 0xa7,  1,  1,  CHG_NONE },
+
+  { "oraa", "#,a->a",     "or8",     2, 0x8a,  1,  1,  CLR_V_CHG_NZ },
+  { "oraa", "*,a->a",     "or8",     2, 0x9a,  3,  3,  CLR_V_CHG_NZ },
+  { "oraa", "(),a->a",    "or8",     3, 0xba,  3,  3,  CLR_V_CHG_NZ },
+  { "oraa", "[],a->a",    "or8",     2, 0xaa,  3,  3,  CLR_V_CHG_NZ },
+
+  { "orab", "#,b->b",     "or8",     2, 0xca,  1,  1,  CLR_V_CHG_NZ },
+  { "orab", "*,b->b",     "or8",     2, 0xda,  3,  3,  CLR_V_CHG_NZ },
+  { "orab", "(),b->b",    "or8",     3, 0xfa,  3,  3,  CLR_V_CHG_NZ },
+  { "orab", "[],b->b",    "or8",     2, 0xea,  3,  3,  CLR_V_CHG_NZ },
+
+  { "orcc", "#,ccr->ccr", "or8",     2, 0x14,  1,  1,  CHG_ALL },
+
+  { "page2", 0,		  "page2",   1, 0x18,  0,  0,  CHG_NONE },
+
+  { "psha", "a->(sp)",    "mov8",    1, 0x36,  2,  2,  CHG_NONE },
+  { "pshb", "b->(sp)",    "mov8",    1, 0x37,  2,  2,  CHG_NONE },
+  { "pshc", "ccr->(sp)",  "mov8",    1, 0x39,  2,  2,  CHG_NONE },
+  { "pshd", "d->(sp)",    "mov16",   1, 0x3b,  2,  2,  CHG_NONE },
+  { "pshx", "x->(sp)",    "mov16",   1, 0x34,  2,  2,  CHG_NONE },
+  { "pshy", "y->(sp)",    "mov16",   1, 0x35,  2,  2,  CHG_NONE },
+
+  { "pula", "(sp)->a",    "mov8",    1, 0x32,  3,  3,  CHG_NONE },
+  { "pulb", "(sp)->b",    "mov8",    1, 0x33,  3,  3,  CHG_NONE },
+  { "pulc", "(sp)->ccr",  "mov8",    1, 0x38,  3,  3,  CHG_ALL },
+  { "puld", "(sp)->d",    "mov16",   1, 0x3a,  3,  3,  CHG_NONE },
+  { "pulx", "(sp)->x",    "mov16",   1, 0x30,  3,  3,  CHG_NONE },
+  { "puly", "(sp)->y",    "mov16",   1, 0x31,  3,  3,  CHG_NONE },
+
+  { "rol",  "()->()",     "rol8",    3, 0x75,  4,  4,  CHG_NZVC },
+  { "rol",  "[]->[]",     "rol8",    2, 0x65,  3,  3,  CHG_NZVC },
+
+  { "rola", "a->a",       "rol8",    1, 0x45,  1,  1,  CHG_NZVC },
+  { "rolb", "b->b",       "rol8",    1, 0x55,  1,  1,  CHG_NZVC },
+
+  { "ror",  "()->()",     "ror8",    3, 0x76,  4,  4,  CHG_NZVC },
+  { "ror",  "[]->[]",     "ror8",    2, 0x66,  3,  3,  CHG_NZVC },
+
+  { "rora", "a->a",       "ror8",    1, 0x46,  1,  1,  CHG_NZVC },
+  { "rorb", "b->b",       "ror8",    1, 0x56,  1,  1,  CHG_NZVC },
+
+  { "rtc",  0,            0,         1, 0x0a,  6,  6,  CHG_NONE },
+  { "rti",  0,            "rti12",   1, 0x0b,  8, 10,  CHG_ALL},
+  { "rts",  0,            "rts12",   1, 0x3d,  5,  5,  CHG_NONE },
+
+  { "sbca", "#,a->a",     "sbc8",    2, 0x82,  1,  1,  CHG_NZVC },
+  { "sbca", "*,a->a",     "sbc8",    2, 0x92,  3,  3,  CHG_NZVC },
+  { "sbca", "(),a->a",    "sbc8",    3, 0xb2,  3,  3,  CHG_NZVC },
+  { "sbca", "[],a->a",    "sbc8",    2, 0xa2,  3,  3,  CHG_NZVC },
+
+  { "sbcb", "#,b->b",     "sbc8",    2, 0xc2,  1,  1,  CHG_NZVC },
+  { "sbcb", "*,b->b",     "sbc8",    2, 0xd2,  3,  3,  CHG_NZVC },
+  { "sbcb", "(),b->b",    "sbc8",    3, 0xf2,  3,  3,  CHG_NZVC },
+  { "sbcb", "[],b->b",    "sbc8",    2, 0xe2,  3,  3,  CHG_NZVC },
+
+  { "staa", "a->*",       "movtst8", 2, 0x5a,  2,  2,  CLR_V_CHG_NZ },
+  { "staa", "a->()",      "movtst8", 3, 0x7a,  3,  3,  CLR_V_CHG_NZ },
+  { "staa", "a->[]",      "movtst8", 2, 0x6a,  2,  2,  CLR_V_CHG_NZ },
+
+  { "stab", "b->*",       "movtst8", 2, 0x5b,  2,  2,  CLR_V_CHG_NZ },
+  { "stab", "b->()",      "movtst8", 3, 0x7b,  3,  3,  CLR_V_CHG_NZ },
+  { "stab", "b->[]",      "movtst8", 2, 0x6b,  2,  2,  CLR_V_CHG_NZ },
+
+  { "std",  "d->*",       "movtst16", 2, 0x5c,  2,  2,  CLR_V_CHG_NZ },
+  { "std",  "d->()",      "movtst16", 3, 0x7c,  3,  3,  CLR_V_CHG_NZ },
+  { "std",  "d->[]",      "movtst16", 2, 0x6c,  2,  2,  CLR_V_CHG_NZ },
+
+  { "sts",  "sp->*",      "movtst16", 2, 0x5f,  2,  2,  CLR_V_CHG_NZ },
+  { "sts",  "sp->()",     "movtst16", 3, 0x7f,  3,  3,  CLR_V_CHG_NZ },
+  { "sts",  "sp->[]",     "movtst16", 2, 0x6f,  2,  2,  CLR_V_CHG_NZ },
+
+  { "stx",  "x->*",       "movtst16", 2, 0x5e,  2,  2,  CLR_V_CHG_NZ },
+  { "stx",  "x->()",      "movtst16", 3, 0x7e,  3,  3,  CLR_V_CHG_NZ },
+  { "stx",  "x->[]",      "movtst16", 2, 0x6e,  2,  2,  CLR_V_CHG_NZ },
+
+  { "sty",  "y->*",       "movtst16", 2, 0x5d,  2,  2,  CLR_V_CHG_NZ },
+  { "sty",  "y->()",      "movtst16", 3, 0x7d,  3,  3,  CLR_V_CHG_NZ },
+  { "sty",  "y->[]",      "movtst16", 2, 0x6d,  2,  2,  CLR_V_CHG_NZ },
+
+  { "suba", "#,a->a",     "sub8",     2, 0x80,  1,  1,  CHG_NZVC },
+  { "suba", "*,a->a",     "sub8",     2, 0x90,  3,  3,  CHG_NZVC },
+  { "suba", "(),a->a",    "sub8",     3, 0xb0,  3,  3,  CHG_NZVC },
+  { "suba", "[],a->a",    "sub8",     2, 0xa0,  3,  3,  CHG_NZVC },
+
+  { "subb", "#,b->b",     "sub8",     2, 0xc0,  1,  1,  CHG_NZVC },
+  { "subb", "*,b->b",     "sub8",     2, 0xd0,  3,  3,  CHG_NZVC },
+  { "subb", "(),b->b",    "sub8",     3, 0xf0,  3,  3,  CHG_NZVC },
+  { "subb", "[],b->b",    "sub8",     2, 0xe0,  3,  3,  CHG_NZVC },
+
+  { "subd", "#,d->d",     "sub16",    3, 0x83,  2,  2,  CHG_NZVC },
+  { "subd", "*,d->d",     "sub16",    2, 0x93,  3,  3,  CHG_NZVC },
+  { "subd", "(),d->d",    "sub16",    3, 0xb3,  3,  3,  CHG_NZVC },
+  { "subd", "[],d->d",    "sub16",    2, 0xa3,  3,  3,  CHG_NZVC },
+
+  { "swi",  0,            0,          1, 0x3f,  9,  9,  CHG_NONE },
+
+  { "tst",  "()",         "tst8",     3, 0xf7,  3,  3,  CLR_VC_CHG_NZ },
+  { "tst",  "[]",         "tst8",     2, 0xe7,  3,  3,  CLR_VC_CHG_NZ },
+
+  { "tsta", "a",          "tst8",     1, 0x97,  1,  1,  CLR_VC_CHG_NZ },
+  { "tstb", "b",          "tst8",     1, 0xd7,  1,  1,  CLR_VC_CHG_NZ },
+
+  { "wai",  0,            0,          1, 0x3e,  8,  _M, CHG_NONE }
+};
+
+struct m6811_opcode_def m6812_page2_opcodes[] = {
+  { "cba",  "b,a",        "sub8",     2, 0x17,  2,  2,  CHG_NZVC },
+
+  /* After 'daa', the Z flag is undefined. Mark it as changed.  */
+  { "daa",  0,            "daa8",     2, 0x07,  3,  3,  CHG_NZVC },
+
+  { "edivs", 0,           0,          2, 0x14,  12,  12,  CHG_NZVC },
+  { "emacs", 0,           0,          2, 0x12,  13,  13,  CHG_NZVC },
+
+  { "emaxd", "[],d->d",   "max16",    3, 0x1a,  4,  4,  CHG_NZVC },
+  { "emaxm", "[],d->[]",  "max16",    3, 0x1e,  4,  4,  CHG_NZVC },
+  { "emind", "[],d->d",   "min16",    3, 0x1b,  4,  4,  CHG_NZVC },
+  { "eminm", "[],d->[]",  "min16",    3, 0x1f,  4,  4,  CHG_NZVC },
+
+  { "emuls", 0,           0,          2, 0x13,  3,  3,  CHG_NZC },
+  { "etbl",  "[]",        "tbl16",    3, 0x3f, 10, 10,  CHG_NZC },
+  { "fdiv",  "x,d->x",    "fdiv16",   2, 0x11, 12, 12,  CHG_ZVC },
+  { "idiv",  "x,d->x",    "idiv16",   2, 0x10, 12, 12,  CLR_V_CHG_ZC },
+  { "idivs", 0,           0,          2, 0x15, 12, 12,  CHG_NZVC },
+
+  { "lbcc",  "R",         "bcc",      4, 0x24,  3,  4,  CHG_NONE },
+  { "lbcs",  "R",         "bcs",      4, 0x25,  3,  4,  CHG_NONE },
+  { "lbeq",  "R",         "beq",      4, 0x27,  3,  4,  CHG_NONE },
+  { "lbge",  "R",         "bge",      4, 0x2c,  3,  4,  CHG_NONE },
+  { "lbgt",  "R",         "bgt",      4, 0x2e,  3,  4,  CHG_NONE },
+  { "lbhi",  "R",         "bhi",      4, 0x22,  3,  4,  CHG_NONE },
+  { "lble",  "R",         "ble",      4, 0x2f,  3,  4,  CHG_NONE },
+  { "lbls",  "R",         "bls",      4, 0x23,  3,  4,  CHG_NONE },
+  { "lblt",  "R",         "blt",      4, 0x2d,  3,  4,  CHG_NONE },
+  { "lbmi",  "R",         "bmi",      4, 0x2b,  3,  4,  CHG_NONE },
+  { "lbne",  "R",         "bne",      4, 0x26,  3,  4,  CHG_NONE },
+  { "lbpl",  "R",         "bpl",      4, 0x2a,  3,  4,  CHG_NONE },
+  { "lbra",  "R",         "bra",      4, 0x20,  4,  4,  CHG_NONE },
+  { "lbrn",  "R",         "nop",      4, 0x21,  3,  3,  CHG_NONE },
+  { "lbvc",  "R",         "bvc",      4, 0x28,  3,  4,  CHG_NONE },
+  { "lbvs",  "R",         "bvs",      4, 0x29,  3,  4,  CHG_NONE },
+
+  { "maxa",  "[],a->a",   "max8",     3, 0x18,  4,  4,  CHG_NZVC },
+  { "maxm",  "[],a->[]",  "max8",     3, 0x1c,  4,  4,  CHG_NZVC },
+  { "mina",  "[],a->a",   "min8",     3, 0x19,  4,  4,  CHG_NZVC },
+  { "minm",  "[],a->[]",  "min8",     3, 0x1d,  4,  4,  CHG_NZVC },
+
+  { "movb",  0,           "move8",    5, 0x0b,  4,  4,  CHG_NONE },
+  { "movb",  0,           "move8",    4, 0x08,  4,  4,  CHG_NONE },
+  { "movb",  0,           "move8",    6, 0x0c,  6,  6,  CHG_NONE },
+  { "movb",  0,           "move8",    5, 0x09,  5,  5,  CHG_NONE },
+  { "movb",  0,           "move8",    5, 0x0d,  5,  5,  CHG_NONE },
+  { "movb",  0,           "move8",    4, 0x0a,  5,  5,  CHG_NONE },
+
+  { "movw",  0,           "move16",   6, 0x03,  5,  5,  CHG_NONE },
+  { "movw",  0,           "move16",   5, 0x00,  4,  4,  CHG_NONE },
+  { "movw",  0,           "move16",   6, 0x04,  6,  6,  CHG_NONE },
+  { "movw",  0,           "move16",   5, 0x01,  5,  5,  CHG_NONE },
+  { "movw",  0,           "move16",   5, 0x05,  5,  5,  CHG_NONE },
+  { "movw",  0,           "move16",   4, 0x02,  5,  5,  CHG_NONE },
+
+  { "rev",  0,            0,          2, 0x3a,  _M, _M, CHG_HNZVC },
+  { "revw", 0,            0,          2, 0x3b,  _M, _M, CHG_HNZVC },
+  { "sba",  "b,a->a",     "sub8",     2, 0x16,  2,  2,  CHG_NZVC },
+
+  { "stop", 0,            0,          2, 0x3e,  2,  9,  CHG_NONE },
+
+  { "tab",  "a->b",       "movtst8",  2, 0x0e,  2,  2,  CLR_V_CHG_NZ },
+  { "tba",  "b->a",       "movtst8",  2, 0x0f,  2,  2,  CLR_V_CHG_NZ },
+
+  { "wav",  0,            0,          2, 0x3c,  8,  _M, SET_Z_CHG_HNVC }
+};
+
+void fatal_error (const struct m6811_opcode_def*, const char*, ...);
 void print (FILE*, int, const char*,...);
 int gen_fetch_operands (FILE*, int, const struct m6811_opcode_def*,
 			const char*);
@@ -705,13 +1156,21 @@ static int current_insn_size = 0;
 /* Fatal error message and exit.  This method is called when an inconsistency
    is detected in the generation table.	 */
 void
-fatal_error (const struct m6811_opcode_def *opcode, const char *msg)
+fatal_error (const struct m6811_opcode_def *opcode, const char *msg, ...)
 {
-  fprintf (stderr, "Fatal error: %s\n", msg);
+  va_list argp;
+
+  fprintf (stderr, "Fatal error: ");
+  va_start (argp, msg);
+  vfprintf (stderr,  msg, argp);
+  va_end (argp);
+  fprintf (stderr, "\n");
   if (opcode)
     {
       fprintf (stderr, "Opcode: 0x%02x %s %s\n",
-	       opcode->insn_code, opcode->name, opcode->operands);
+	       opcode->insn_code,
+	       opcode->name ? opcode->name : "(null)",
+	       opcode->operands ? opcode->operands : "(null)");
     }
   exit (1);
 }
@@ -794,6 +1253,7 @@ print (FILE *fp, int col, const char *ms
    x	"    X "
    y	"    Y "
    sp	"    SP "
+   pc   "    PC "
    *	68HC11 page0 memory pointer.
 	Get 8-bits page0 offset from program, set up 'addr' local
 	variable to refer to the location in page0.
@@ -805,6 +1265,7 @@ print (FILE *fp, int col, const char *ms
    ()	68HC11 extended address mode (global variable).
 	Get 16-bits address from program and set 'addr'.
 	Copy the 8/16-bits value pointed to by 'addr' in a 8/16-bits variable.
+   []   68HC12 indexed addressing mode
    (sp) Pop
 	Pop a 8/16-bits value from stack and set in a 8/16-bits variable.
    r	Relative branch
@@ -815,6 +1276,7 @@ print (FILE *fp, int col, const char *ms
    &(y)
    &()	Similar to (x), (y) and () except that we don't read the
 	value pointed to by 'addr' (ie, only 'addr' is setup). Used by jmp/jsr.
+   &[]  Similar to [] but don't read the value pointed to by the address.
    ,	Operand separator.
    -	End of input operands.
   
@@ -920,6 +1382,12 @@ gen_fetch_operands (FILE *fp, int col,
 	      print (fp, col, "addr = cpu_fetch16 (proc);");
 	      operands += 2;
 	    }
+	  else if (strncmp (operands, "[]", 2) == 0)
+	    {
+	      current_insn_size += 1;
+	      print (fp, col, "addr = cpu_get_indexed_operand_addr (proc, 0);");
+	      operands += 2;
+	    }
 	  else
 	    {
 	      fatal_error (opcode, "Unknown operand");
@@ -960,10 +1428,20 @@ gen_fetch_operands (FILE *fp, int col,
 		     vars[cur_var], operand_size, operand_size);
 	      operands++;
 	    }
-	  else if (strncmp (operands, "sp)", 3) == 0)
+	  else if (strncmp (operands, "@)", 2) == 0)
 	    {
-	      print (fp, col, "%s%s = cpu_pop_uint%s (proc);",
+	      current_insn_size += 2;
+	      print (fp, col, "addr = cpu_fetch16 (proc);");
+	      print (fp, col, "%s%s = memory_read%s (proc, addr);",
 		     vars[cur_var], operand_size, operand_size);
+	      operands += 2;
+	    }
+	  else if (strncmp (operands, "sp)", 3) == 0)
+	    {
+	      print (fp, col, "%s%s = cpu_%s_pop_uint%s (proc);",
+		     vars[cur_var], operand_size,
+                     cpu_type == cpu6811 ? "m68hc11" : "m68hc12",
+                     operand_size);
 	      operands += 3;
 	    }
 	  else
@@ -972,6 +1450,55 @@ gen_fetch_operands (FILE *fp, int col,
 	    }
 	  break;
 
+	case '[':
+	  if (cur_var >= 2)
+	    fatal_error (opcode, "Too many locals");
+	  
+	  if (addr_set)
+	    fatal_error (opcode, "Wrong use of '[', 'addr' already used");
+	  
+	  if (strncmp (operands, "]", 1) == 0)
+	    {
+	      addr_set = 1;
+	      current_insn_size += 1;
+	      print (fp, col, "addr = cpu_get_indexed_operand_addr (proc,0);");
+	      print (fp, col, "%s%s = memory_read%s (proc, addr);",
+		     vars[cur_var], operand_size, operand_size);
+	      operands += 1;
+	    }
+	  else if (strncmp (operands, "]", 1) == 0)
+	    {
+	      current_insn_size += 1;
+	      print (fp, col, "%s%s = cpu_get_indexed_operand%s (proc,0);",
+		     vars[cur_var], operand_size, operand_size);
+	      operands += 1;
+	    }
+	  else
+	    {
+	      fatal_error (opcode, "Unknown operand");
+	    }
+	  break;
+
+	case '{':
+	  if (cur_var >= 2)
+	    fatal_error (opcode, "Too many locals");
+	  
+	  if (addr_set)
+	    fatal_error (opcode, "Wrong use of '{', 'addr' already used");
+	  
+	  if (strncmp (operands, "}", 1) == 0)
+	    {
+	      current_insn_size += 1;
+	      print (fp, col, "%s%s = cpu_get_indexed_operand%s (proc, 1);",
+		     vars[cur_var], operand_size, operand_size);
+	      operands += 1;
+	    }
+	  else
+	    {
+	      fatal_error (opcode, "Unknown operand");
+	    }
+	  break;
+
 	case 's':
 	  if (cur_var >= 2)
 	    fatal_error (opcode, "Too many locals");
@@ -1008,6 +1535,15 @@ gen_fetch_operands (FILE *fp, int col,
 	  print (fp, col, "addr = cpu_fetch_relbranch (proc);");
 	  break;
 
+	case 'R':
+	  if (addr_set && cur_var != 2)
+	    fatal_error (opcode, "Wrong use of 'R'");
+
+	  addr_set = 1;
+	  current_insn_size += 2;
+	  print (fp, col, "addr = cpu_fetch_relbranch16 (proc);");
+	  break;
+
 	case '#':
 	  if (strcmp (operand_size, "8") == 0)
 	    {
@@ -1063,6 +1599,7 @@ gen_fetch_operands (FILE *fp, int col,
 	the result must be saved.
 	If they were not used an input operand, 'addr' is computed
 	(as in gen_fetch_operands()), and the result is saved.
+   []   68HC12 indexed indirect
    (sp) Push
 	Push the 8/16-bits result on the stack.	 */
 void
@@ -1171,7 +1708,8 @@ gen_save_result (FILE *fp, int col,
 	}
       else if (strncmp (operands, "sp)", 3) == 0)
 	{
-	  print (fp, col, "cpu_push_uint%s (proc, dst%s);",
+	  print (fp, col, "cpu_%s_push_uint%s (proc, dst%s);",
+                 cpu_type == cpu6811 ? "m68hc11" : "m68hc12",
 		 operand_size, operand_size);
 	  operands += 3;
 	  result_size = operand_size;
@@ -1182,6 +1720,41 @@ gen_save_result (FILE *fp, int col,
 	}
       break;
 
+    case '[':
+      if (strncmp (operands, "]", 1) == 0)
+	{
+	  if (addr_set == 0)
+	    {
+	      current_insn_size += 1;
+	      print (fp, col, "addr = cpu_get_indexed_operand_addr (proc,0);");
+	    }
+	  print (fp, col, "memory_write%s (proc, addr, dst%s);",
+		 operand_size, operand_size);
+	  operands++;
+	  result_size = operand_size;
+	}
+      else
+	{
+	  fatal_error (opcode, "Invalid operand");
+	}
+      break;
+      
+    case '{':
+      if (strncmp (operands, "}", 1) == 0)
+	{
+	  current_insn_size += 1;
+	  print (fp, col, "addr = cpu_get_indexed_operand_addr (proc, 1);");
+	  print (fp, col, "memory_write%s (proc, addr, dst%s);",
+		 operand_size, operand_size);
+	  operands++;
+	  result_size = operand_size;
+	}
+      else
+	{
+	  fatal_error (opcode, "Invalid operand");
+	}
+      break;
+      
     case 's':
       if (strncmp (operands, "p", 1) == 0)
 	{
@@ -1246,7 +1819,6 @@ find_opcode_pattern (const struct m6811_
   return 0;
 }
 
-
 /* Generate the code for interpretation of instruction 'opcode'.  */
 void
 gen_interp (FILE *fp, int col, const struct m6811_opcode_def *opcode)
@@ -1316,7 +1888,8 @@ gen_interpreter_for_table (FILE *fp, int
   int i;
   int init_size;
 
-  init_size = table == m6811_page1_opcodes ? 1 : 2;
+  init_size = table == m6811_page1_opcodes
+    || table == m6812_page1_opcodes? 1 : 2;
   
   /* Get the opcode and dispatch directly.  */
   print (fp, col, "op = cpu_fetch8 (proc);");
@@ -1334,10 +1907,13 @@ gen_interpreter_for_table (FILE *fp, int
 
       current_insn_size = init_size;
       gen_interp (fp, col, &table[i]);
+#if 0
       if (current_insn_size != table[i].insn_size)
 	{
-	  fatal_error (&table[i], "Insn size inconsistency");
+	  fatal_error (&table[i], "Insn size %ld inconsistent with %ld",
+		       current_insn_size, table[i].insn_size);
 	}
+#endif
     }
 
   print (fp, col, "default:\n");
@@ -1421,58 +1997,139 @@ gen_function_close (FILE *fp)
   print (fp, 0, "}\n");
 }
 
+int
+cmp_opcode (void* e1, void* e2)
+{
+  struct m6811_opcode_def* op1 = (struct m6811_opcode_def*) e1;
+  struct m6811_opcode_def* op2 = (struct m6811_opcode_def*) e2;
+  
+  return (int) (op1->insn_code) - (int) (op2->insn_code);
+}
+
 void
+prepare_table (struct m6811_opcode_def* table, int size)
+{
+  int i;
+  
+  qsort (table, size, sizeof (table[0]), cmp_opcode);
+  for (i = 1; i < size; i++)
+    {
+      if (table[i].insn_code == table[i-1].insn_code)
+	{
+	  fprintf (stderr, "Two insns with code 0x%02x\n",
+		   table[i].insn_code);
+	}
+    }
+}
+
+void
 gen_interpreter (FILE *fp)
 {
   int col = 0;
 
+  prepare_table (m6811_page1_opcodes, TABLE_SIZE (m6811_page1_opcodes));
+  prepare_table (m6811_page2_opcodes, TABLE_SIZE (m6811_page2_opcodes));
+  prepare_table (m6811_page3_opcodes, TABLE_SIZE (m6811_page3_opcodes));
+  prepare_table (m6811_page4_opcodes, TABLE_SIZE (m6811_page4_opcodes));
+
+  prepare_table (m6812_page1_opcodes, TABLE_SIZE (m6812_page1_opcodes));
+  prepare_table (m6812_page2_opcodes, TABLE_SIZE (m6812_page2_opcodes));
+
   /* Generate header of interpretor.  */
   print (fp, col, "/* File generated automatically by gencode. */\n");
   print (fp, col, "#include \"sim-main.h\"\n\n");
+
+  if (cpu_type & cpu6811)
+    {
+      gen_cycle_table (fp, "cycles_page1", m6811_page1_opcodes,
+		       TABLE_SIZE (m6811_page1_opcodes));
+      gen_cycle_table (fp, "cycles_page2", m6811_page2_opcodes,
+		       TABLE_SIZE (m6811_page2_opcodes));
+      gen_cycle_table (fp, "cycles_page3", m6811_page3_opcodes,
+		       TABLE_SIZE (m6811_page3_opcodes));
+      gen_cycle_table (fp, "cycles_page4", m6811_page4_opcodes,
+		       TABLE_SIZE (m6811_page4_opcodes));
+
+      gen_function_entry (fp, "static void\ncpu_page3_interp");
+      gen_interpreter_for_table (fp, indent_level,
+				 m6811_page3_opcodes,
+				 TABLE_SIZE(m6811_page3_opcodes),
+				 "cycles_page3");
+      gen_function_close (fp);
+  
+      gen_function_entry (fp, "static void\ncpu_page4_interp");
+      gen_interpreter_for_table (fp, indent_level,
+				 m6811_page4_opcodes,
+				 TABLE_SIZE(m6811_page4_opcodes),
+				 "cycles_page4");
+      gen_function_close (fp);
+
+      /* Generate the page 2, 3 and 4 handlers.  */
+      gen_function_entry (fp, "static void\ncpu_page2_interp");
+      gen_interpreter_for_table (fp, indent_level,
+				 m6811_page2_opcodes,
+				 TABLE_SIZE(m6811_page2_opcodes),
+				 "cycles_page2");
+      gen_function_close (fp);
+
+      /* Generate the interpretor entry point.  */
+      gen_function_entry (fp, "void\ncpu_interp_m6811");
+
+      gen_interpreter_for_table (fp, indent_level, m6811_page1_opcodes,
+				 TABLE_SIZE(m6811_page1_opcodes),
+				 "cycles_page1");
+      gen_function_close (fp);
+    }
+  else
+    {
+      gen_cycle_table (fp, "cycles_page1", m6812_page1_opcodes,
+		       TABLE_SIZE (m6812_page1_opcodes));
+      gen_cycle_table (fp, "cycles_page2", m6812_page2_opcodes,
+		       TABLE_SIZE (m6812_page2_opcodes));
+
+      gen_function_entry (fp, "static void\ncpu_page2_interp");
+      gen_interpreter_for_table (fp, indent_level,
+				 m6812_page2_opcodes,
+				 TABLE_SIZE(m6812_page2_opcodes),
+				 "cycles_page2");
+      gen_function_close (fp);
+
+      /* Generate the interpretor entry point.  */
+      gen_function_entry (fp, "void\ncpu_interp_m6812");
+
+      gen_interpreter_for_table (fp, indent_level, m6812_page1_opcodes,
+				 TABLE_SIZE(m6812_page1_opcodes),
+				 "cycles_page1");
+      gen_function_close (fp);
+    }
+}
 
-  gen_cycle_table (fp, "cycles_page1", m6811_page1_opcodes,
-		   TABLE_SIZE (m6811_page1_opcodes));
-  gen_cycle_table (fp, "cycles_page2", m6811_page2_opcodes,
-		   TABLE_SIZE (m6811_page2_opcodes));
-  gen_cycle_table (fp, "cycles_page3", m6811_page3_opcodes,
-		   TABLE_SIZE (m6811_page3_opcodes));
-  gen_cycle_table (fp, "cycles_page4", m6811_page4_opcodes,
-		   TABLE_SIZE (m6811_page4_opcodes));
-
-  /* Generate the page 2, 3 and 4 handlers.  */
-  gen_function_entry (fp, "static void\ncpu_page2_interp");
-  gen_interpreter_for_table (fp, indent_level,
-			     m6811_page2_opcodes,
-			     TABLE_SIZE(m6811_page2_opcodes),
-			     "cycles_page2");
-  gen_function_close (fp);
-  
-  gen_function_entry (fp, "static void\ncpu_page3_interp");
-  gen_interpreter_for_table (fp, indent_level,
-			     m6811_page3_opcodes,
-			     TABLE_SIZE(m6811_page3_opcodes),
-			     "cycles_page3");
-  gen_function_close (fp);
-  
-  gen_function_entry (fp, "static void\ncpu_page4_interp");
-  gen_interpreter_for_table (fp, indent_level,
-			     m6811_page4_opcodes,
-			     TABLE_SIZE(m6811_page4_opcodes),
-			     "cycles_page4");
-  gen_function_close (fp);
-
-  /* Generate the interpretor entry point.  */
-  gen_function_entry (fp, "void\ncpu_interp");
-
-  gen_interpreter_for_table (fp, indent_level, m6811_page1_opcodes,
-			     TABLE_SIZE(m6811_page1_opcodes),
-			     "cycles_page1");
-  gen_function_close (fp);
+void
+usage (char* prog)
+{
+  fprintf (stderr, "Usage: %s {-m6811|-m6812}\n", prog);
+  exit (2);
 }
 
 int
 main (int argc, char *argv[])
 {
+  int i;
+
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], "-m6811") == 0)
+	cpu_type = cpu6811;
+      else if (strcmp (argv[i], "-m6812") == 0)
+	cpu_type = cpu6812;
+      else
+	{
+	  usage (argv[0]);
+	}
+    }
+  if (cpu_type == 0)
+    usage (argv[0]);
+  
   gen_interpreter (stdout);
   if (fclose (stdout) != 0)
     {
Index: interp.c
===================================================================
RCS file: /cvs/src/src/sim/m68hc11/interp.c,v
retrieving revision 1.3
diff -u -p -r1.3 interp.c
--- interp.c	2000/09/10 14:05:29	1.3
+++ interp.c	2001/05/20 15:32:28
@@ -1,5 +1,5 @@
 /* interp.c -- Simulator for Motorola 68HC11
-   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
    Written by Stephane Carrez (stcarrez@worldnet.fr)
 
 This file is part of GDB, the GNU debugger.
@@ -55,7 +55,7 @@ struct sim_info_list
   const char *device;
 };
 
-struct sim_info_list dev_list[] = {
+struct sim_info_list dev_list_68hc11[] = {
   {"cpu", "/m68hc11"},
   {"timer", "/m68hc11/m68hc11tim"},
   {"sio", "/m68hc11/m68hc11sio"},
@@ -64,18 +64,48 @@ struct sim_info_list dev_list[] = {
   {0, 0}
 };
 
+struct sim_info_list dev_list_68hc12[] = {
+  {"cpu", "/m68hc12"},
+  {"timer", "/m68hc12/m68hc12tim"},
+  {"sio", "/m68hc12/m68hc12sio"},
+  {"spi", "/m68hc12/m68hc12spi"},
+  {"eeprom", "/m68hc12/m68hc12eepr"},
+  {0, 0}
+};
+
+/* Cover function of sim_state_free to free the cpu buffers as well.  */
+
+static void
+free_state (SIM_DESC sd)
+{
+  if (STATE_MODULES (sd) != NULL)
+    sim_module_uninstall (sd);
+
+  sim_state_free (sd);
+}
+
 /* Give some information about the simulator.  */
 static void
 sim_get_info (SIM_DESC sd, char *cmd)
 {
   sim_cpu *cpu;
 
+  cpu = STATE_CPU (sd, 0);
   if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-'))
     {
       int i;
       struct hw *hw_dev;
+      struct sim_info_list *dev_list;
+      const struct bfd_arch_info *arch;
+
+      arch = STATE_ARCHITECTURE (sd);
       cmd++;
 
+      if (arch->arch == bfd_arch_m68hc11)
+        dev_list = dev_list_68hc11;
+      else
+        dev_list = dev_list_68hc12;
+
       for (i = 0; dev_list[i].name; i++)
 	if (strcmp (cmd, dev_list[i].name) == 0)
 	  break;
@@ -96,7 +126,6 @@ sim_get_info (SIM_DESC sd, char *cmd)
       return;
     }
 
-  cpu = STATE_CPU (sd, 0);
   cpu_info (sd, cpu);
   interrupts_info (sd, &cpu->cpu_interrupts);
 }
@@ -107,13 +136,28 @@ sim_board_reset (SIM_DESC sd)
 {
   struct hw *hw_cpu;
   sim_cpu *cpu;
+  const struct bfd_arch_info *arch;
+  const char *cpu_type;
 
   cpu = STATE_CPU (sd, 0);
+  arch = STATE_ARCHITECTURE (sd);
+
   /*  hw_cpu = sim_hw_parse (sd, "/"); */
-  hw_cpu = sim_hw_parse (sd, "/m68hc11");
+  if (arch->arch == bfd_arch_m68hc11)
+    {
+      cpu->cpu_type = CPU_M6811;
+      cpu_type = "/m68hc11";
+    }
+  else
+    {
+      cpu->cpu_type = CPU_M6812;
+      cpu_type = "/m68hc12";
+    }
+  
+  hw_cpu = sim_hw_parse (sd, cpu_type);
   if (hw_cpu == 0)
     {
-      sim_io_eprintf (sd, "m68hc11 cpu not found in device tree.");
+      sim_io_eprintf (sd, "%s cpu not found in device tree.", cpu_type);
       return;
     }
 
@@ -122,6 +166,144 @@ sim_board_reset (SIM_DESC sd)
   cpu_restart (cpu);
 }
 
+int
+sim_hw_configure (SIM_DESC sd)
+{
+  const struct bfd_arch_info *arch;
+  struct hw *device_tree;
+  int m6811_mode;
+  sim_cpu *cpu;
+  
+  arch = STATE_ARCHITECTURE (sd);
+  if (arch == 0)
+    return 0;
+
+  cpu = STATE_CPU (sd, 0);
+  cpu->cpu_configured_arch = arch;
+  device_tree = sim_hw_parse (sd, "/");
+  if (arch->arch == bfd_arch_m68hc11)
+    {
+      cpu->cpu_interpretor = cpu_interp_m6811;
+      if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
+	{
+	  /* Allocate core managed memory */
+
+	  /* the monitor  */
+	  sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
+			   /* MONITOR_BASE, MONITOR_SIZE */
+			   0x8000, M6811_RAM_LEVEL, 0x8000);
+	  sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
+			   M6811_RAM_LEVEL);
+	  sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
+	}
+
+      if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0)
+	{
+	  sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5");
+	  sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio");
+	  sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio");
+	}
+      if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0)
+	{
+	  /* M68hc11 Timer configuration. */
+	  sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5");
+	  sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim");
+	}
+
+      /* Create the SPI device.  */
+      if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0)
+	{
+	  sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3");
+	  sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
+	}
+      if (hw_tree_find_property (device_tree, "/m68hc11/nvram/reg") == 0)
+	{
+	  /* M68hc11 persistent ram configuration. */
+	  sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256");
+	  sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram");
+	  sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified");
+	  /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */
+	}
+      if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0)
+	{
+	  sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512");
+	  sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
+	}
+    }
+  else
+    {
+      cpu->cpu_interpretor = cpu_interp_m6812;
+      if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0)
+	{
+	  /* Allocate core external memory.  */
+	  sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
+			   0x8000, M6811_RAM_LEVEL, 0x8000);
+	  sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
+			   M6811_RAM_LEVEL);
+
+	  sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF");
+	}
+
+      if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg"))
+	{
+	  sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8");
+	  sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/backend stdio");
+	  sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1");
+	}
+      if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@2/reg"))
+	{
+	  sim_hw_parse (sd, "/m68hc12/m68hc12sio@2/reg 0xC8 0x8");
+	  sim_hw_parse (sd, "/m68hc12/m68hc12sio@2/backend tcp");
+	  sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@2");
+	}
+      if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0)
+	{
+	  /* M68hc11 Timer configuration. */
+	  sim_hw_parse (sd, "/m68hc12/m68hc12tim/reg 0x1b 0x5");
+	  sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim");
+	}
+
+      /* Create the SPI device.  */
+      if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0)
+	{
+	  sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3");
+	  sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
+	}
+      if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0)
+	{
+	  /* M68hc11 persistent ram configuration. */
+	  sim_hw_parse (sd, "/m68hc12/nvram/reg 0x2000 8192");
+	  sim_hw_parse (sd, "/m68hc12/nvram/file m68hc12.ram");
+	  sim_hw_parse (sd, "/m68hc12/nvram/mode save-modified");
+	}
+      if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0)
+	{
+	  sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
+	  sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
+	}
+    }
+  return 0;
+}
+
+static int
+sim_prepare_for_program (SIM_DESC sd, struct _bfd* abfd)
+{
+  sim_cpu *cpu;
+
+  cpu = STATE_CPU (sd, 0);
+
+  sim_hw_configure (sd);
+  if (abfd != NULL)
+    {
+      cpu->cpu_elf_start = bfd_get_start_address (abfd);
+    }
+
+  /* reset all state information */
+  sim_board_reset (sd);
+
+  return SIM_RC_OK;
+}
+
 SIM_DESC
 sim_open (SIM_OPEN_KIND kind, host_callback *callback,
           struct _bfd *abfd, char **argv)
@@ -144,7 +326,10 @@ sim_open (SIM_OPEN_KIND kind, host_callb
 
   cpu->cpu_use_elf_start = 1;
   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
-    return 0;
+    {
+      free_state (sd);
+      return 0;
+    }
 
   /* getopt will print the error message so we just have to exit if this fails.
      FIXME: Hmmm...  in the case of gdb we need getopt to call
@@ -153,72 +338,24 @@ sim_open (SIM_OPEN_KIND kind, host_callb
     {
       /* Uninstall the modules to avoid memory leaks,
          file descriptor leaks, etc.  */
-      sim_module_uninstall (sd);
+      free_state (sd);
       return 0;
     }
 
-  device_tree = sim_hw_parse (sd, "/");
-  if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
-    {
-      /* Allocate core managed memory */
-
-      /* the monitor  */
-      sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
-		       /* MONITOR_BASE, MONITOR_SIZE */
-		       0x8000, M6811_RAM_LEVEL, 0x8000);
-      sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
-                       M6811_RAM_LEVEL);
-      sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
-    }
-
-  if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0)
-    {
-      sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5");
-      sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio");
-      sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio");
-    }
-  if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0)
-    {
-      /* M68hc11 Timer configuration. */
-      sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5");
-      sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim");
-    }
-
-  /* Create the SPI device.  */
-  if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0)
-    {
-      sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3");
-      sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
-    }
-  if (hw_tree_find_property (device_tree, "/m68hc11/pram/reg") == 0)
-    {
-      /* M68hc11 persistent ram configuration. */
-      sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256");
-      sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram");
-      sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified");
-      /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */
-    }
-  if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0)
-    {
-      sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512");
-      /* Connect the CPU reset to all devices. */
-      sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
-    }
-
   /* Check for/establish the a reference program image.  */
   if (sim_analyze_program (sd,
 			   (STATE_PROG_ARGV (sd) != NULL
 			    ? *STATE_PROG_ARGV (sd)
 			    : NULL), abfd) != SIM_RC_OK)
     {
-      sim_module_uninstall (sd);
+      free_state (sd);
       return 0;
     }
 
   /* Establish any remaining configuration options.  */
   if (sim_config (sd) != SIM_RC_OK)
     {
-      sim_module_uninstall (sd);
+      free_state (sd);
       return 0;
     }
 
@@ -226,16 +363,11 @@ sim_open (SIM_OPEN_KIND kind, host_callb
     {
       /* Uninstall the modules to avoid memory leaks,
          file descriptor leaks, etc.  */
-      sim_module_uninstall (sd);
+      free_state (sd);
       return 0;
     }
-
-  if (abfd != NULL)
-    {
-      cpu->cpu_elf_start = bfd_get_start_address (abfd);
-    }
 
-  sim_board_reset (sd);
+  sim_hw_configure (sd);
 
   /* Fudge our descriptor.  */
   return sd;
@@ -253,7 +385,7 @@ sim_close (SIM_DESC sd, int quitting)
   sim_io_shutdown (sd);
 
   /* FIXME - free SD */
-
+  sim_state_free (sd);
   return;
 }
 
@@ -302,8 +434,17 @@ sim_trace (SIM_DESC sd)
 void
 sim_info (SIM_DESC sd, int verbose)
 {
+  const char *cpu_type;
+  const struct bfd_arch_info *arch;
+
+  arch = STATE_ARCHITECTURE (sd);
+  if (arch->arch == bfd_arch_m68hc11)
+    cpu_type = "68HC11";
+  else
+    cpu_type = "68HC12";
+
   sim_io_eprintf (sd, "Simulator info:\n");
-  sim_io_eprintf (sd, "  CPU Motorola 68HC11\n");
+  sim_io_eprintf (sd, "  CPU Motorola %s\n", cpu_type);
   sim_get_info (sd, 0);
   sim_module_info (sd, verbose || STATE_VERBOSE_P (sd));
 }
@@ -312,20 +453,7 @@ SIM_RC
 sim_create_inferior (SIM_DESC sd, struct _bfd *abfd,
                      char **argv, char **env)
 {
-  sim_cpu *cpu;
-  int i;
-
-  cpu = STATE_CPU (sd, 0);
-
-  if (abfd != NULL)
-    {
-      cpu->cpu_elf_start = bfd_get_start_address (abfd);
-    }
-
-  /* reset all state information */
-  sim_board_reset (sd);
-
-  return SIM_RC_OK;
+  return sim_prepare_for_program (sd, abfd);
 }
 
 
@@ -450,7 +578,9 @@ sim_do_command (SIM_DESC sd, char *cmd)
 {
   char *mm_cmd = "memory-map";
   char *int_cmd = "interrupt";
+  sim_cpu *cpu;
 
+  cpu = STATE_CPU (sd, 0);
   /* Commands available from GDB:   */
   if (sim_args_command (sd, cmd) != SIM_RC_OK)
     {
@@ -466,4 +596,8 @@ sim_do_command (SIM_DESC sd, char *cmd)
       else
 	sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
     }
+
+  /* If the architecture changed, re-configure.  */
+  if (STATE_ARCHITECTURE (sd) != cpu->cpu_configured_arch)
+    sim_hw_configure (sd);
 }
Index: m68hc11_sim.c
===================================================================
RCS file: /cvs/src/src/sim/m68hc11/m68hc11_sim.c,v
retrieving revision 1.2
diff -u -p -r1.2 m68hc11_sim.c
--- m68hc11_sim.c	2000/09/09 21:00:39	1.2
+++ m68hc11_sim.c	2001/05/20 15:32:34
@@ -1,5 +1,5 @@
-/* m6811_cpu.c -- 68HC11 CPU Emulation
-   Copyright 1999, 2000 Free Software Foundation, Inc.
+/* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
+   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
    Written by Stephane Carrez (stcarrez@worldnet.fr)
 
 This file is part of GDB, GAS, and the GNU binutils.
@@ -305,6 +305,341 @@ cpu_set_sp (sim_cpu *cpu, uint16 val)
   cpu_update_frame (cpu, 0);
 }
 
+uint16
+cpu_get_reg (sim_cpu* cpu, uint8 reg)
+{
+  switch (reg)
+    {
+    case 0:
+      return cpu_get_x (cpu);
+
+    case 1:
+      return cpu_get_y (cpu);
+
+    case 2:
+      return cpu_get_sp (cpu);
+
+    case 3:
+      return cpu_get_pc (cpu);
+
+    default:
+      return 0;
+    }
+}
+
+uint16
+cpu_get_src_reg (sim_cpu* cpu, uint8 reg)
+{
+  switch (reg)
+    {
+    case 0:
+      return cpu_get_a (cpu);
+
+    case 1:
+      return cpu_get_b (cpu);
+
+    case 2:
+      return cpu_get_ccr (cpu);
+
+    case 3:
+      return cpu_get_tmp3 (cpu);
+
+    case 4:
+      return cpu_get_d (cpu);
+
+    case 5:
+      return cpu_get_x (cpu);
+
+    case 6:
+      return cpu_get_y (cpu);
+
+    case 7:
+      return cpu_get_sp (cpu);
+
+    default:
+      return 0;
+    }
+}
+
+void
+cpu_set_dst_reg (sim_cpu* cpu, uint8 reg, uint16 val)
+{
+  switch (reg)
+    {
+    case 0:
+      cpu_set_a (cpu, val);
+      break;
+
+    case 1:
+      cpu_set_b (cpu, val);
+      break;
+
+    case 2:
+      cpu_set_ccr (cpu, val);
+      break;
+
+    case 3:
+      cpu_set_tmp2 (cpu, val);
+      break;
+
+    case 4:
+      cpu_set_d (cpu, val);
+      break;
+
+    case 5:
+      cpu_set_x (cpu, val);
+      break;
+
+    case 6:
+      cpu_set_y (cpu, val);
+      break;
+
+    case 7:
+      cpu_set_sp (cpu, val);
+      break;
+
+    default:
+      break;
+    }
+}
+
+void
+cpu_set_reg (sim_cpu* cpu, uint8 reg, uint16 val)
+{
+  switch (reg)
+    {
+    case 0:
+      cpu_set_x (cpu, val);
+      break;
+      
+    case 1:
+      cpu_set_y (cpu, val);
+      break;
+      
+    case 2:
+      cpu_set_sp (cpu, val);
+      break;
+      
+    case 3:
+      cpu_set_pc (cpu, val);
+      break;
+      
+    default:
+      break;
+    }
+}
+
+/* Returns the address of a 68HC12 indexed operand.
+   Pre and post modifications are handled on the source register.  */
+uint16
+cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict)
+{
+  uint8 reg;
+  uint16 sval;
+  uint16 addr;
+  uint8 code;
+
+  code = cpu_fetch8 (cpu);
+
+  /* n,r with 5-bit signed constant.  */
+  if ((code & 0x20) == 0)
+    {
+      reg = (code >> 6) & 3;
+      sval = (code & 0x1f);
+      if (code & 0x10)
+	sval |= 0xfff0;
+
+      addr = cpu_get_reg (cpu, reg);
+      addr += sval;
+    }
+
+  /* Auto pre/post increment/decrement.  */
+  else if ((code & 0xc0) != 0xc0)
+    {
+      reg = (code >> 6) & 3;
+      sval = (code & 0x0f);
+      if (sval & 0x8)
+	{
+	  sval |= 0xfff0;
+	}
+      else
+	{
+	  sval = sval + 1;
+	}
+      addr = cpu_get_reg (cpu, reg);
+      cpu_set_reg (cpu, reg, addr + sval);
+      if ((code & 0x10) == 0)
+	{
+	  addr += sval;
+	}
+    }
+
+  /* [n,r] 16-bits offset indexed indirect.  */
+  else if ((code & 0x07) == 3)
+    {
+      if (restrict)
+	{
+	  return 0;
+	}
+      reg = (code >> 3) & 0x03;
+      addr = cpu_get_reg (cpu, reg);
+      addr += cpu_fetch16 (cpu);
+      addr = memory_read16 (cpu, addr);
+      cpu_add_cycles (cpu, 1);
+    }
+  else if ((code & 0x4) == 0)
+    {
+      if (restrict)
+	{
+	  return 0;
+	}
+      reg = (code >> 3) & 0x03;
+      addr = cpu_get_reg (cpu, reg);
+      if (code & 0x2)
+	{
+	  sval = cpu_fetch16 (cpu);
+	  cpu_add_cycles (cpu, 1);
+	}
+      else
+	{
+	  sval = cpu_fetch8 (cpu);
+	  if (code & 0x1)
+	    sval |= 0xff00;
+	  cpu_add_cycles (cpu, 1);
+	}
+      addr += sval;
+    }
+  else
+    {
+      reg = (code >> 3) & 0x03;
+      addr = cpu_get_reg (cpu, reg);
+      switch (code & 3)
+	{
+	case 0:
+	  addr += cpu_get_a (cpu);
+	  break;
+	case 1:
+	  addr += cpu_get_b (cpu);
+	  break;
+	case 2:
+	  addr += cpu_get_d (cpu);
+	  break;
+	case 3:
+	default:
+	  addr += cpu_get_d (cpu);
+	  addr = memory_read16 (cpu, addr);
+	  cpu_add_cycles (cpu, 1);
+	  break;
+	}
+    }
+
+  return addr;
+}
+
+uint8
+cpu_get_indexed_operand8 (sim_cpu* cpu, int restrict)
+{
+  uint16 addr;
+
+  addr = cpu_get_indexed_operand_addr (cpu, restrict);
+  return memory_read8 (cpu, addr);
+}
+
+uint16
+cpu_get_indexed_operand16 (sim_cpu* cpu, int restrict)
+{
+  uint16 addr;
+
+  addr = cpu_get_indexed_operand_addr (cpu, restrict);
+  return memory_read16 (cpu, addr);
+}
+
+void
+cpu_move8 (sim_cpu *cpu, uint8 code)
+{
+  uint8 src;
+  uint16 addr;
+
+  switch (code)
+    {
+    case 0x0b:
+      src = cpu_fetch8 (cpu);
+      addr = cpu_fetch16 (cpu);
+      break;
+
+    case 0x08:
+      addr = cpu_get_indexed_operand_addr (cpu, 1);
+      src = cpu_fetch8 (cpu);
+      break;
+
+    case 0x0c:
+      addr = cpu_fetch16 (cpu);
+      src = memory_read8 (cpu, addr);
+      addr = cpu_fetch16 (cpu);
+      break;
+
+    case 0x09:
+      addr = cpu_get_indexed_operand_addr (cpu, 1);
+      src = memory_read8 (cpu, cpu_fetch16 (cpu));
+      break;
+
+    case 0x0d:
+      src = cpu_get_indexed_operand8 (cpu, 1);
+      addr = cpu_fetch16 (cpu);
+      break;
+
+    case 0x0a:
+      src = cpu_get_indexed_operand8 (cpu, 1);
+      addr = cpu_get_indexed_operand_addr (cpu, 1);
+      break;
+      
+    }
+  memory_write8 (cpu, addr, src);
+}
+
+void
+cpu_move16 (sim_cpu *cpu, uint8 code)
+{
+  uint16 src;
+  uint16 addr;
+
+  switch (code)
+    {
+    case 0x03:
+      src = cpu_fetch16 (cpu);
+      addr = cpu_fetch16 (cpu);
+      break;
+
+    case 0x00:
+      addr = cpu_get_indexed_operand_addr (cpu, 1);
+      src = cpu_fetch16 (cpu);
+      break;
+
+    case 0x04:
+      addr = cpu_fetch16 (cpu);
+      src = memory_read16 (cpu, addr);
+      addr = cpu_fetch16 (cpu);
+      break;
+
+    case 0x01:
+      addr = cpu_get_indexed_operand_addr (cpu, 1);
+      src = memory_read16 (cpu, cpu_fetch16 (cpu));
+      break;
+
+    case 0x05:
+      src = cpu_get_indexed_operand16 (cpu, 1);
+      addr = cpu_fetch16 (cpu);
+      break;
+
+    case 0x02:
+      src = cpu_get_indexed_operand16 (cpu, 1);
+      addr = cpu_get_indexed_operand_addr (cpu, 1);
+      break;
+      
+    }
+  memory_write16 (cpu, addr, src);
+}
+
 int
 cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
 {
@@ -346,7 +681,10 @@ cpu_reset (sim_cpu *cpu)
   /* Initialize the config register.
      It is only initialized at reset time.  */
   memset (cpu->ios, 0, sizeof (cpu->ios));
-  cpu->ios[M6811_INIT] = 0x1;
+  if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
+    cpu->ios[M6811_INIT] = 0x1;
+  else
+    cpu->ios[M6811_INIT] = 0;
 
   /* Output compare registers set to 0xFFFF.  */
   cpu->ios[M6811_TOC1_H] = 0xFF;
@@ -463,19 +801,110 @@ cpu_fetch_relbranch (sim_cpu *cpu)
   return addr;
 }
 
+uint16
+cpu_fetch_relbranch16 (sim_cpu *cpu)
+{
+  uint16 addr = cpu_fetch16 (cpu);
 
+  addr += cpu->cpu_regs.pc;
+  return addr;
+}
+
 /* Push all the CPU registers (when an interruption occurs).  */
 void
 cpu_push_all (sim_cpu *cpu)
+{
+  if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
+    {
+      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.pc);
+      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.iy);
+      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.ix);
+      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.d);
+      cpu_m68hc11_push_uint8 (cpu, cpu->cpu_regs.ccr);
+    }
+  else
+    {
+      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.pc);
+      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.iy);
+      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.ix);
+      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.d);
+      cpu_m68hc12_push_uint8 (cpu, cpu->cpu_regs.ccr);
+    }
+}
+
+/* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations.  */
+void
+cpu_dbcc (sim_cpu* cpu)
 {
-  cpu_push_uint16 (cpu, cpu->cpu_regs.pc);
-  cpu_push_uint16 (cpu, cpu->cpu_regs.iy);
-  cpu_push_uint16 (cpu, cpu->cpu_regs.ix);
-  cpu_push_uint16 (cpu, cpu->cpu_regs.d);
-  cpu_push_uint8 (cpu, cpu->cpu_regs.ccr);
+  uint8 code;
+  uint16 addr;
+  uint16 inc;
+  uint16 reg;
+  
+  code = cpu_fetch8 (cpu);
+  switch (code & 0xc0)
+    {
+    case 0x80: /* ibcc */
+      inc = 1;
+      break;
+    case 0x40: /* tbcc */
+      inc = 0;
+      break;
+    case 0:    /* dbcc */
+      inc = -1;
+      break;
+    default:
+      abort ();
+      break;
+    }
+
+  addr = cpu_fetch8 (cpu);
+  if (code & 0x10)
+    addr |= 0xff00;
+
+  addr += cpu_get_pc (cpu);
+  reg = cpu_get_src_reg (cpu, code & 0x07);
+  reg += inc;
+
+  /* Branch according to register value.  */
+  if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
+    {
+      cpu_set_pc (cpu, addr);
+    }
+  cpu_set_dst_reg (cpu, code & 0x07, reg);
 }
 
+void
+cpu_exg (sim_cpu* cpu, uint8 code)
+{
+  uint8 r1, r2;
+  uint16 src1;
+  uint16 src2;
+
+  r1 = (code >> 4) & 0x07;
+  r2 = code & 0x07;
+  if (code & 0x80)
+    {
+      src1 = cpu_get_src_reg (cpu, r1);
+      src2 = cpu_get_src_reg (cpu, r2);
+      if (r2 == 1 || r2 == 2)
+        src2 |= 0xff00;
+      
+      cpu_set_dst_reg (cpu, r2, src1);
+      cpu_set_dst_reg (cpu, r1, src2);
+    }
+  else
+    {
+      src1 = cpu_get_src_reg (cpu, r1);
+
+      /* Sign extend the 8-bit registers (A, B, CCR).  */
+      if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
+        src1 |= 0xff00;
 
+      cpu_set_dst_reg (cpu, r2, src1);
+    }
+}
+
 /* Handle special instructions.  */
 void
 cpu_special (sim_cpu *cpu, enum M6811_Special special)
@@ -485,13 +914,27 @@ cpu_special (sim_cpu *cpu, enum M6811_Sp
     case M6811_RTI:
       {
         uint8 ccr;
+
+        ccr = cpu_m68hc11_pop_uint8 (cpu);
+        cpu_set_ccr (cpu, ccr);
+        cpu_set_d (cpu, cpu_m68hc11_pop_uint16 (cpu));
+        cpu_set_x (cpu, cpu_m68hc11_pop_uint16 (cpu));
+        cpu_set_y (cpu, cpu_m68hc11_pop_uint16 (cpu));
+        cpu_set_pc (cpu, cpu_m68hc11_pop_uint16 (cpu));
+	cpu_return (cpu);
+        break;
+      }
+
+    case M6812_RTI:
+      {
+        uint8 ccr;
 
-        ccr = cpu_pop_uint8 (cpu);
+        ccr = cpu_m68hc12_pop_uint8 (cpu);
         cpu_set_ccr (cpu, ccr);
-        cpu_set_d (cpu, cpu_pop_uint16 (cpu));
-        cpu_set_x (cpu, cpu_pop_uint16 (cpu));
-        cpu_set_y (cpu, cpu_pop_uint16 (cpu));
-        cpu_set_pc (cpu, cpu_pop_uint16 (cpu));
+        cpu_set_d (cpu, cpu_m68hc12_pop_uint16 (cpu));
+        cpu_set_x (cpu, cpu_m68hc12_pop_uint16 (cpu));
+        cpu_set_y (cpu, cpu_m68hc12_pop_uint16 (cpu));
+        cpu_set_pc (cpu, cpu_m68hc12_pop_uint16 (cpu));
 	cpu_return (cpu);
         break;
       }
@@ -542,6 +985,7 @@ cpu_special (sim_cpu *cpu, enum M6811_Sp
       break;
 
     case M6811_TEST:
+    case M6812_BGND:
       {
         SIM_DESC sd;
 
@@ -558,6 +1002,115 @@ cpu_special (sim_cpu *cpu, enum M6811_Sp
         /* else this is a nop but not in test factory mode.  */
         break;
       }
+
+    case M6812_IDIVS:
+      {
+        int32 src1 = (int16) cpu_get_d (cpu);
+        int32 src2 = (int16) cpu_get_x (cpu);
+
+        if (src2 == 0)
+          {
+            cpu_set_ccr_C (cpu, 1);
+          }
+        else
+          {
+            cpu_set_d (cpu, src1 % src2);
+            src1 = src1 / src2;
+            cpu_set_x (cpu, src1);
+            cpu_set_ccr_C (cpu, 0);
+            cpu_set_ccr_Z (cpu, src1 == 0);
+            cpu_set_ccr_N (cpu, src1 & 0x8000);
+            cpu_set_ccr_V (cpu, src1 >= 32768 || src1 < -32768);
+          }
+      }
+      break;
+      
+    case M6812_EDIV:
+      {
+        uint32 src1 = (uint32) cpu_get_x (cpu);
+        uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
+          | (uint32) (cpu_get_d (cpu));
+
+        if (src1 == 0)
+          {
+            cpu_set_ccr_C (cpu, 1);
+          }
+        else
+          {
+            cpu_set_ccr_C (cpu, 0);
+            cpu_set_d (cpu, src2 % src1);
+            src2 = src2 / src1;
+            cpu_set_y (cpu, src2);
+            cpu_set_ccr_Z (cpu, src2 == 0);
+            cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
+            cpu_set_ccr_V (cpu, (src2 & 0xffff0000) != 0);
+          }
+      }
+      break;
+      
+    case M6812_EDIVS:
+      {
+        int32 src1 = (int16) cpu_get_x (cpu);
+        int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
+          | (uint32) (cpu_get_d (cpu));
+
+        if (src1 == 0)
+          {
+            cpu_set_ccr_C (cpu, 1);
+          }
+        else
+          {
+            cpu_set_ccr_C (cpu, 0);
+            cpu_set_d (cpu, src2 % src1);
+            src2 = src2 / src1;
+            cpu_set_y (cpu, src2);
+            cpu_set_ccr_Z (cpu, src2 == 0);
+            cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
+            cpu_set_ccr_V (cpu, src2 > 32767 || src2 < -32768);
+          }
+      }
+      break;      
+
+    case M6812_EMULS:
+      {
+        int32 src1, src2;
+
+        src1 = (int16) cpu_get_d (cpu);
+        src2 = (int16) cpu_get_y (cpu);
+        src1 = src1 * src2;
+        cpu_set_d (cpu, src1 & 0x0ffff);
+        cpu_set_y (cpu, src1 >> 16);
+        cpu_set_ccr_Z (cpu, src1 == 0);
+        cpu_set_ccr_N (cpu, (src1 & 0x80000000) != 0);
+        cpu_set_ccr_C (cpu, (src1 & 0x00008000) != 0);
+      }
+      break;
+      
+    case M6812_EMACS:
+      {
+        int32 src1, src2;
+        uint16 addr;
+        
+        addr = cpu_fetch16 (cpu);
+        src1 = (int16) memory_read16 (cpu, cpu_get_x (cpu));
+        src2 = (int16) memory_read16 (cpu, cpu_get_y (cpu));
+        src1 = src1 * src2;
+        src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
+          | (uint32) memory_read16 (cpu, addr + 2);
+
+        memory_write16 (cpu, addr, (src1 + src2) >> 16);
+        memory_write16 (cpu, addr + 2, (src1 + src2));
+
+        
+      }
+      break;
+
+    case M6812_ETBL:
+    default:
+      sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
+                       cpu_get_pc (cpu), sim_stopped,
+                       SIM_SIGILL);
+      break;
     }
 }
 
@@ -577,7 +1130,7 @@ cpu_single_step (sim_cpu *cpu)
     }
   
   /*  printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
-  cpu_interp (cpu);
+  cpu->cpu_interpretor (cpu);
   cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
 }
 
Index: sim-main.h
===================================================================
RCS file: /cvs/src/src/sim/m68hc11/sim-main.h,v
retrieving revision 1.4
diff -u -p -r1.4 sim-main.h
--- sim-main.h	2000/09/10 14:05:29	1.4
+++ sim-main.h	2001/05/20 15:32:46
@@ -1,5 +1,5 @@
-/* sim-main.h -- Simulator for Motorola 68HC11
-   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* sim-main.h -- Simulator for Motorola 68HC11 & 68HC12
+   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
    Written by Stephane Carrez (stcarrez@worldnet.fr)
 
 This file is part of GDB, the GNU debugger.
@@ -65,6 +65,11 @@ enum m68hc11_map_level
   M6811_RAM_LEVEL
 };
 
+enum cpu_type
+{
+  CPU_M6811,
+  CPU_M6812
+};
 
 #define X_REGNUM 	0
 #define D_REGNUM	1
@@ -103,23 +108,45 @@ extern void print_io_byte (SIM_DESC sd, 
 			   io_reg_desc *desc, uint8 val, uint16 addr);
 
 
-/* List of special 68HC11 instructions that are not handled by the
+/* List of special 68HC11&68HC12 instructions that are not handled by the
    'gencode.c' generator.  These complex instructions are implemented
    by 'cpu_special'.  */
 enum M6811_Special
 {
+  /* 68HC11 instructions.  */
+  M6811_DAA,
+  M6811_EMUL_SYSCALL,
+  M6811_ILLEGAL,
   M6811_RTI,
-  M6811_WAI,
+  M6811_STOP,
   M6811_SWI,
   M6811_TEST,
-  M6811_ILLEGAL,
-  M6811_EMUL_SYSCALL
+  M6811_WAI,
+
+  /* 68HC12 instructions.  */
+  M6812_BGND,
+  M6812_CALL,
+  M6812_IDIVS,
+  M6812_EDIV,
+  M6812_EDIVS,
+  M6812_EMACS,
+  M6812_EMUL,
+  M6812_EMULS,
+  M6812_ETBL,
+  M6812_MEM,
+  M6812_REV,
+  M6812_REVW,
+  M6812_RTC,
+  M6812_RTI,
+  M6812_WAV
 };
 
 #define CPU_POP 1
 #define CPU_PUSH 2
 
-#define MAX_PORTS 0x40
+#define M6811_MAX_PORTS (0x03f+1)
+#define M6812_MAX_PORTS (0x3ff+1)
+#define MAX_PORTS       (M6812_MAX_PORTS)
 
 /* Tentative to keep track of the stack frame.
    The frame is updated each time a call or a return are made.
@@ -141,6 +168,10 @@ struct cpu_frame_list
   struct cpu_frame      *frame;
 };
 
+struct _sim_cpu;
+
+typedef void (* cpu_interp) (struct _sim_cpu*);
+
 struct _sim_cpu {
   /* CPU registers.  */
   struct m6811_regs     cpu_regs;
@@ -152,6 +183,12 @@ struct _sim_cpu {
   struct cpu_frame_list *cpu_current_frame;
   int                   cpu_need_update_frame;
 
+  /* Pointer to the interpretor routine.  */
+  cpu_interp            cpu_interpretor;
+
+  /* Pointer to the architecture currently configured in the simulator.  */
+  const struct bfd_arch_info  *cpu_configured_arch;
+  
   /* CPU absolute cycle time.  The cycle time is updated after
      each instruction, by the number of cycles taken by the instruction.
      It is cleared only when reset occurs.  */
@@ -186,11 +223,14 @@ struct _sim_cpu {
   /* The mode in which the CPU is configured (MODA and MODB pins).  */
   unsigned int          cpu_mode;
 
+  /* The cpu being configured.  */
+  enum cpu_type         cpu_type;
+  
   /* Initial value of the CONFIG register.  */
   uint8                 cpu_config;
   uint8                 cpu_use_local_config;
   
-  uint8 ios[0x3F];
+  uint8                 ios[MAX_PORTS];
   
   /* ... base type ... */
   sim_cpu_base base;
@@ -218,10 +258,18 @@ struct _sim_cpu {
 #define cpu_get_a(PROC)            ((PROC->cpu_regs.d >> 8) & 0x0FF)
 #define cpu_get_b(PROC)            ((PROC->cpu_regs.d) & 0x0FF)
 
+/* 68HC12 specific and Motorola internal registers.  */
+#define cpu_get_tmp3(PROC)         (0)
+#define cpu_get_tmp2(PROC)         (0)
+
 #define cpu_set_d(PROC,VAL)        (((PROC)->cpu_regs.d) = (VAL))
 #define cpu_set_x(PROC,VAL)        (((PROC)->cpu_regs.ix) = (VAL))
 #define cpu_set_y(PROC,VAL)        (((PROC)->cpu_regs.iy) = (VAL))
 
+/* 68HC12 specific and Motorola internal registers.  */
+#define cpu_set_tmp3(PROC,VAL)     (0)
+#define cpu_set_tmp2(PROC,VAL)     (0)
+
 #if 0
 /* This is a function in m68hc11_sim.c to keep track of the frame.  */
 #define cpu_set_sp(PROC,VAL)       (((PROC)->cpu_regs.sp) = (VAL))
@@ -376,10 +424,10 @@ cpu_ccr_update_sub16 (sim_cpu *proc, uin
   cpu_set_ccr_Z (proc, r == 0);
   cpu_set_ccr_N (proc, r & 0x8000 ? 1 : 0);
 }
-
 
+/* Push and pop instructions for 68HC11 (next-available stack mode).  */
 inline void
-cpu_push_uint8 (sim_cpu *proc, uint8 val)
+cpu_m68hc11_push_uint8 (sim_cpu *proc, uint8 val)
 {
   uint16 addr = proc->cpu_regs.sp;
 
@@ -389,7 +437,7 @@ cpu_push_uint8 (sim_cpu *proc, uint8 val
 }
 
 inline void
-cpu_push_uint16 (sim_cpu *proc, uint16 val)
+cpu_m68hc11_push_uint16 (sim_cpu *proc, uint16 val)
 {
   uint16 addr = proc->cpu_regs.sp - 1;
 
@@ -399,7 +447,7 @@ cpu_push_uint16 (sim_cpu *proc, uint16 v
 }
 
 inline uint8
-cpu_pop_uint8 (sim_cpu *proc)
+cpu_m68hc11_pop_uint8 (sim_cpu *proc)
 {
   uint16 addr = proc->cpu_regs.sp;
   uint8 val;
@@ -411,7 +459,7 @@ cpu_pop_uint8 (sim_cpu *proc)
 }
 
 inline uint16
-cpu_pop_uint16 (sim_cpu *proc)
+cpu_m68hc11_pop_uint16 (sim_cpu *proc)
 {
   uint16 addr = proc->cpu_regs.sp;
   uint16 val;
@@ -422,6 +470,54 @@ cpu_pop_uint16 (sim_cpu *proc)
   return val;
 }
 
+/* Push and pop instructions for 68HC12 (last-used stack mode).  */
+inline void
+cpu_m68hc12_push_uint8 (sim_cpu *proc, uint8 val)
+{
+  uint16 addr = proc->cpu_regs.sp;
+
+  addr --;
+  memory_write8 (proc, addr, val);
+  proc->cpu_regs.sp = addr;
+  proc->cpu_need_update_frame |= CPU_PUSH;
+}
+
+inline void
+cpu_m68hc12_push_uint16 (sim_cpu *proc, uint16 val)
+{
+  uint16 addr = proc->cpu_regs.sp;
+
+  addr -= 2;
+  memory_write16 (proc, addr, val);
+  proc->cpu_regs.sp = addr;
+  proc->cpu_need_update_frame |= CPU_PUSH;
+}
+
+inline uint8
+cpu_m68hc12_pop_uint8 (sim_cpu *proc)
+{
+  uint16 addr = proc->cpu_regs.sp;
+  uint8 val;
+  
+  val = memory_read8 (proc, addr);
+  proc->cpu_regs.sp = addr + 1;
+  proc->cpu_need_update_frame |= CPU_POP;
+  return val;
+}
+
+inline uint16
+cpu_m68hc12_pop_uint16 (sim_cpu *proc)
+{
+  uint16 addr = proc->cpu_regs.sp;
+  uint16 val;
+  
+  val = memory_read16 (proc, addr);
+  proc->cpu_regs.sp = addr + 2;
+  proc->cpu_need_update_frame |= CPU_POP;
+  return val;
+}
+
+/* Fetch a 8/16 bit value and update the PC.  */
 inline uint8
 cpu_fetch8 (sim_cpu *proc)
 {
@@ -445,9 +541,14 @@ cpu_fetch16 (sim_cpu *proc)
 }
 
 extern void cpu_call (sim_cpu* proc, uint16 addr);
+extern void cpu_exg (sim_cpu* proc, uint8 code);
+extern void cpu_dbcc (sim_cpu* proc);
 extern void cpu_special (sim_cpu *proc, enum M6811_Special special);
+extern void cpu_move8 (sim_cpu *proc, uint8 op);
+extern void cpu_move16 (sim_cpu *proc, uint8 op);
 
 extern uint16 cpu_fetch_relbranch (sim_cpu *proc);
+extern uint16 cpu_fetch_relbranch16 (sim_cpu *proc);
 extern void cpu_push_all (sim_cpu *proc);
 extern void cpu_single_step (sim_cpu *proc);
 
@@ -463,7 +564,8 @@ extern int cpu_restart (sim_cpu *cpu);
 extern void sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
                               uint16 addr, const char *message, ...);
 extern void emul_os (int op, sim_cpu *cpu);
-extern void cpu_interp (sim_cpu *cpu);
+extern void cpu_interp_m6811 (sim_cpu *cpu);
+extern void cpu_interp_m6812 (sim_cpu *cpu);
 
 /* The current state of the processor; registers, memory, etc.  */
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]