166e63ce3Schristos /* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
2*1424dfb3Schristos Copyright 1999-2020 Free Software Foundation, Inc.
366e63ce3Schristos Written by Stephane Carrez (stcarrez@nerim.fr)
466e63ce3Schristos
566e63ce3Schristos This file is part of GDB, GAS, and the GNU binutils.
666e63ce3Schristos
766e63ce3Schristos This program is free software; you can redistribute it and/or modify
866e63ce3Schristos it under the terms of the GNU General Public License as published by
966e63ce3Schristos the Free Software Foundation; either version 3 of the License, or
1066e63ce3Schristos (at your option) any later version.
1166e63ce3Schristos
1266e63ce3Schristos This program is distributed in the hope that it will be useful,
1366e63ce3Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1466e63ce3Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1566e63ce3Schristos GNU General Public License for more details.
1666e63ce3Schristos
1766e63ce3Schristos You should have received a copy of the GNU General Public License
1866e63ce3Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */
1966e63ce3Schristos
2066e63ce3Schristos #include "sim-main.h"
2166e63ce3Schristos #include "sim-assert.h"
2266e63ce3Schristos #include "sim-module.h"
2366e63ce3Schristos #include "sim-options.h"
2466e63ce3Schristos
2566e63ce3Schristos enum {
2666e63ce3Schristos OPTION_CPU_RESET = OPTION_START,
2766e63ce3Schristos OPTION_EMUL_OS,
2866e63ce3Schristos OPTION_CPU_CONFIG,
2966e63ce3Schristos OPTION_CPU_BOOTSTRAP,
3066e63ce3Schristos OPTION_CPU_MODE
3166e63ce3Schristos };
3266e63ce3Schristos
3366e63ce3Schristos static DECLARE_OPTION_HANDLER (cpu_option_handler);
3466e63ce3Schristos
3566e63ce3Schristos static const OPTION cpu_options[] =
3666e63ce3Schristos {
3766e63ce3Schristos { {"cpu-reset", no_argument, NULL, OPTION_CPU_RESET },
3866e63ce3Schristos '\0', NULL, "Reset the CPU",
3966e63ce3Schristos cpu_option_handler },
4066e63ce3Schristos
4166e63ce3Schristos { {"emulos", no_argument, NULL, OPTION_EMUL_OS },
4266e63ce3Schristos '\0', NULL, "Emulate some OS system calls (read, write, ...)",
4366e63ce3Schristos cpu_option_handler },
4466e63ce3Schristos
4566e63ce3Schristos { {"cpu-config", required_argument, NULL, OPTION_CPU_CONFIG },
4666e63ce3Schristos '\0', NULL, "Specify the initial CPU configuration register",
4766e63ce3Schristos cpu_option_handler },
4866e63ce3Schristos
4966e63ce3Schristos { {"bootstrap", no_argument, NULL, OPTION_CPU_BOOTSTRAP },
5066e63ce3Schristos '\0', NULL, "Start the processing in bootstrap mode",
5166e63ce3Schristos cpu_option_handler },
5266e63ce3Schristos
5366e63ce3Schristos { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
5466e63ce3Schristos };
5566e63ce3Schristos
5666e63ce3Schristos
5766e63ce3Schristos static SIM_RC
cpu_option_handler(SIM_DESC sd,sim_cpu * cpu,int opt,char * arg,int is_command)5866e63ce3Schristos cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
5966e63ce3Schristos int opt, char *arg, int is_command)
6066e63ce3Schristos {
6166e63ce3Schristos int val;
6266e63ce3Schristos
6366e63ce3Schristos cpu = STATE_CPU (sd, 0);
6466e63ce3Schristos switch (opt)
6566e63ce3Schristos {
6666e63ce3Schristos case OPTION_CPU_RESET:
6766e63ce3Schristos sim_board_reset (sd);
6866e63ce3Schristos break;
6966e63ce3Schristos
7066e63ce3Schristos case OPTION_EMUL_OS:
7166e63ce3Schristos cpu->cpu_emul_syscall = 1;
7266e63ce3Schristos break;
7366e63ce3Schristos
7466e63ce3Schristos case OPTION_CPU_CONFIG:
7566e63ce3Schristos if (sscanf(arg, "0x%x", &val) == 1
7666e63ce3Schristos || sscanf(arg, "%d", &val) == 1)
7766e63ce3Schristos {
7866e63ce3Schristos cpu->cpu_config = val;
7966e63ce3Schristos cpu->cpu_use_local_config = 1;
8066e63ce3Schristos }
8166e63ce3Schristos else
8266e63ce3Schristos cpu->cpu_use_local_config = 0;
8366e63ce3Schristos break;
8466e63ce3Schristos
8566e63ce3Schristos case OPTION_CPU_BOOTSTRAP:
8666e63ce3Schristos cpu->cpu_start_mode = "bootstrap";
8766e63ce3Schristos break;
8866e63ce3Schristos
8966e63ce3Schristos case OPTION_CPU_MODE:
9066e63ce3Schristos break;
9166e63ce3Schristos }
9266e63ce3Schristos
9366e63ce3Schristos return SIM_RC_OK;
9466e63ce3Schristos }
9566e63ce3Schristos
9666e63ce3Schristos
9766e63ce3Schristos void
cpu_call(sim_cpu * cpu,uint16 addr)9866e63ce3Schristos cpu_call (sim_cpu *cpu, uint16 addr)
9966e63ce3Schristos {
10066e63ce3Schristos
10166e63ce3Schristos cpu_set_pc (cpu, addr);
10266e63ce3Schristos }
10366e63ce3Schristos
10466e63ce3Schristos void
cpu_return(sim_cpu * cpu)10566e63ce3Schristos cpu_return (sim_cpu *cpu)
10666e63ce3Schristos {
10766e63ce3Schristos }
10866e63ce3Schristos
10966e63ce3Schristos /* Set the stack pointer and re-compute the current frame. */
11066e63ce3Schristos void
cpu_set_sp(sim_cpu * cpu,uint16 val)11166e63ce3Schristos cpu_set_sp (sim_cpu *cpu, uint16 val)
11266e63ce3Schristos {
11366e63ce3Schristos cpu->cpu_regs.sp = val;
11466e63ce3Schristos }
11566e63ce3Schristos
11666e63ce3Schristos uint16
cpu_get_reg(sim_cpu * cpu,uint8 reg)11766e63ce3Schristos cpu_get_reg (sim_cpu *cpu, uint8 reg)
11866e63ce3Schristos {
11966e63ce3Schristos switch (reg)
12066e63ce3Schristos {
12166e63ce3Schristos case 0:
12266e63ce3Schristos return cpu_get_x (cpu);
12366e63ce3Schristos
12466e63ce3Schristos case 1:
12566e63ce3Schristos return cpu_get_y (cpu);
12666e63ce3Schristos
12766e63ce3Schristos case 2:
12866e63ce3Schristos return cpu_get_sp (cpu);
12966e63ce3Schristos
13066e63ce3Schristos case 3:
13166e63ce3Schristos return cpu_get_pc (cpu);
13266e63ce3Schristos
13366e63ce3Schristos default:
13466e63ce3Schristos return 0;
13566e63ce3Schristos }
13666e63ce3Schristos }
13766e63ce3Schristos
13866e63ce3Schristos uint16
cpu_get_src_reg(sim_cpu * cpu,uint8 reg)13966e63ce3Schristos cpu_get_src_reg (sim_cpu *cpu, uint8 reg)
14066e63ce3Schristos {
14166e63ce3Schristos switch (reg)
14266e63ce3Schristos {
14366e63ce3Schristos case 0:
14466e63ce3Schristos return cpu_get_a (cpu);
14566e63ce3Schristos
14666e63ce3Schristos case 1:
14766e63ce3Schristos return cpu_get_b (cpu);
14866e63ce3Schristos
14966e63ce3Schristos case 2:
15066e63ce3Schristos return cpu_get_ccr (cpu);
15166e63ce3Schristos
15266e63ce3Schristos case 3:
15366e63ce3Schristos return cpu_get_tmp3 (cpu);
15466e63ce3Schristos
15566e63ce3Schristos case 4:
15666e63ce3Schristos return cpu_get_d (cpu);
15766e63ce3Schristos
15866e63ce3Schristos case 5:
15966e63ce3Schristos return cpu_get_x (cpu);
16066e63ce3Schristos
16166e63ce3Schristos case 6:
16266e63ce3Schristos return cpu_get_y (cpu);
16366e63ce3Schristos
16466e63ce3Schristos case 7:
16566e63ce3Schristos return cpu_get_sp (cpu);
16666e63ce3Schristos
16766e63ce3Schristos default:
16866e63ce3Schristos return 0;
16966e63ce3Schristos }
17066e63ce3Schristos }
17166e63ce3Schristos
17266e63ce3Schristos void
cpu_set_dst_reg(sim_cpu * cpu,uint8 reg,uint16 val)17366e63ce3Schristos cpu_set_dst_reg (sim_cpu *cpu, uint8 reg, uint16 val)
17466e63ce3Schristos {
17566e63ce3Schristos switch (reg)
17666e63ce3Schristos {
17766e63ce3Schristos case 0:
17866e63ce3Schristos cpu_set_a (cpu, val);
17966e63ce3Schristos break;
18066e63ce3Schristos
18166e63ce3Schristos case 1:
18266e63ce3Schristos cpu_set_b (cpu, val);
18366e63ce3Schristos break;
18466e63ce3Schristos
18566e63ce3Schristos case 2:
18666e63ce3Schristos cpu_set_ccr (cpu, val);
18766e63ce3Schristos break;
18866e63ce3Schristos
18966e63ce3Schristos case 3:
19066e63ce3Schristos cpu_set_tmp2 (cpu, val);
19166e63ce3Schristos break;
19266e63ce3Schristos
19366e63ce3Schristos case 4:
19466e63ce3Schristos cpu_set_d (cpu, val);
19566e63ce3Schristos break;
19666e63ce3Schristos
19766e63ce3Schristos case 5:
19866e63ce3Schristos cpu_set_x (cpu, val);
19966e63ce3Schristos break;
20066e63ce3Schristos
20166e63ce3Schristos case 6:
20266e63ce3Schristos cpu_set_y (cpu, val);
20366e63ce3Schristos break;
20466e63ce3Schristos
20566e63ce3Schristos case 7:
20666e63ce3Schristos cpu_set_sp (cpu, val);
20766e63ce3Schristos break;
20866e63ce3Schristos
20966e63ce3Schristos default:
21066e63ce3Schristos break;
21166e63ce3Schristos }
21266e63ce3Schristos }
21366e63ce3Schristos
21466e63ce3Schristos void
cpu_set_reg(sim_cpu * cpu,uint8 reg,uint16 val)21566e63ce3Schristos cpu_set_reg (sim_cpu *cpu, uint8 reg, uint16 val)
21666e63ce3Schristos {
21766e63ce3Schristos switch (reg)
21866e63ce3Schristos {
21966e63ce3Schristos case 0:
22066e63ce3Schristos cpu_set_x (cpu, val);
22166e63ce3Schristos break;
22266e63ce3Schristos
22366e63ce3Schristos case 1:
22466e63ce3Schristos cpu_set_y (cpu, val);
22566e63ce3Schristos break;
22666e63ce3Schristos
22766e63ce3Schristos case 2:
22866e63ce3Schristos cpu_set_sp (cpu, val);
22966e63ce3Schristos break;
23066e63ce3Schristos
23166e63ce3Schristos case 3:
23266e63ce3Schristos cpu_set_pc (cpu, val);
23366e63ce3Schristos break;
23466e63ce3Schristos
23566e63ce3Schristos default:
23666e63ce3Schristos break;
23766e63ce3Schristos }
23866e63ce3Schristos }
23966e63ce3Schristos
24066e63ce3Schristos /* Returns the address of a 68HC12 indexed operand.
24166e63ce3Schristos Pre and post modifications are handled on the source register. */
24266e63ce3Schristos uint16
cpu_get_indexed_operand_addr(sim_cpu * cpu,int restricted)243ed6a76a9Schristos cpu_get_indexed_operand_addr (sim_cpu *cpu, int restricted)
24466e63ce3Schristos {
24566e63ce3Schristos uint8 reg;
24666e63ce3Schristos uint16 sval;
24766e63ce3Schristos uint16 addr;
24866e63ce3Schristos uint8 code;
24966e63ce3Schristos
25066e63ce3Schristos code = cpu_fetch8 (cpu);
25166e63ce3Schristos
25266e63ce3Schristos /* n,r with 5-bit signed constant. */
25366e63ce3Schristos if ((code & 0x20) == 0)
25466e63ce3Schristos {
25566e63ce3Schristos reg = (code >> 6) & 3;
25666e63ce3Schristos sval = (code & 0x1f);
25766e63ce3Schristos if (code & 0x10)
25866e63ce3Schristos sval |= 0xfff0;
25966e63ce3Schristos
26066e63ce3Schristos addr = cpu_get_reg (cpu, reg);
26166e63ce3Schristos addr += sval;
26266e63ce3Schristos }
26366e63ce3Schristos
26466e63ce3Schristos /* Auto pre/post increment/decrement. */
26566e63ce3Schristos else if ((code & 0xc0) != 0xc0)
26666e63ce3Schristos {
26766e63ce3Schristos reg = (code >> 6) & 3;
26866e63ce3Schristos sval = (code & 0x0f);
26966e63ce3Schristos if (sval & 0x8)
27066e63ce3Schristos {
27166e63ce3Schristos sval |= 0xfff0;
27266e63ce3Schristos }
27366e63ce3Schristos else
27466e63ce3Schristos {
27566e63ce3Schristos sval = sval + 1;
27666e63ce3Schristos }
27766e63ce3Schristos addr = cpu_get_reg (cpu, reg);
27866e63ce3Schristos cpu_set_reg (cpu, reg, addr + sval);
27966e63ce3Schristos if ((code & 0x10) == 0)
28066e63ce3Schristos {
28166e63ce3Schristos addr += sval;
28266e63ce3Schristos }
28366e63ce3Schristos }
28466e63ce3Schristos
28566e63ce3Schristos /* [n,r] 16-bits offset indexed indirect. */
28666e63ce3Schristos else if ((code & 0x07) == 3)
28766e63ce3Schristos {
288ed6a76a9Schristos if (restricted)
28966e63ce3Schristos {
29066e63ce3Schristos return 0;
29166e63ce3Schristos }
29266e63ce3Schristos reg = (code >> 3) & 0x03;
29366e63ce3Schristos addr = cpu_get_reg (cpu, reg);
29466e63ce3Schristos addr += cpu_fetch16 (cpu);
29566e63ce3Schristos addr = memory_read16 (cpu, addr);
29666e63ce3Schristos cpu_add_cycles (cpu, 1);
29766e63ce3Schristos }
29866e63ce3Schristos else if ((code & 0x4) == 0)
29966e63ce3Schristos {
300ed6a76a9Schristos if (restricted)
30166e63ce3Schristos {
30266e63ce3Schristos return 0;
30366e63ce3Schristos }
30466e63ce3Schristos reg = (code >> 3) & 0x03;
30566e63ce3Schristos addr = cpu_get_reg (cpu, reg);
30666e63ce3Schristos if (code & 0x2)
30766e63ce3Schristos {
30866e63ce3Schristos sval = cpu_fetch16 (cpu);
30966e63ce3Schristos cpu_add_cycles (cpu, 1);
31066e63ce3Schristos }
31166e63ce3Schristos else
31266e63ce3Schristos {
31366e63ce3Schristos sval = cpu_fetch8 (cpu);
31466e63ce3Schristos if (code & 0x1)
31566e63ce3Schristos sval |= 0xff00;
31666e63ce3Schristos cpu_add_cycles (cpu, 1);
31766e63ce3Schristos }
31866e63ce3Schristos addr += sval;
31966e63ce3Schristos }
32066e63ce3Schristos else
32166e63ce3Schristos {
32266e63ce3Schristos reg = (code >> 3) & 0x03;
32366e63ce3Schristos addr = cpu_get_reg (cpu, reg);
32466e63ce3Schristos switch (code & 3)
32566e63ce3Schristos {
32666e63ce3Schristos case 0:
32766e63ce3Schristos addr += cpu_get_a (cpu);
32866e63ce3Schristos break;
32966e63ce3Schristos case 1:
33066e63ce3Schristos addr += cpu_get_b (cpu);
33166e63ce3Schristos break;
33266e63ce3Schristos case 2:
33366e63ce3Schristos addr += cpu_get_d (cpu);
33466e63ce3Schristos break;
33566e63ce3Schristos case 3:
33666e63ce3Schristos default:
33766e63ce3Schristos addr += cpu_get_d (cpu);
33866e63ce3Schristos addr = memory_read16 (cpu, addr);
33966e63ce3Schristos cpu_add_cycles (cpu, 1);
34066e63ce3Schristos break;
34166e63ce3Schristos }
34266e63ce3Schristos }
34366e63ce3Schristos
34466e63ce3Schristos return addr;
34566e63ce3Schristos }
34666e63ce3Schristos
34766e63ce3Schristos uint8
cpu_get_indexed_operand8(sim_cpu * cpu,int restricted)348ed6a76a9Schristos cpu_get_indexed_operand8 (sim_cpu *cpu, int restricted)
34966e63ce3Schristos {
35066e63ce3Schristos uint16 addr;
35166e63ce3Schristos
352ed6a76a9Schristos addr = cpu_get_indexed_operand_addr (cpu, restricted);
35366e63ce3Schristos return memory_read8 (cpu, addr);
35466e63ce3Schristos }
35566e63ce3Schristos
35666e63ce3Schristos uint16
cpu_get_indexed_operand16(sim_cpu * cpu,int restricted)357ed6a76a9Schristos cpu_get_indexed_operand16 (sim_cpu *cpu, int restricted)
35866e63ce3Schristos {
35966e63ce3Schristos uint16 addr;
36066e63ce3Schristos
361ed6a76a9Schristos addr = cpu_get_indexed_operand_addr (cpu, restricted);
36266e63ce3Schristos return memory_read16 (cpu, addr);
36366e63ce3Schristos }
36466e63ce3Schristos
36566e63ce3Schristos void
cpu_move8(sim_cpu * cpu,uint8 code)36666e63ce3Schristos cpu_move8 (sim_cpu *cpu, uint8 code)
36766e63ce3Schristos {
36866e63ce3Schristos uint8 src;
36966e63ce3Schristos uint16 addr;
37066e63ce3Schristos
37166e63ce3Schristos switch (code)
37266e63ce3Schristos {
37366e63ce3Schristos case 0x0b:
37466e63ce3Schristos src = cpu_fetch8 (cpu);
37566e63ce3Schristos addr = cpu_fetch16 (cpu);
37666e63ce3Schristos break;
37766e63ce3Schristos
37866e63ce3Schristos case 0x08:
37966e63ce3Schristos addr = cpu_get_indexed_operand_addr (cpu, 1);
38066e63ce3Schristos src = cpu_fetch8 (cpu);
38166e63ce3Schristos break;
38266e63ce3Schristos
38366e63ce3Schristos case 0x0c:
38466e63ce3Schristos addr = cpu_fetch16 (cpu);
38566e63ce3Schristos src = memory_read8 (cpu, addr);
38666e63ce3Schristos addr = cpu_fetch16 (cpu);
38766e63ce3Schristos break;
38866e63ce3Schristos
38966e63ce3Schristos case 0x09:
39066e63ce3Schristos addr = cpu_get_indexed_operand_addr (cpu, 1);
39166e63ce3Schristos src = memory_read8 (cpu, cpu_fetch16 (cpu));
39266e63ce3Schristos break;
39366e63ce3Schristos
39466e63ce3Schristos case 0x0d:
39566e63ce3Schristos src = cpu_get_indexed_operand8 (cpu, 1);
39666e63ce3Schristos addr = cpu_fetch16 (cpu);
39766e63ce3Schristos break;
39866e63ce3Schristos
39966e63ce3Schristos case 0x0a:
40066e63ce3Schristos src = cpu_get_indexed_operand8 (cpu, 1);
40166e63ce3Schristos addr = cpu_get_indexed_operand_addr (cpu, 1);
40266e63ce3Schristos break;
40366e63ce3Schristos
40466e63ce3Schristos default:
40566e63ce3Schristos sim_engine_abort (CPU_STATE (cpu), cpu, 0,
40666e63ce3Schristos "Invalid code 0x%0x -- internal error?", code);
40766e63ce3Schristos return;
40866e63ce3Schristos }
40966e63ce3Schristos memory_write8 (cpu, addr, src);
41066e63ce3Schristos }
41166e63ce3Schristos
41266e63ce3Schristos void
cpu_move16(sim_cpu * cpu,uint8 code)41366e63ce3Schristos cpu_move16 (sim_cpu *cpu, uint8 code)
41466e63ce3Schristos {
41566e63ce3Schristos uint16 src;
41666e63ce3Schristos uint16 addr;
41766e63ce3Schristos
41866e63ce3Schristos switch (code)
41966e63ce3Schristos {
42066e63ce3Schristos case 0x03:
42166e63ce3Schristos src = cpu_fetch16 (cpu);
42266e63ce3Schristos addr = cpu_fetch16 (cpu);
42366e63ce3Schristos break;
42466e63ce3Schristos
42566e63ce3Schristos case 0x00:
42666e63ce3Schristos addr = cpu_get_indexed_operand_addr (cpu, 1);
42766e63ce3Schristos src = cpu_fetch16 (cpu);
42866e63ce3Schristos break;
42966e63ce3Schristos
43066e63ce3Schristos case 0x04:
43166e63ce3Schristos addr = cpu_fetch16 (cpu);
43266e63ce3Schristos src = memory_read16 (cpu, addr);
43366e63ce3Schristos addr = cpu_fetch16 (cpu);
43466e63ce3Schristos break;
43566e63ce3Schristos
43666e63ce3Schristos case 0x01:
43766e63ce3Schristos addr = cpu_get_indexed_operand_addr (cpu, 1);
43866e63ce3Schristos src = memory_read16 (cpu, cpu_fetch16 (cpu));
43966e63ce3Schristos break;
44066e63ce3Schristos
44166e63ce3Schristos case 0x05:
44266e63ce3Schristos src = cpu_get_indexed_operand16 (cpu, 1);
44366e63ce3Schristos addr = cpu_fetch16 (cpu);
44466e63ce3Schristos break;
44566e63ce3Schristos
44666e63ce3Schristos case 0x02:
44766e63ce3Schristos src = cpu_get_indexed_operand16 (cpu, 1);
44866e63ce3Schristos addr = cpu_get_indexed_operand_addr (cpu, 1);
44966e63ce3Schristos break;
45066e63ce3Schristos
45166e63ce3Schristos default:
45266e63ce3Schristos sim_engine_abort (CPU_STATE (cpu), cpu, 0,
45366e63ce3Schristos "Invalid code 0x%0x -- internal error?", code);
45466e63ce3Schristos return;
45566e63ce3Schristos }
45666e63ce3Schristos memory_write16 (cpu, addr, src);
45766e63ce3Schristos }
45866e63ce3Schristos
45966e63ce3Schristos int
cpu_initialize(SIM_DESC sd,sim_cpu * cpu)46066e63ce3Schristos cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
46166e63ce3Schristos {
46266e63ce3Schristos sim_add_option_table (sd, 0, cpu_options);
46366e63ce3Schristos
46466e63ce3Schristos memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
46566e63ce3Schristos
46666e63ce3Schristos cpu->cpu_absolute_cycle = 0;
46766e63ce3Schristos cpu->cpu_current_cycle = 0;
46866e63ce3Schristos cpu->cpu_emul_syscall = 1;
46966e63ce3Schristos cpu->cpu_running = 1;
47066e63ce3Schristos cpu->cpu_stop_on_interrupt = 0;
47166e63ce3Schristos cpu->cpu_frequency = 8 * 1000 * 1000;
47266e63ce3Schristos cpu->cpu_use_elf_start = 0;
47366e63ce3Schristos cpu->cpu_elf_start = 0;
47466e63ce3Schristos cpu->cpu_use_local_config = 0;
47566e63ce3Schristos cpu->bank_start = 0;
47666e63ce3Schristos cpu->bank_end = 0;
47766e63ce3Schristos cpu->bank_shift = 0;
47866e63ce3Schristos cpu->cpu_config = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
47966e63ce3Schristos M6811_EEON;
48066e63ce3Schristos interrupts_initialize (sd, cpu);
48166e63ce3Schristos
48266e63ce3Schristos cpu->cpu_is_initialized = 1;
48366e63ce3Schristos return 0;
48466e63ce3Schristos }
48566e63ce3Schristos
48666e63ce3Schristos
48766e63ce3Schristos /* Reinitialize the processor after a reset. */
48866e63ce3Schristos int
cpu_reset(sim_cpu * cpu)48966e63ce3Schristos cpu_reset (sim_cpu *cpu)
49066e63ce3Schristos {
49166e63ce3Schristos /* Initialize the config register.
49266e63ce3Schristos It is only initialized at reset time. */
49366e63ce3Schristos memset (cpu->ios, 0, sizeof (cpu->ios));
49466e63ce3Schristos if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
49566e63ce3Schristos cpu->ios[M6811_INIT] = 0x1;
49666e63ce3Schristos else
49766e63ce3Schristos cpu->ios[M6811_INIT] = 0;
49866e63ce3Schristos
49966e63ce3Schristos /* Output compare registers set to 0xFFFF. */
50066e63ce3Schristos cpu->ios[M6811_TOC1_H] = 0xFF;
50166e63ce3Schristos cpu->ios[M6811_TOC1_L] = 0xFF;
50266e63ce3Schristos cpu->ios[M6811_TOC2_H] = 0xFF;
50366e63ce3Schristos cpu->ios[M6811_TOC2_L] = 0xFF;
50466e63ce3Schristos cpu->ios[M6811_TOC3_H] = 0xFF;
50566e63ce3Schristos cpu->ios[M6811_TOC4_L] = 0xFF;
50666e63ce3Schristos cpu->ios[M6811_TOC5_H] = 0xFF;
50766e63ce3Schristos cpu->ios[M6811_TOC5_L] = 0xFF;
50866e63ce3Schristos
50966e63ce3Schristos /* Setup the processor registers. */
51066e63ce3Schristos memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
51166e63ce3Schristos cpu->cpu_absolute_cycle = 0;
51266e63ce3Schristos cpu->cpu_current_cycle = 0;
51366e63ce3Schristos cpu->cpu_is_initialized = 0;
51466e63ce3Schristos
51566e63ce3Schristos /* Reset interrupts. */
51666e63ce3Schristos interrupts_reset (&cpu->cpu_interrupts);
51766e63ce3Schristos
51866e63ce3Schristos /* Reinitialize the CPU operating mode. */
51966e63ce3Schristos cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
52066e63ce3Schristos return 0;
52166e63ce3Schristos }
52266e63ce3Schristos
52366e63ce3Schristos /* Reinitialize the processor after a reset. */
52466e63ce3Schristos int
cpu_restart(sim_cpu * cpu)52566e63ce3Schristos cpu_restart (sim_cpu *cpu)
52666e63ce3Schristos {
52766e63ce3Schristos uint16 addr;
52866e63ce3Schristos
52966e63ce3Schristos /* Get CPU starting address depending on the CPU mode. */
53066e63ce3Schristos if (cpu->cpu_use_elf_start == 0)
53166e63ce3Schristos {
53266e63ce3Schristos switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
53366e63ce3Schristos {
53466e63ce3Schristos /* Single Chip */
53566e63ce3Schristos default:
53666e63ce3Schristos case 0 :
53766e63ce3Schristos addr = memory_read16 (cpu, 0xFFFE);
53866e63ce3Schristos break;
53966e63ce3Schristos
54066e63ce3Schristos /* Expanded Multiplexed */
54166e63ce3Schristos case M6811_MDA:
54266e63ce3Schristos addr = memory_read16 (cpu, 0xFFFE);
54366e63ce3Schristos break;
54466e63ce3Schristos
54566e63ce3Schristos /* Special Bootstrap */
54666e63ce3Schristos case M6811_SMOD:
54766e63ce3Schristos addr = 0;
54866e63ce3Schristos break;
54966e63ce3Schristos
55066e63ce3Schristos /* Factory Test */
55166e63ce3Schristos case M6811_MDA | M6811_SMOD:
55266e63ce3Schristos addr = memory_read16 (cpu, 0xFFFE);
55366e63ce3Schristos break;
55466e63ce3Schristos }
55566e63ce3Schristos }
55666e63ce3Schristos else
55766e63ce3Schristos {
55866e63ce3Schristos addr = cpu->cpu_elf_start;
55966e63ce3Schristos }
56066e63ce3Schristos
56166e63ce3Schristos /* Setup the processor registers. */
56266e63ce3Schristos cpu->cpu_insn_pc = addr;
56366e63ce3Schristos cpu->cpu_regs.pc = addr;
56466e63ce3Schristos cpu->cpu_regs.ccr = M6811_X_BIT | M6811_I_BIT | M6811_S_BIT;
56566e63ce3Schristos cpu->cpu_absolute_cycle = 0;
56666e63ce3Schristos cpu->cpu_is_initialized = 1;
56766e63ce3Schristos cpu->cpu_current_cycle = 0;
56866e63ce3Schristos
56966e63ce3Schristos cpu_call (cpu, addr);
57066e63ce3Schristos
57166e63ce3Schristos return 0;
57266e63ce3Schristos }
57366e63ce3Schristos
57466e63ce3Schristos void
print_io_reg_desc(SIM_DESC sd,io_reg_desc * desc,int val,int mode)57566e63ce3Schristos print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
57666e63ce3Schristos {
57766e63ce3Schristos while (desc->mask)
57866e63ce3Schristos {
57966e63ce3Schristos if (val & desc->mask)
58066e63ce3Schristos sim_io_printf (sd, "%s",
58166e63ce3Schristos mode == 0 ? desc->short_name : desc->long_name);
58266e63ce3Schristos desc++;
58366e63ce3Schristos }
58466e63ce3Schristos }
58566e63ce3Schristos
58666e63ce3Schristos void
print_io_byte(SIM_DESC sd,const char * name,io_reg_desc * desc,uint8 val,uint16 addr)58766e63ce3Schristos print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
58866e63ce3Schristos uint8 val, uint16 addr)
58966e63ce3Schristos {
59066e63ce3Schristos sim_io_printf (sd, " %-9.9s @ 0x%04x 0x%02x ", name, addr, val);
59166e63ce3Schristos if (desc)
59266e63ce3Schristos print_io_reg_desc (sd, desc, val, 0);
59366e63ce3Schristos }
59466e63ce3Schristos
59566e63ce3Schristos void
print_io_word(SIM_DESC sd,const char * name,io_reg_desc * desc,uint16 val,uint16 addr)59666e63ce3Schristos print_io_word (SIM_DESC sd, const char *name, io_reg_desc *desc,
59766e63ce3Schristos uint16 val, uint16 addr)
59866e63ce3Schristos {
59966e63ce3Schristos sim_io_printf (sd, " %-9.9s @ 0x%04x 0x%04x ", name, addr, val);
60066e63ce3Schristos if (desc)
60166e63ce3Schristos print_io_reg_desc (sd, desc, val, 0);
60266e63ce3Schristos }
60366e63ce3Schristos
60466e63ce3Schristos void
cpu_ccr_update_tst8(sim_cpu * cpu,uint8 val)6051c468f90Schristos cpu_ccr_update_tst8 (sim_cpu *cpu, uint8 val)
60666e63ce3Schristos {
6071c468f90Schristos cpu_set_ccr_V (cpu, 0);
6081c468f90Schristos cpu_set_ccr_N (cpu, val & 0x80 ? 1 : 0);
6091c468f90Schristos cpu_set_ccr_Z (cpu, val == 0 ? 1 : 0);
61066e63ce3Schristos }
61166e63ce3Schristos
61266e63ce3Schristos
61366e63ce3Schristos uint16
cpu_fetch_relbranch(sim_cpu * cpu)61466e63ce3Schristos cpu_fetch_relbranch (sim_cpu *cpu)
61566e63ce3Schristos {
61666e63ce3Schristos uint16 addr = (uint16) cpu_fetch8 (cpu);
61766e63ce3Schristos
61866e63ce3Schristos if (addr & 0x0080)
61966e63ce3Schristos {
62066e63ce3Schristos addr |= 0xFF00;
62166e63ce3Schristos }
62266e63ce3Schristos addr += cpu->cpu_regs.pc;
62366e63ce3Schristos return addr;
62466e63ce3Schristos }
62566e63ce3Schristos
62666e63ce3Schristos uint16
cpu_fetch_relbranch16(sim_cpu * cpu)62766e63ce3Schristos cpu_fetch_relbranch16 (sim_cpu *cpu)
62866e63ce3Schristos {
62966e63ce3Schristos uint16 addr = cpu_fetch16 (cpu);
63066e63ce3Schristos
63166e63ce3Schristos addr += cpu->cpu_regs.pc;
63266e63ce3Schristos return addr;
63366e63ce3Schristos }
63466e63ce3Schristos
63566e63ce3Schristos /* Push all the CPU registers (when an interruption occurs). */
63666e63ce3Schristos void
cpu_push_all(sim_cpu * cpu)63766e63ce3Schristos cpu_push_all (sim_cpu *cpu)
63866e63ce3Schristos {
63966e63ce3Schristos if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
64066e63ce3Schristos {
64166e63ce3Schristos cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.pc);
64266e63ce3Schristos cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.iy);
64366e63ce3Schristos cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.ix);
64466e63ce3Schristos cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.d);
64566e63ce3Schristos cpu_m68hc11_push_uint8 (cpu, cpu->cpu_regs.ccr);
64666e63ce3Schristos }
64766e63ce3Schristos else
64866e63ce3Schristos {
64966e63ce3Schristos cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.pc);
65066e63ce3Schristos cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.iy);
65166e63ce3Schristos cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.ix);
65266e63ce3Schristos cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.d);
65366e63ce3Schristos cpu_m68hc12_push_uint8 (cpu, cpu->cpu_regs.ccr);
65466e63ce3Schristos }
65566e63ce3Schristos }
65666e63ce3Schristos
65766e63ce3Schristos /* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations. */
65866e63ce3Schristos void
cpu_dbcc(sim_cpu * cpu)65966e63ce3Schristos cpu_dbcc (sim_cpu *cpu)
66066e63ce3Schristos {
66166e63ce3Schristos uint8 code;
66266e63ce3Schristos uint16 addr;
66366e63ce3Schristos uint16 inc;
66466e63ce3Schristos uint16 reg;
66566e63ce3Schristos
66666e63ce3Schristos code = cpu_fetch8 (cpu);
66766e63ce3Schristos switch (code & 0xc0)
66866e63ce3Schristos {
66966e63ce3Schristos case 0x80: /* ibcc */
67066e63ce3Schristos inc = 1;
67166e63ce3Schristos break;
67266e63ce3Schristos case 0x40: /* tbcc */
67366e63ce3Schristos inc = 0;
67466e63ce3Schristos break;
67566e63ce3Schristos case 0: /* dbcc */
67666e63ce3Schristos inc = -1;
67766e63ce3Schristos break;
67866e63ce3Schristos default:
67966e63ce3Schristos abort ();
68066e63ce3Schristos break;
68166e63ce3Schristos }
68266e63ce3Schristos
68366e63ce3Schristos addr = cpu_fetch8 (cpu);
68466e63ce3Schristos if (code & 0x10)
68566e63ce3Schristos addr |= 0xff00;
68666e63ce3Schristos
68766e63ce3Schristos addr += cpu_get_pc (cpu);
68866e63ce3Schristos reg = cpu_get_src_reg (cpu, code & 0x07);
68966e63ce3Schristos reg += inc;
69066e63ce3Schristos
69166e63ce3Schristos /* Branch according to register value. */
69266e63ce3Schristos if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
69366e63ce3Schristos {
69466e63ce3Schristos cpu_set_pc (cpu, addr);
69566e63ce3Schristos }
69666e63ce3Schristos cpu_set_dst_reg (cpu, code & 0x07, reg);
69766e63ce3Schristos }
69866e63ce3Schristos
69966e63ce3Schristos void
cpu_exg(sim_cpu * cpu,uint8 code)70066e63ce3Schristos cpu_exg (sim_cpu *cpu, uint8 code)
70166e63ce3Schristos {
70266e63ce3Schristos uint8 r1, r2;
70366e63ce3Schristos uint16 src1;
70466e63ce3Schristos uint16 src2;
70566e63ce3Schristos
70666e63ce3Schristos r1 = (code >> 4) & 0x07;
70766e63ce3Schristos r2 = code & 0x07;
70866e63ce3Schristos if (code & 0x80)
70966e63ce3Schristos {
71066e63ce3Schristos src1 = cpu_get_src_reg (cpu, r1);
71166e63ce3Schristos src2 = cpu_get_src_reg (cpu, r2);
71266e63ce3Schristos if (r2 == 1 || r2 == 2)
71366e63ce3Schristos src2 |= 0xff00;
71466e63ce3Schristos
71566e63ce3Schristos cpu_set_dst_reg (cpu, r2, src1);
71666e63ce3Schristos cpu_set_dst_reg (cpu, r1, src2);
71766e63ce3Schristos }
71866e63ce3Schristos else
71966e63ce3Schristos {
72066e63ce3Schristos src1 = cpu_get_src_reg (cpu, r1);
72166e63ce3Schristos
72266e63ce3Schristos /* Sign extend the 8-bit registers (A, B, CCR). */
72366e63ce3Schristos if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
72466e63ce3Schristos src1 |= 0xff00;
72566e63ce3Schristos
72666e63ce3Schristos cpu_set_dst_reg (cpu, r2, src1);
72766e63ce3Schristos }
72866e63ce3Schristos }
72966e63ce3Schristos
73066e63ce3Schristos /* Handle special instructions. */
73166e63ce3Schristos void
cpu_special(sim_cpu * cpu,enum M6811_Special special)73266e63ce3Schristos cpu_special (sim_cpu *cpu, enum M6811_Special special)
73366e63ce3Schristos {
73466e63ce3Schristos switch (special)
73566e63ce3Schristos {
73666e63ce3Schristos case M6811_RTI:
73766e63ce3Schristos {
73866e63ce3Schristos uint8 ccr;
73966e63ce3Schristos
74066e63ce3Schristos ccr = cpu_m68hc11_pop_uint8 (cpu);
74166e63ce3Schristos cpu_set_ccr (cpu, ccr);
74266e63ce3Schristos cpu_set_d (cpu, cpu_m68hc11_pop_uint16 (cpu));
74366e63ce3Schristos cpu_set_x (cpu, cpu_m68hc11_pop_uint16 (cpu));
74466e63ce3Schristos cpu_set_y (cpu, cpu_m68hc11_pop_uint16 (cpu));
74566e63ce3Schristos cpu_set_pc (cpu, cpu_m68hc11_pop_uint16 (cpu));
74666e63ce3Schristos cpu_return (cpu);
74766e63ce3Schristos break;
74866e63ce3Schristos }
74966e63ce3Schristos
75066e63ce3Schristos case M6812_RTI:
75166e63ce3Schristos {
75266e63ce3Schristos uint8 ccr;
75366e63ce3Schristos
75466e63ce3Schristos ccr = cpu_m68hc12_pop_uint8 (cpu);
75566e63ce3Schristos cpu_set_ccr (cpu, ccr);
75666e63ce3Schristos cpu_set_d (cpu, cpu_m68hc12_pop_uint16 (cpu));
75766e63ce3Schristos cpu_set_x (cpu, cpu_m68hc12_pop_uint16 (cpu));
75866e63ce3Schristos cpu_set_y (cpu, cpu_m68hc12_pop_uint16 (cpu));
75966e63ce3Schristos cpu_set_pc (cpu, cpu_m68hc12_pop_uint16 (cpu));
76066e63ce3Schristos cpu_return (cpu);
76166e63ce3Schristos break;
76266e63ce3Schristos }
76366e63ce3Schristos
76466e63ce3Schristos case M6811_WAI:
76566e63ce3Schristos /* In the ELF-start mode, we are in a special mode where
76666e63ce3Schristos the WAI corresponds to an exit. */
76766e63ce3Schristos if (cpu->cpu_use_elf_start)
76866e63ce3Schristos {
76966e63ce3Schristos cpu_set_pc (cpu, cpu->cpu_insn_pc);
77066e63ce3Schristos sim_engine_halt (CPU_STATE (cpu), cpu,
77166e63ce3Schristos NULL, NULL_CIA, sim_exited,
77266e63ce3Schristos cpu_get_d (cpu));
77366e63ce3Schristos return;
77466e63ce3Schristos }
77566e63ce3Schristos /* SCz: not correct... */
77666e63ce3Schristos cpu_push_all (cpu);
77766e63ce3Schristos break;
77866e63ce3Schristos
77966e63ce3Schristos case M6811_SWI:
78066e63ce3Schristos interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
78166e63ce3Schristos interrupts_process (&cpu->cpu_interrupts);
78266e63ce3Schristos break;
78366e63ce3Schristos
78466e63ce3Schristos case M6811_EMUL_SYSCALL:
78566e63ce3Schristos case M6811_ILLEGAL:
78666e63ce3Schristos if (cpu->cpu_emul_syscall)
78766e63ce3Schristos {
78866e63ce3Schristos uint8 op = memory_read8 (cpu,
78966e63ce3Schristos cpu_get_pc (cpu) - 1);
79066e63ce3Schristos if (op == 0x41)
79166e63ce3Schristos {
79266e63ce3Schristos cpu_set_pc (cpu, cpu->cpu_insn_pc);
79366e63ce3Schristos sim_engine_halt (CPU_STATE (cpu), cpu,
79466e63ce3Schristos NULL, NULL_CIA, sim_exited,
79566e63ce3Schristos cpu_get_d (cpu));
79666e63ce3Schristos return;
79766e63ce3Schristos }
79866e63ce3Schristos else
79966e63ce3Schristos {
80066e63ce3Schristos emul_os (op, cpu);
80166e63ce3Schristos }
80266e63ce3Schristos return;
80366e63ce3Schristos }
80466e63ce3Schristos
80566e63ce3Schristos interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
80666e63ce3Schristos interrupts_process (&cpu->cpu_interrupts);
80766e63ce3Schristos break;
80866e63ce3Schristos
80966e63ce3Schristos case M6811_TEST:
81066e63ce3Schristos case M6812_BGND:
81166e63ce3Schristos {
81266e63ce3Schristos SIM_DESC sd;
81366e63ce3Schristos
81466e63ce3Schristos sd = CPU_STATE (cpu);
81566e63ce3Schristos
81666e63ce3Schristos /* Breakpoint instruction if we are under gdb. */
81766e63ce3Schristos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
81866e63ce3Schristos {
81966e63ce3Schristos cpu->cpu_regs.pc --;
82066e63ce3Schristos sim_engine_halt (CPU_STATE (cpu), cpu,
82166e63ce3Schristos 0, cpu_get_pc (cpu), sim_stopped,
82266e63ce3Schristos SIM_SIGTRAP);
82366e63ce3Schristos }
82466e63ce3Schristos /* else this is a nop but not in test factory mode. */
82566e63ce3Schristos break;
82666e63ce3Schristos }
82766e63ce3Schristos
82866e63ce3Schristos case M6812_IDIVS:
82966e63ce3Schristos {
83066e63ce3Schristos int32 src1 = (int16) cpu_get_d (cpu);
83166e63ce3Schristos int32 src2 = (int16) cpu_get_x (cpu);
83266e63ce3Schristos
83366e63ce3Schristos if (src2 == 0)
83466e63ce3Schristos {
83566e63ce3Schristos cpu_set_ccr_C (cpu, 1);
83666e63ce3Schristos }
83766e63ce3Schristos else
83866e63ce3Schristos {
83966e63ce3Schristos cpu_set_d (cpu, src1 % src2);
84066e63ce3Schristos src1 = src1 / src2;
84166e63ce3Schristos cpu_set_x (cpu, src1);
84266e63ce3Schristos cpu_set_ccr_C (cpu, 0);
84366e63ce3Schristos cpu_set_ccr_Z (cpu, src1 == 0);
84466e63ce3Schristos cpu_set_ccr_N (cpu, src1 & 0x8000);
84566e63ce3Schristos cpu_set_ccr_V (cpu, src1 >= 32768 || src1 < -32768);
84666e63ce3Schristos }
84766e63ce3Schristos }
84866e63ce3Schristos break;
84966e63ce3Schristos
85066e63ce3Schristos case M6812_EDIV:
85166e63ce3Schristos {
85266e63ce3Schristos uint32 src1 = (uint32) cpu_get_x (cpu);
85366e63ce3Schristos uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
85466e63ce3Schristos | (uint32) (cpu_get_d (cpu));
85566e63ce3Schristos
85666e63ce3Schristos if (src1 == 0)
85766e63ce3Schristos {
85866e63ce3Schristos cpu_set_ccr_C (cpu, 1);
85966e63ce3Schristos }
86066e63ce3Schristos else
86166e63ce3Schristos {
86266e63ce3Schristos cpu_set_ccr_C (cpu, 0);
86366e63ce3Schristos cpu_set_d (cpu, src2 % src1);
86466e63ce3Schristos src2 = src2 / src1;
86566e63ce3Schristos cpu_set_y (cpu, src2);
86666e63ce3Schristos cpu_set_ccr_Z (cpu, src2 == 0);
86766e63ce3Schristos cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
86866e63ce3Schristos cpu_set_ccr_V (cpu, (src2 & 0xffff0000) != 0);
86966e63ce3Schristos }
87066e63ce3Schristos }
87166e63ce3Schristos break;
87266e63ce3Schristos
87366e63ce3Schristos case M6812_EDIVS:
87466e63ce3Schristos {
87566e63ce3Schristos int32 src1 = (int16) cpu_get_x (cpu);
87666e63ce3Schristos int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
87766e63ce3Schristos | (uint32) (cpu_get_d (cpu));
87866e63ce3Schristos
87966e63ce3Schristos if (src1 == 0)
88066e63ce3Schristos {
88166e63ce3Schristos cpu_set_ccr_C (cpu, 1);
88266e63ce3Schristos }
88366e63ce3Schristos else
88466e63ce3Schristos {
88566e63ce3Schristos cpu_set_ccr_C (cpu, 0);
88666e63ce3Schristos cpu_set_d (cpu, src2 % src1);
88766e63ce3Schristos src2 = src2 / src1;
88866e63ce3Schristos cpu_set_y (cpu, src2);
88966e63ce3Schristos cpu_set_ccr_Z (cpu, src2 == 0);
89066e63ce3Schristos cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
89166e63ce3Schristos cpu_set_ccr_V (cpu, src2 > 32767 || src2 < -32768);
89266e63ce3Schristos }
89366e63ce3Schristos }
89466e63ce3Schristos break;
89566e63ce3Schristos
89666e63ce3Schristos case M6812_EMULS:
89766e63ce3Schristos {
89866e63ce3Schristos int32 src1, src2;
89966e63ce3Schristos
90066e63ce3Schristos src1 = (int16) cpu_get_d (cpu);
90166e63ce3Schristos src2 = (int16) cpu_get_y (cpu);
90266e63ce3Schristos src1 = src1 * src2;
90366e63ce3Schristos cpu_set_d (cpu, src1 & 0x0ffff);
90466e63ce3Schristos cpu_set_y (cpu, src1 >> 16);
90566e63ce3Schristos cpu_set_ccr_Z (cpu, src1 == 0);
90666e63ce3Schristos cpu_set_ccr_N (cpu, (src1 & 0x80000000) != 0);
90766e63ce3Schristos cpu_set_ccr_C (cpu, (src1 & 0x00008000) != 0);
90866e63ce3Schristos }
90966e63ce3Schristos break;
91066e63ce3Schristos
91166e63ce3Schristos case M6812_EMACS:
91266e63ce3Schristos {
91366e63ce3Schristos int32 src1, src2;
91466e63ce3Schristos uint16 addr;
91566e63ce3Schristos
91666e63ce3Schristos addr = cpu_fetch16 (cpu);
91766e63ce3Schristos src1 = (int16) memory_read16 (cpu, cpu_get_x (cpu));
91866e63ce3Schristos src2 = (int16) memory_read16 (cpu, cpu_get_y (cpu));
91966e63ce3Schristos src1 = src1 * src2;
92066e63ce3Schristos src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
92166e63ce3Schristos | (uint32) memory_read16 (cpu, addr + 2);
92266e63ce3Schristos
92366e63ce3Schristos memory_write16 (cpu, addr, (src1 + src2) >> 16);
92466e63ce3Schristos memory_write16 (cpu, addr + 2, (src1 + src2));
92566e63ce3Schristos
92666e63ce3Schristos
92766e63ce3Schristos }
92866e63ce3Schristos break;
92966e63ce3Schristos
93066e63ce3Schristos case M6812_CALL:
93166e63ce3Schristos {
93266e63ce3Schristos uint8 page;
93366e63ce3Schristos uint16 addr;
93466e63ce3Schristos
93566e63ce3Schristos addr = cpu_fetch16 (cpu);
93666e63ce3Schristos page = cpu_fetch8 (cpu);
93766e63ce3Schristos
93866e63ce3Schristos cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
93966e63ce3Schristos cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
94066e63ce3Schristos
94166e63ce3Schristos cpu_set_page (cpu, page);
94266e63ce3Schristos cpu_set_pc (cpu, addr);
94366e63ce3Schristos }
94466e63ce3Schristos break;
94566e63ce3Schristos
94666e63ce3Schristos case M6812_CALL_INDIRECT:
94766e63ce3Schristos {
94866e63ce3Schristos uint8 code;
94966e63ce3Schristos uint16 addr;
95066e63ce3Schristos uint8 page;
95166e63ce3Schristos
95266e63ce3Schristos code = memory_read8 (cpu, cpu_get_pc (cpu));
95366e63ce3Schristos /* Indirect addressing call has the page specified in the
95466e63ce3Schristos memory location pointed to by the address. */
95566e63ce3Schristos if ((code & 0xE3) == 0xE3)
95666e63ce3Schristos {
95766e63ce3Schristos addr = cpu_get_indexed_operand_addr (cpu, 0);
95866e63ce3Schristos page = memory_read8 (cpu, addr + 2);
95966e63ce3Schristos addr = memory_read16 (cpu, addr);
96066e63ce3Schristos }
96166e63ce3Schristos else
96266e63ce3Schristos {
96366e63ce3Schristos /* Otherwise, page is in the opcode. */
96466e63ce3Schristos addr = cpu_get_indexed_operand16 (cpu, 0);
96566e63ce3Schristos page = cpu_fetch8 (cpu);
96666e63ce3Schristos }
96766e63ce3Schristos cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
96866e63ce3Schristos cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
96966e63ce3Schristos cpu_set_page (cpu, page);
97066e63ce3Schristos cpu_set_pc (cpu, addr);
97166e63ce3Schristos }
97266e63ce3Schristos break;
97366e63ce3Schristos
97466e63ce3Schristos case M6812_RTC:
97566e63ce3Schristos {
97666e63ce3Schristos uint8 page = cpu_m68hc12_pop_uint8 (cpu);
97766e63ce3Schristos uint16 addr = cpu_m68hc12_pop_uint16 (cpu);
97866e63ce3Schristos
97966e63ce3Schristos cpu_set_page (cpu, page);
98066e63ce3Schristos cpu_set_pc (cpu, addr);
98166e63ce3Schristos }
98266e63ce3Schristos break;
98366e63ce3Schristos
98466e63ce3Schristos case M6812_ETBL:
98566e63ce3Schristos default:
98666e63ce3Schristos sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
98766e63ce3Schristos cpu_get_pc (cpu), sim_stopped,
98866e63ce3Schristos SIM_SIGILL);
98966e63ce3Schristos break;
99066e63ce3Schristos }
99166e63ce3Schristos }
99266e63ce3Schristos
99366e63ce3Schristos
99466e63ce3Schristos void
cpu_single_step(sim_cpu * cpu)99566e63ce3Schristos cpu_single_step (sim_cpu *cpu)
99666e63ce3Schristos {
99766e63ce3Schristos cpu->cpu_current_cycle = 0;
99866e63ce3Schristos cpu->cpu_insn_pc = cpu_get_pc (cpu);
99966e63ce3Schristos
100066e63ce3Schristos /* Handle the pending interrupts. If an interrupt is handled,
100166e63ce3Schristos treat this as an single step. */
100266e63ce3Schristos if (interrupts_process (&cpu->cpu_interrupts))
100366e63ce3Schristos {
100466e63ce3Schristos cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
100566e63ce3Schristos return;
100666e63ce3Schristos }
100766e63ce3Schristos
100866e63ce3Schristos /* printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
100966e63ce3Schristos cpu->cpu_interpretor (cpu);
101066e63ce3Schristos cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
101166e63ce3Schristos }
101266e63ce3Schristos
101366e63ce3Schristos /* VARARGS */
101466e63ce3Schristos void
sim_memory_error(sim_cpu * cpu,SIM_SIGNAL excep,uint16 addr,const char * message,...)101566e63ce3Schristos sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
101666e63ce3Schristos uint16 addr, const char *message, ...)
101766e63ce3Schristos {
101866e63ce3Schristos char buf[1024];
101966e63ce3Schristos va_list args;
102066e63ce3Schristos
102166e63ce3Schristos va_start (args, message);
102266e63ce3Schristos vsprintf (buf, message, args);
102366e63ce3Schristos va_end (args);
102466e63ce3Schristos
102566e63ce3Schristos sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
102666e63ce3Schristos cpu_memory_exception (cpu, excep, addr, buf);
102766e63ce3Schristos }
102866e63ce3Schristos
102966e63ce3Schristos
103066e63ce3Schristos void
cpu_memory_exception(sim_cpu * cpu,SIM_SIGNAL excep,uint16 addr,const char * message)103166e63ce3Schristos cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
103266e63ce3Schristos uint16 addr, const char *message)
103366e63ce3Schristos {
103466e63ce3Schristos if (cpu->cpu_running == 0)
103566e63ce3Schristos return;
103666e63ce3Schristos
103766e63ce3Schristos cpu_set_pc (cpu, cpu->cpu_insn_pc);
103866e63ce3Schristos sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
103966e63ce3Schristos cpu_get_pc (cpu), sim_stopped, excep);
104066e63ce3Schristos
104166e63ce3Schristos #if 0
104266e63ce3Schristos cpu->mem_exception = excep;
104366e63ce3Schristos cpu->fault_addr = addr;
104466e63ce3Schristos cpu->fault_msg = strdup (message);
104566e63ce3Schristos
104666e63ce3Schristos if (cpu->cpu_use_handler)
104766e63ce3Schristos {
104866e63ce3Schristos longjmp (&cpu->cpu_exception_handler, 1);
104966e63ce3Schristos }
105066e63ce3Schristos (* cpu->callback->printf_filtered)
105166e63ce3Schristos (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
105266e63ce3Schristos #endif
105366e63ce3Schristos }
105466e63ce3Schristos
105566e63ce3Schristos void
cpu_info(SIM_DESC sd,sim_cpu * cpu)105666e63ce3Schristos cpu_info (SIM_DESC sd, sim_cpu *cpu)
105766e63ce3Schristos {
105866e63ce3Schristos sim_io_printf (sd, "CPU info:\n");
105966e63ce3Schristos sim_io_printf (sd, " Absolute cycle: %s\n",
106066e63ce3Schristos cycle_to_string (cpu, cpu->cpu_absolute_cycle,
106166e63ce3Schristos PRINT_TIME | PRINT_CYCLE));
106266e63ce3Schristos
106366e63ce3Schristos sim_io_printf (sd, " Syscall emulation: %s\n",
106466e63ce3Schristos cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
106566e63ce3Schristos sim_io_printf (sd, " Memory errors detection: %s\n",
106666e63ce3Schristos cpu->cpu_check_memory ? "yes" : "no");
106766e63ce3Schristos sim_io_printf (sd, " Stop on interrupt: %s\n",
106866e63ce3Schristos cpu->cpu_stop_on_interrupt ? "yes" : "no");
106966e63ce3Schristos }
107066e63ce3Schristos
1071