1 1.1 christos /* Simulator for the moxie processor 2 1.11 christos Copyright (C) 2008-2024 Free Software Foundation, Inc. 3 1.1 christos Contributed by Anthony Green 4 1.1 christos 5 1.1 christos This file is part of GDB, the GNU debugger. 6 1.1 christos 7 1.1 christos This program is free software; you can redistribute it and/or modify 8 1.1 christos it under the terms of the GNU General Public License as published by 9 1.1 christos the Free Software Foundation; either version 3 of the License, or 10 1.1 christos (at your option) any later version. 11 1.1 christos 12 1.1 christos This program is distributed in the hope that it will be useful, 13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 christos GNU General Public License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU General Public License 18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 1.1 christos 20 1.10 christos /* This must come before any other includes. */ 21 1.10 christos #include "defs.h" 22 1.10 christos 23 1.1 christos #include <fcntl.h> 24 1.1 christos #include <signal.h> 25 1.1 christos #include <stdlib.h> 26 1.5 christos #include <string.h> 27 1.1 christos #include <sys/param.h> 28 1.5 christos #include <unistd.h> 29 1.1 christos #include "bfd.h" 30 1.1 christos #include "libiberty.h" 31 1.10 christos #include "sim/sim.h" 32 1.1 christos 33 1.1 christos #include "sim-main.h" 34 1.1 christos #include "sim-base.h" 35 1.5 christos #include "sim-options.h" 36 1.9 christos #include "sim-io.h" 37 1.10 christos #include "sim-signal.h" 38 1.10 christos #include "target-newlib-syscall.h" 39 1.1 christos 40 1.11 christos #include "moxie-sim.h" 41 1.1 christos 42 1.1 christos /* Extract the signed 10-bit offset from a 16-bit branch 43 1.1 christos instruction. */ 44 1.1 christos #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1) 45 1.1 christos 46 1.1 christos #define EXTRACT_WORD(addr) \ 47 1.1 christos ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 24) \ 48 1.1 christos + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1) << 16) \ 49 1.1 christos + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+2) << 8) \ 50 1.1 christos + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+3))) 51 1.1 christos 52 1.3 christos #define EXTRACT_OFFSET(addr) \ 53 1.3 christos (unsigned int) \ 54 1.3 christos (((signed short) \ 55 1.3 christos ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 8) \ 56 1.3 christos + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1))) << 16) >> 16) 57 1.3 christos 58 1.5 christos static unsigned long 59 1.10 christos moxie_extract_unsigned_integer (const unsigned char *addr, int len) 60 1.1 christos { 61 1.1 christos unsigned long retval; 62 1.1 christos unsigned char * p; 63 1.1 christos unsigned char * startaddr = (unsigned char *)addr; 64 1.1 christos unsigned char * endaddr = startaddr + len; 65 1.1 christos 66 1.1 christos if (len > (int) sizeof (unsigned long)) 67 1.5 christos printf ("That operation is not available on integers of more than %zu bytes.", 68 1.1 christos sizeof (unsigned long)); 69 1.1 christos 70 1.1 christos /* Start at the most significant end of the integer, and work towards 71 1.1 christos the least significant. */ 72 1.1 christos retval = 0; 73 1.1 christos 74 1.1 christos for (p = endaddr; p > startaddr;) 75 1.1 christos retval = (retval << 8) | * -- p; 76 1.1 christos 77 1.1 christos return retval; 78 1.1 christos } 79 1.1 christos 80 1.5 christos static void 81 1.5 christos moxie_store_unsigned_integer (unsigned char *addr, int len, unsigned long val) 82 1.1 christos { 83 1.1 christos unsigned char * p; 84 1.1 christos unsigned char * startaddr = (unsigned char *)addr; 85 1.1 christos unsigned char * endaddr = startaddr + len; 86 1.1 christos 87 1.1 christos for (p = endaddr; p > startaddr;) 88 1.1 christos { 89 1.1 christos * -- p = val & 0xff; 90 1.1 christos val >>= 8; 91 1.1 christos } 92 1.1 christos } 93 1.1 christos 94 1.1 christos /* The machine state. 95 1.1 christos 96 1.1 christos This state is maintained in host byte order. The fetch/store 97 1.1 christos register functions must translate between host byte order and the 98 1.1 christos target processor byte order. Keeping this data in target byte 99 1.1 christos order simplifies the register read/write functions. Keeping this 100 1.1 christos data in native order improves the performance of the simulator. 101 1.1 christos Simulation speed is deemed more important. */ 102 1.1 christos 103 1.1 christos #define NUM_MOXIE_REGS 17 /* Including PC */ 104 1.1 christos #define NUM_MOXIE_SREGS 256 /* The special registers */ 105 1.1 christos #define PC_REGNO 16 106 1.1 christos 107 1.1 christos /* The ordering of the moxie_regset structure is matched in the 108 1.1 christos gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro. */ 109 1.5 christos /* TODO: This should be moved to sim-main.h:_sim_cpu. */ 110 1.1 christos struct moxie_regset 111 1.1 christos { 112 1.11 christos int32_t regs[NUM_MOXIE_REGS + 1]; /* primary registers */ 113 1.11 christos int32_t sregs[256]; /* special registers */ 114 1.11 christos int32_t cc; /* the condition code reg */ 115 1.1 christos unsigned long long insts; /* instruction counter */ 116 1.1 christos }; 117 1.1 christos 118 1.1 christos #define CC_GT 1<<0 119 1.1 christos #define CC_LT 1<<1 120 1.1 christos #define CC_EQ 1<<2 121 1.1 christos #define CC_GTU 1<<3 122 1.1 christos #define CC_LTU 1<<4 123 1.1 christos 124 1.11 christos /* TODO: This should be moved to sim-main.h:moxie_sim_cpu. */ 125 1.1 christos union 126 1.1 christos { 127 1.1 christos struct moxie_regset asregs; 128 1.11 christos int32_t asints [1]; /* but accessed larger... */ 129 1.1 christos } cpu; 130 1.1 christos 131 1.1 christos static void 132 1.5 christos set_initial_gprs (void) 133 1.1 christos { 134 1.1 christos int i; 135 1.1 christos 136 1.1 christos /* Set up machine just out of reset. */ 137 1.1 christos cpu.asregs.regs[PC_REGNO] = 0; 138 1.1 christos 139 1.1 christos /* Clean out the register contents. */ 140 1.1 christos for (i = 0; i < NUM_MOXIE_REGS; i++) 141 1.1 christos cpu.asregs.regs[i] = 0; 142 1.1 christos for (i = 0; i < NUM_MOXIE_SREGS; i++) 143 1.1 christos cpu.asregs.sregs[i] = 0; 144 1.1 christos } 145 1.1 christos 146 1.1 christos /* Write a 1 byte value to memory. */ 147 1.1 christos 148 1.5 christos static INLINE void 149 1.11 christos wbat (sim_cpu *scpu, int32_t pc, int32_t x, int32_t v) 150 1.1 christos { 151 1.5 christos address_word cia = CPU_PC_GET (scpu); 152 1.1 christos 153 1.1 christos sim_core_write_aligned_1 (scpu, cia, write_map, x, v); 154 1.1 christos } 155 1.1 christos 156 1.1 christos /* Write a 2 byte value to memory. */ 157 1.1 christos 158 1.5 christos static INLINE void 159 1.11 christos wsat (sim_cpu *scpu, int32_t pc, int32_t x, int32_t v) 160 1.1 christos { 161 1.5 christos address_word cia = CPU_PC_GET (scpu); 162 1.1 christos 163 1.1 christos sim_core_write_aligned_2 (scpu, cia, write_map, x, v); 164 1.1 christos } 165 1.1 christos 166 1.1 christos /* Write a 4 byte value to memory. */ 167 1.1 christos 168 1.5 christos static INLINE void 169 1.11 christos wlat (sim_cpu *scpu, int32_t pc, int32_t x, int32_t v) 170 1.1 christos { 171 1.5 christos address_word cia = CPU_PC_GET (scpu); 172 1.1 christos 173 1.1 christos sim_core_write_aligned_4 (scpu, cia, write_map, x, v); 174 1.1 christos } 175 1.1 christos 176 1.1 christos /* Read 2 bytes from memory. */ 177 1.1 christos 178 1.5 christos static INLINE int 179 1.11 christos rsat (sim_cpu *scpu, int32_t pc, int32_t x) 180 1.1 christos { 181 1.5 christos address_word cia = CPU_PC_GET (scpu); 182 1.1 christos 183 1.1 christos return (sim_core_read_aligned_2 (scpu, cia, read_map, x)); 184 1.1 christos } 185 1.1 christos 186 1.1 christos /* Read 1 byte from memory. */ 187 1.1 christos 188 1.5 christos static INLINE int 189 1.11 christos rbat (sim_cpu *scpu, int32_t pc, int32_t x) 190 1.1 christos { 191 1.5 christos address_word cia = CPU_PC_GET (scpu); 192 1.1 christos 193 1.1 christos return (sim_core_read_aligned_1 (scpu, cia, read_map, x)); 194 1.1 christos } 195 1.1 christos 196 1.1 christos /* Read 4 bytes from memory. */ 197 1.1 christos 198 1.5 christos static INLINE int 199 1.11 christos rlat (sim_cpu *scpu, int32_t pc, int32_t x) 200 1.1 christos { 201 1.5 christos address_word cia = CPU_PC_GET (scpu); 202 1.1 christos 203 1.1 christos return (sim_core_read_aligned_4 (scpu, cia, read_map, x)); 204 1.1 christos } 205 1.1 christos 206 1.1 christos #define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; } 207 1.1 christos 208 1.5 christos static unsigned int 209 1.1 christos convert_target_flags (unsigned int tflags) 210 1.1 christos { 211 1.1 christos unsigned int hflags = 0x0; 212 1.1 christos 213 1.1 christos CHECK_FLAG(0x0001, O_WRONLY); 214 1.1 christos CHECK_FLAG(0x0002, O_RDWR); 215 1.1 christos CHECK_FLAG(0x0008, O_APPEND); 216 1.1 christos CHECK_FLAG(0x0200, O_CREAT); 217 1.1 christos CHECK_FLAG(0x0400, O_TRUNC); 218 1.1 christos CHECK_FLAG(0x0800, O_EXCL); 219 1.1 christos CHECK_FLAG(0x2000, O_SYNC); 220 1.1 christos 221 1.1 christos if (tflags != 0x0) 222 1.1 christos fprintf (stderr, 223 1.1 christos "Simulator Error: problem converting target open flags for host. 0x%x\n", 224 1.1 christos tflags); 225 1.1 christos 226 1.1 christos return hflags; 227 1.1 christos } 228 1.1 christos 229 1.5 christos /* TODO: Split this up into finger trace levels than just insn. */ 230 1.5 christos #define MOXIE_TRACE_INSN(str) \ 231 1.5 christos TRACE_INSN (scpu, "0x%08x, %s, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", \ 232 1.5 christos opc, str, cpu.asregs.regs[0], cpu.asregs.regs[1], \ 233 1.5 christos cpu.asregs.regs[2], cpu.asregs.regs[3], cpu.asregs.regs[4], \ 234 1.5 christos cpu.asregs.regs[5], cpu.asregs.regs[6], cpu.asregs.regs[7], \ 235 1.5 christos cpu.asregs.regs[8], cpu.asregs.regs[9], cpu.asregs.regs[10], \ 236 1.5 christos cpu.asregs.regs[11], cpu.asregs.regs[12], cpu.asregs.regs[13], \ 237 1.5 christos cpu.asregs.regs[14], cpu.asregs.regs[15]) 238 1.1 christos 239 1.1 christos void 240 1.5 christos sim_engine_run (SIM_DESC sd, 241 1.5 christos int next_cpu_nr, /* ignore */ 242 1.5 christos int nr_cpus, /* ignore */ 243 1.5 christos int siggnal) /* ignore */ 244 1.1 christos { 245 1.11 christos int32_t pc, opc; 246 1.1 christos unsigned short inst; 247 1.1 christos sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */ 248 1.5 christos address_word cia = CPU_PC_GET (scpu); 249 1.1 christos 250 1.1 christos pc = cpu.asregs.regs[PC_REGNO]; 251 1.1 christos 252 1.1 christos /* Run instructions here. */ 253 1.1 christos do 254 1.1 christos { 255 1.1 christos opc = pc; 256 1.1 christos 257 1.1 christos /* Fetch the instruction at pc. */ 258 1.1 christos inst = (sim_core_read_aligned_1 (scpu, cia, read_map, pc) << 8) 259 1.1 christos + sim_core_read_aligned_1 (scpu, cia, read_map, pc+1); 260 1.1 christos 261 1.1 christos /* Decode instruction. */ 262 1.1 christos if (inst & (1 << 15)) 263 1.1 christos { 264 1.1 christos if (inst & (1 << 14)) 265 1.1 christos { 266 1.1 christos /* This is a Form 3 instruction. */ 267 1.1 christos int opcode = (inst >> 10 & 0xf); 268 1.1 christos 269 1.1 christos switch (opcode) 270 1.1 christos { 271 1.1 christos case 0x00: /* beq */ 272 1.1 christos { 273 1.5 christos MOXIE_TRACE_INSN ("beq"); 274 1.1 christos if (cpu.asregs.cc & CC_EQ) 275 1.1 christos pc += INST2OFFSET(inst); 276 1.1 christos } 277 1.1 christos break; 278 1.1 christos case 0x01: /* bne */ 279 1.1 christos { 280 1.5 christos MOXIE_TRACE_INSN ("bne"); 281 1.1 christos if (! (cpu.asregs.cc & CC_EQ)) 282 1.1 christos pc += INST2OFFSET(inst); 283 1.1 christos } 284 1.1 christos break; 285 1.1 christos case 0x02: /* blt */ 286 1.1 christos { 287 1.5 christos MOXIE_TRACE_INSN ("blt"); 288 1.1 christos if (cpu.asregs.cc & CC_LT) 289 1.1 christos pc += INST2OFFSET(inst); 290 1.1 christos } break; 291 1.1 christos case 0x03: /* bgt */ 292 1.1 christos { 293 1.5 christos MOXIE_TRACE_INSN ("bgt"); 294 1.1 christos if (cpu.asregs.cc & CC_GT) 295 1.1 christos pc += INST2OFFSET(inst); 296 1.1 christos } 297 1.1 christos break; 298 1.1 christos case 0x04: /* bltu */ 299 1.1 christos { 300 1.5 christos MOXIE_TRACE_INSN ("bltu"); 301 1.1 christos if (cpu.asregs.cc & CC_LTU) 302 1.1 christos pc += INST2OFFSET(inst); 303 1.1 christos } 304 1.1 christos break; 305 1.1 christos case 0x05: /* bgtu */ 306 1.1 christos { 307 1.5 christos MOXIE_TRACE_INSN ("bgtu"); 308 1.1 christos if (cpu.asregs.cc & CC_GTU) 309 1.1 christos pc += INST2OFFSET(inst); 310 1.1 christos } 311 1.1 christos break; 312 1.1 christos case 0x06: /* bge */ 313 1.1 christos { 314 1.5 christos MOXIE_TRACE_INSN ("bge"); 315 1.1 christos if (cpu.asregs.cc & (CC_GT | CC_EQ)) 316 1.1 christos pc += INST2OFFSET(inst); 317 1.1 christos } 318 1.1 christos break; 319 1.1 christos case 0x07: /* ble */ 320 1.1 christos { 321 1.5 christos MOXIE_TRACE_INSN ("ble"); 322 1.1 christos if (cpu.asregs.cc & (CC_LT | CC_EQ)) 323 1.1 christos pc += INST2OFFSET(inst); 324 1.1 christos } 325 1.1 christos break; 326 1.1 christos case 0x08: /* bgeu */ 327 1.1 christos { 328 1.5 christos MOXIE_TRACE_INSN ("bgeu"); 329 1.1 christos if (cpu.asregs.cc & (CC_GTU | CC_EQ)) 330 1.1 christos pc += INST2OFFSET(inst); 331 1.1 christos } 332 1.1 christos break; 333 1.1 christos case 0x09: /* bleu */ 334 1.1 christos { 335 1.5 christos MOXIE_TRACE_INSN ("bleu"); 336 1.1 christos if (cpu.asregs.cc & (CC_LTU | CC_EQ)) 337 1.1 christos pc += INST2OFFSET(inst); 338 1.1 christos } 339 1.1 christos break; 340 1.1 christos default: 341 1.1 christos { 342 1.5 christos MOXIE_TRACE_INSN ("SIGILL3"); 343 1.8 christos sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL); 344 1.1 christos break; 345 1.1 christos } 346 1.1 christos } 347 1.1 christos } 348 1.1 christos else 349 1.1 christos { 350 1.1 christos /* This is a Form 2 instruction. */ 351 1.1 christos int opcode = (inst >> 12 & 0x3); 352 1.1 christos switch (opcode) 353 1.1 christos { 354 1.1 christos case 0x00: /* inc */ 355 1.1 christos { 356 1.1 christos int a = (inst >> 8) & 0xf; 357 1.1 christos unsigned av = cpu.asregs.regs[a]; 358 1.1 christos unsigned v = (inst & 0xff); 359 1.3 christos 360 1.5 christos MOXIE_TRACE_INSN ("inc"); 361 1.1 christos cpu.asregs.regs[a] = av + v; 362 1.1 christos } 363 1.1 christos break; 364 1.1 christos case 0x01: /* dec */ 365 1.1 christos { 366 1.1 christos int a = (inst >> 8) & 0xf; 367 1.1 christos unsigned av = cpu.asregs.regs[a]; 368 1.1 christos unsigned v = (inst & 0xff); 369 1.3 christos 370 1.5 christos MOXIE_TRACE_INSN ("dec"); 371 1.1 christos cpu.asregs.regs[a] = av - v; 372 1.1 christos } 373 1.1 christos break; 374 1.1 christos case 0x02: /* gsr */ 375 1.1 christos { 376 1.1 christos int a = (inst >> 8) & 0xf; 377 1.1 christos unsigned v = (inst & 0xff); 378 1.3 christos 379 1.5 christos MOXIE_TRACE_INSN ("gsr"); 380 1.1 christos cpu.asregs.regs[a] = cpu.asregs.sregs[v]; 381 1.1 christos } 382 1.1 christos break; 383 1.1 christos case 0x03: /* ssr */ 384 1.1 christos { 385 1.1 christos int a = (inst >> 8) & 0xf; 386 1.1 christos unsigned v = (inst & 0xff); 387 1.3 christos 388 1.5 christos MOXIE_TRACE_INSN ("ssr"); 389 1.1 christos cpu.asregs.sregs[v] = cpu.asregs.regs[a]; 390 1.1 christos } 391 1.1 christos break; 392 1.1 christos default: 393 1.5 christos MOXIE_TRACE_INSN ("SIGILL2"); 394 1.8 christos sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL); 395 1.1 christos break; 396 1.1 christos } 397 1.1 christos } 398 1.1 christos } 399 1.1 christos else 400 1.1 christos { 401 1.1 christos /* This is a Form 1 instruction. */ 402 1.1 christos int opcode = inst >> 8; 403 1.1 christos switch (opcode) 404 1.1 christos { 405 1.1 christos case 0x00: /* bad */ 406 1.1 christos opc = opcode; 407 1.5 christos MOXIE_TRACE_INSN ("SIGILL0"); 408 1.8 christos sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL); 409 1.1 christos break; 410 1.1 christos case 0x01: /* ldi.l (immediate) */ 411 1.1 christos { 412 1.1 christos int reg = (inst >> 4) & 0xf; 413 1.5 christos unsigned int val = EXTRACT_WORD(pc+2); 414 1.3 christos 415 1.5 christos MOXIE_TRACE_INSN ("ldi.l"); 416 1.1 christos cpu.asregs.regs[reg] = val; 417 1.1 christos pc += 4; 418 1.1 christos } 419 1.1 christos break; 420 1.1 christos case 0x02: /* mov (register-to-register) */ 421 1.1 christos { 422 1.1 christos int dest = (inst >> 4) & 0xf; 423 1.1 christos int src = (inst ) & 0xf; 424 1.3 christos 425 1.5 christos MOXIE_TRACE_INSN ("mov"); 426 1.1 christos cpu.asregs.regs[dest] = cpu.asregs.regs[src]; 427 1.1 christos } 428 1.1 christos break; 429 1.1 christos case 0x03: /* jsra */ 430 1.1 christos { 431 1.1 christos unsigned int fn = EXTRACT_WORD(pc+2); 432 1.1 christos unsigned int sp = cpu.asregs.regs[1]; 433 1.3 christos 434 1.5 christos MOXIE_TRACE_INSN ("jsra"); 435 1.1 christos /* Save a slot for the static chain. */ 436 1.1 christos sp -= 4; 437 1.1 christos 438 1.1 christos /* Push the return address. */ 439 1.1 christos sp -= 4; 440 1.1 christos wlat (scpu, opc, sp, pc + 6); 441 1.1 christos 442 1.1 christos /* Push the current frame pointer. */ 443 1.1 christos sp -= 4; 444 1.1 christos wlat (scpu, opc, sp, cpu.asregs.regs[0]); 445 1.1 christos 446 1.1 christos /* Uncache the stack pointer and set the pc and $fp. */ 447 1.1 christos cpu.asregs.regs[1] = sp; 448 1.1 christos cpu.asregs.regs[0] = sp; 449 1.1 christos pc = fn - 2; 450 1.1 christos } 451 1.1 christos break; 452 1.1 christos case 0x04: /* ret */ 453 1.1 christos { 454 1.1 christos unsigned int sp = cpu.asregs.regs[0]; 455 1.1 christos 456 1.5 christos MOXIE_TRACE_INSN ("ret"); 457 1.1 christos 458 1.1 christos /* Pop the frame pointer. */ 459 1.1 christos cpu.asregs.regs[0] = rlat (scpu, opc, sp); 460 1.1 christos sp += 4; 461 1.1 christos 462 1.1 christos /* Pop the return address. */ 463 1.1 christos pc = rlat (scpu, opc, sp) - 2; 464 1.1 christos sp += 4; 465 1.1 christos 466 1.1 christos /* Skip over the static chain slot. */ 467 1.1 christos sp += 4; 468 1.1 christos 469 1.1 christos /* Uncache the stack pointer. */ 470 1.1 christos cpu.asregs.regs[1] = sp; 471 1.1 christos } 472 1.1 christos break; 473 1.1 christos case 0x05: /* add.l */ 474 1.1 christos { 475 1.1 christos int a = (inst >> 4) & 0xf; 476 1.1 christos int b = inst & 0xf; 477 1.1 christos unsigned av = cpu.asregs.regs[a]; 478 1.1 christos unsigned bv = cpu.asregs.regs[b]; 479 1.3 christos 480 1.5 christos MOXIE_TRACE_INSN ("add.l"); 481 1.1 christos cpu.asregs.regs[a] = av + bv; 482 1.1 christos } 483 1.1 christos break; 484 1.1 christos case 0x06: /* push */ 485 1.1 christos { 486 1.1 christos int a = (inst >> 4) & 0xf; 487 1.1 christos int b = inst & 0xf; 488 1.1 christos int sp = cpu.asregs.regs[a] - 4; 489 1.3 christos 490 1.5 christos MOXIE_TRACE_INSN ("push"); 491 1.1 christos wlat (scpu, opc, sp, cpu.asregs.regs[b]); 492 1.1 christos cpu.asregs.regs[a] = sp; 493 1.1 christos } 494 1.1 christos break; 495 1.1 christos case 0x07: /* pop */ 496 1.1 christos { 497 1.1 christos int a = (inst >> 4) & 0xf; 498 1.1 christos int b = inst & 0xf; 499 1.1 christos int sp = cpu.asregs.regs[a]; 500 1.3 christos 501 1.5 christos MOXIE_TRACE_INSN ("pop"); 502 1.1 christos cpu.asregs.regs[b] = rlat (scpu, opc, sp); 503 1.1 christos cpu.asregs.regs[a] = sp + 4; 504 1.1 christos } 505 1.1 christos break; 506 1.1 christos case 0x08: /* lda.l */ 507 1.1 christos { 508 1.1 christos int reg = (inst >> 4) & 0xf; 509 1.1 christos unsigned int addr = EXTRACT_WORD(pc+2); 510 1.3 christos 511 1.5 christos MOXIE_TRACE_INSN ("lda.l"); 512 1.1 christos cpu.asregs.regs[reg] = rlat (scpu, opc, addr); 513 1.1 christos pc += 4; 514 1.1 christos } 515 1.1 christos break; 516 1.1 christos case 0x09: /* sta.l */ 517 1.1 christos { 518 1.1 christos int reg = (inst >> 4) & 0xf; 519 1.1 christos unsigned int addr = EXTRACT_WORD(pc+2); 520 1.3 christos 521 1.5 christos MOXIE_TRACE_INSN ("sta.l"); 522 1.1 christos wlat (scpu, opc, addr, cpu.asregs.regs[reg]); 523 1.1 christos pc += 4; 524 1.1 christos } 525 1.1 christos break; 526 1.1 christos case 0x0a: /* ld.l (register indirect) */ 527 1.1 christos { 528 1.1 christos int src = inst & 0xf; 529 1.1 christos int dest = (inst >> 4) & 0xf; 530 1.1 christos int xv; 531 1.3 christos 532 1.5 christos MOXIE_TRACE_INSN ("ld.l"); 533 1.1 christos xv = cpu.asregs.regs[src]; 534 1.1 christos cpu.asregs.regs[dest] = rlat (scpu, opc, xv); 535 1.1 christos } 536 1.1 christos break; 537 1.1 christos case 0x0b: /* st.l */ 538 1.1 christos { 539 1.1 christos int dest = (inst >> 4) & 0xf; 540 1.1 christos int val = inst & 0xf; 541 1.3 christos 542 1.5 christos MOXIE_TRACE_INSN ("st.l"); 543 1.1 christos wlat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]); 544 1.1 christos } 545 1.1 christos break; 546 1.1 christos case 0x0c: /* ldo.l */ 547 1.1 christos { 548 1.3 christos unsigned int addr = EXTRACT_OFFSET(pc+2); 549 1.1 christos int a = (inst >> 4) & 0xf; 550 1.1 christos int b = inst & 0xf; 551 1.3 christos 552 1.5 christos MOXIE_TRACE_INSN ("ldo.l"); 553 1.1 christos addr += cpu.asregs.regs[b]; 554 1.1 christos cpu.asregs.regs[a] = rlat (scpu, opc, addr); 555 1.3 christos pc += 2; 556 1.1 christos } 557 1.1 christos break; 558 1.1 christos case 0x0d: /* sto.l */ 559 1.1 christos { 560 1.3 christos unsigned int addr = EXTRACT_OFFSET(pc+2); 561 1.1 christos int a = (inst >> 4) & 0xf; 562 1.1 christos int b = inst & 0xf; 563 1.3 christos 564 1.5 christos MOXIE_TRACE_INSN ("sto.l"); 565 1.1 christos addr += cpu.asregs.regs[a]; 566 1.1 christos wlat (scpu, opc, addr, cpu.asregs.regs[b]); 567 1.3 christos pc += 2; 568 1.1 christos } 569 1.1 christos break; 570 1.1 christos case 0x0e: /* cmp */ 571 1.1 christos { 572 1.1 christos int a = (inst >> 4) & 0xf; 573 1.1 christos int b = inst & 0xf; 574 1.1 christos int cc = 0; 575 1.1 christos int va = cpu.asregs.regs[a]; 576 1.1 christos int vb = cpu.asregs.regs[b]; 577 1.1 christos 578 1.5 christos MOXIE_TRACE_INSN ("cmp"); 579 1.1 christos if (va == vb) 580 1.1 christos cc = CC_EQ; 581 1.1 christos else 582 1.1 christos { 583 1.1 christos cc |= (va < vb ? CC_LT : 0); 584 1.1 christos cc |= (va > vb ? CC_GT : 0); 585 1.1 christos cc |= ((unsigned int) va < (unsigned int) vb ? CC_LTU : 0); 586 1.1 christos cc |= ((unsigned int) va > (unsigned int) vb ? CC_GTU : 0); 587 1.1 christos } 588 1.1 christos 589 1.1 christos cpu.asregs.cc = cc; 590 1.1 christos } 591 1.1 christos break; 592 1.1 christos case 0x0f: /* nop */ 593 1.1 christos break; 594 1.3 christos case 0x10: /* sex.b */ 595 1.3 christos { 596 1.3 christos int a = (inst >> 4) & 0xf; 597 1.3 christos int b = inst & 0xf; 598 1.3 christos signed char bv = cpu.asregs.regs[b]; 599 1.3 christos 600 1.5 christos MOXIE_TRACE_INSN ("sex.b"); 601 1.3 christos cpu.asregs.regs[a] = (int) bv; 602 1.3 christos } 603 1.3 christos break; 604 1.3 christos case 0x11: /* sex.s */ 605 1.3 christos { 606 1.3 christos int a = (inst >> 4) & 0xf; 607 1.3 christos int b = inst & 0xf; 608 1.3 christos signed short bv = cpu.asregs.regs[b]; 609 1.3 christos 610 1.5 christos MOXIE_TRACE_INSN ("sex.s"); 611 1.3 christos cpu.asregs.regs[a] = (int) bv; 612 1.3 christos } 613 1.3 christos break; 614 1.3 christos case 0x12: /* zex.b */ 615 1.3 christos { 616 1.3 christos int a = (inst >> 4) & 0xf; 617 1.3 christos int b = inst & 0xf; 618 1.3 christos signed char bv = cpu.asregs.regs[b]; 619 1.3 christos 620 1.5 christos MOXIE_TRACE_INSN ("zex.b"); 621 1.3 christos cpu.asregs.regs[a] = (int) bv & 0xff; 622 1.3 christos } 623 1.3 christos break; 624 1.3 christos case 0x13: /* zex.s */ 625 1.3 christos { 626 1.3 christos int a = (inst >> 4) & 0xf; 627 1.3 christos int b = inst & 0xf; 628 1.3 christos signed short bv = cpu.asregs.regs[b]; 629 1.3 christos 630 1.5 christos MOXIE_TRACE_INSN ("zex.s"); 631 1.3 christos cpu.asregs.regs[a] = (int) bv & 0xffff; 632 1.3 christos } 633 1.3 christos break; 634 1.3 christos case 0x14: /* umul.x */ 635 1.3 christos { 636 1.3 christos int a = (inst >> 4) & 0xf; 637 1.3 christos int b = inst & 0xf; 638 1.3 christos unsigned av = cpu.asregs.regs[a]; 639 1.3 christos unsigned bv = cpu.asregs.regs[b]; 640 1.3 christos unsigned long long r = 641 1.3 christos (unsigned long long) av * (unsigned long long) bv; 642 1.3 christos 643 1.5 christos MOXIE_TRACE_INSN ("umul.x"); 644 1.3 christos cpu.asregs.regs[a] = r >> 32; 645 1.3 christos } 646 1.3 christos break; 647 1.3 christos case 0x15: /* mul.x */ 648 1.3 christos { 649 1.3 christos int a = (inst >> 4) & 0xf; 650 1.3 christos int b = inst & 0xf; 651 1.3 christos unsigned av = cpu.asregs.regs[a]; 652 1.3 christos unsigned bv = cpu.asregs.regs[b]; 653 1.3 christos signed long long r = 654 1.3 christos (signed long long) av * (signed long long) bv; 655 1.3 christos 656 1.5 christos MOXIE_TRACE_INSN ("mul.x"); 657 1.3 christos cpu.asregs.regs[a] = r >> 32; 658 1.3 christos } 659 1.3 christos break; 660 1.1 christos case 0x16: /* bad */ 661 1.1 christos case 0x17: /* bad */ 662 1.1 christos case 0x18: /* bad */ 663 1.1 christos { 664 1.1 christos opc = opcode; 665 1.5 christos MOXIE_TRACE_INSN ("SIGILL0"); 666 1.8 christos sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL); 667 1.1 christos break; 668 1.1 christos } 669 1.1 christos case 0x19: /* jsr */ 670 1.1 christos { 671 1.1 christos unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf]; 672 1.1 christos unsigned int sp = cpu.asregs.regs[1]; 673 1.1 christos 674 1.5 christos MOXIE_TRACE_INSN ("jsr"); 675 1.1 christos 676 1.1 christos /* Save a slot for the static chain. */ 677 1.1 christos sp -= 4; 678 1.1 christos 679 1.1 christos /* Push the return address. */ 680 1.1 christos sp -= 4; 681 1.1 christos wlat (scpu, opc, sp, pc + 2); 682 1.1 christos 683 1.1 christos /* Push the current frame pointer. */ 684 1.1 christos sp -= 4; 685 1.1 christos wlat (scpu, opc, sp, cpu.asregs.regs[0]); 686 1.1 christos 687 1.1 christos /* Uncache the stack pointer and set the fp & pc. */ 688 1.1 christos cpu.asregs.regs[1] = sp; 689 1.1 christos cpu.asregs.regs[0] = sp; 690 1.1 christos pc = fn - 2; 691 1.1 christos } 692 1.1 christos break; 693 1.1 christos case 0x1a: /* jmpa */ 694 1.1 christos { 695 1.1 christos unsigned int tgt = EXTRACT_WORD(pc+2); 696 1.3 christos 697 1.5 christos MOXIE_TRACE_INSN ("jmpa"); 698 1.1 christos pc = tgt - 2; 699 1.1 christos } 700 1.1 christos break; 701 1.1 christos case 0x1b: /* ldi.b (immediate) */ 702 1.1 christos { 703 1.1 christos int reg = (inst >> 4) & 0xf; 704 1.3 christos unsigned int val = EXTRACT_WORD(pc+2); 705 1.1 christos 706 1.5 christos MOXIE_TRACE_INSN ("ldi.b"); 707 1.1 christos cpu.asregs.regs[reg] = val; 708 1.1 christos pc += 4; 709 1.1 christos } 710 1.1 christos break; 711 1.1 christos case 0x1c: /* ld.b (register indirect) */ 712 1.1 christos { 713 1.1 christos int src = inst & 0xf; 714 1.1 christos int dest = (inst >> 4) & 0xf; 715 1.1 christos int xv; 716 1.3 christos 717 1.5 christos MOXIE_TRACE_INSN ("ld.b"); 718 1.1 christos xv = cpu.asregs.regs[src]; 719 1.1 christos cpu.asregs.regs[dest] = rbat (scpu, opc, xv); 720 1.1 christos } 721 1.1 christos break; 722 1.1 christos case 0x1d: /* lda.b */ 723 1.1 christos { 724 1.1 christos int reg = (inst >> 4) & 0xf; 725 1.1 christos unsigned int addr = EXTRACT_WORD(pc+2); 726 1.3 christos 727 1.5 christos MOXIE_TRACE_INSN ("lda.b"); 728 1.1 christos cpu.asregs.regs[reg] = rbat (scpu, opc, addr); 729 1.1 christos pc += 4; 730 1.1 christos } 731 1.1 christos break; 732 1.1 christos case 0x1e: /* st.b */ 733 1.1 christos { 734 1.1 christos int dest = (inst >> 4) & 0xf; 735 1.1 christos int val = inst & 0xf; 736 1.3 christos 737 1.5 christos MOXIE_TRACE_INSN ("st.b"); 738 1.1 christos wbat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]); 739 1.1 christos } 740 1.1 christos break; 741 1.1 christos case 0x1f: /* sta.b */ 742 1.1 christos { 743 1.1 christos int reg = (inst >> 4) & 0xf; 744 1.1 christos unsigned int addr = EXTRACT_WORD(pc+2); 745 1.3 christos 746 1.5 christos MOXIE_TRACE_INSN ("sta.b"); 747 1.1 christos wbat (scpu, opc, addr, cpu.asregs.regs[reg]); 748 1.1 christos pc += 4; 749 1.1 christos } 750 1.1 christos break; 751 1.1 christos case 0x20: /* ldi.s (immediate) */ 752 1.1 christos { 753 1.1 christos int reg = (inst >> 4) & 0xf; 754 1.1 christos 755 1.1 christos unsigned int val = EXTRACT_WORD(pc+2); 756 1.3 christos 757 1.5 christos MOXIE_TRACE_INSN ("ldi.s"); 758 1.1 christos cpu.asregs.regs[reg] = val; 759 1.1 christos pc += 4; 760 1.1 christos } 761 1.1 christos break; 762 1.1 christos case 0x21: /* ld.s (register indirect) */ 763 1.1 christos { 764 1.1 christos int src = inst & 0xf; 765 1.1 christos int dest = (inst >> 4) & 0xf; 766 1.1 christos int xv; 767 1.3 christos 768 1.5 christos MOXIE_TRACE_INSN ("ld.s"); 769 1.1 christos xv = cpu.asregs.regs[src]; 770 1.1 christos cpu.asregs.regs[dest] = rsat (scpu, opc, xv); 771 1.1 christos } 772 1.1 christos break; 773 1.1 christos case 0x22: /* lda.s */ 774 1.1 christos { 775 1.1 christos int reg = (inst >> 4) & 0xf; 776 1.1 christos unsigned int addr = EXTRACT_WORD(pc+2); 777 1.3 christos 778 1.5 christos MOXIE_TRACE_INSN ("lda.s"); 779 1.1 christos cpu.asregs.regs[reg] = rsat (scpu, opc, addr); 780 1.1 christos pc += 4; 781 1.1 christos } 782 1.1 christos break; 783 1.1 christos case 0x23: /* st.s */ 784 1.1 christos { 785 1.1 christos int dest = (inst >> 4) & 0xf; 786 1.1 christos int val = inst & 0xf; 787 1.3 christos 788 1.5 christos MOXIE_TRACE_INSN ("st.s"); 789 1.1 christos wsat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]); 790 1.1 christos } 791 1.1 christos break; 792 1.1 christos case 0x24: /* sta.s */ 793 1.1 christos { 794 1.1 christos int reg = (inst >> 4) & 0xf; 795 1.1 christos unsigned int addr = EXTRACT_WORD(pc+2); 796 1.3 christos 797 1.5 christos MOXIE_TRACE_INSN ("sta.s"); 798 1.1 christos wsat (scpu, opc, addr, cpu.asregs.regs[reg]); 799 1.1 christos pc += 4; 800 1.1 christos } 801 1.1 christos break; 802 1.1 christos case 0x25: /* jmp */ 803 1.1 christos { 804 1.1 christos int reg = (inst >> 4) & 0xf; 805 1.3 christos 806 1.5 christos MOXIE_TRACE_INSN ("jmp"); 807 1.1 christos pc = cpu.asregs.regs[reg] - 2; 808 1.1 christos } 809 1.1 christos break; 810 1.1 christos case 0x26: /* and */ 811 1.1 christos { 812 1.1 christos int a = (inst >> 4) & 0xf; 813 1.1 christos int b = inst & 0xf; 814 1.1 christos int av, bv; 815 1.3 christos 816 1.5 christos MOXIE_TRACE_INSN ("and"); 817 1.1 christos av = cpu.asregs.regs[a]; 818 1.1 christos bv = cpu.asregs.regs[b]; 819 1.1 christos cpu.asregs.regs[a] = av & bv; 820 1.1 christos } 821 1.1 christos break; 822 1.1 christos case 0x27: /* lshr */ 823 1.1 christos { 824 1.1 christos int a = (inst >> 4) & 0xf; 825 1.1 christos int b = inst & 0xf; 826 1.1 christos int av = cpu.asregs.regs[a]; 827 1.1 christos int bv = cpu.asregs.regs[b]; 828 1.3 christos 829 1.5 christos MOXIE_TRACE_INSN ("lshr"); 830 1.1 christos cpu.asregs.regs[a] = (unsigned) ((unsigned) av >> bv); 831 1.1 christos } 832 1.1 christos break; 833 1.1 christos case 0x28: /* ashl */ 834 1.1 christos { 835 1.1 christos int a = (inst >> 4) & 0xf; 836 1.1 christos int b = inst & 0xf; 837 1.1 christos int av = cpu.asregs.regs[a]; 838 1.1 christos int bv = cpu.asregs.regs[b]; 839 1.3 christos 840 1.5 christos MOXIE_TRACE_INSN ("ashl"); 841 1.1 christos cpu.asregs.regs[a] = av << bv; 842 1.1 christos } 843 1.1 christos break; 844 1.1 christos case 0x29: /* sub.l */ 845 1.1 christos { 846 1.1 christos int a = (inst >> 4) & 0xf; 847 1.1 christos int b = inst & 0xf; 848 1.1 christos unsigned av = cpu.asregs.regs[a]; 849 1.1 christos unsigned bv = cpu.asregs.regs[b]; 850 1.3 christos 851 1.5 christos MOXIE_TRACE_INSN ("sub.l"); 852 1.1 christos cpu.asregs.regs[a] = av - bv; 853 1.1 christos } 854 1.1 christos break; 855 1.1 christos case 0x2a: /* neg */ 856 1.1 christos { 857 1.1 christos int a = (inst >> 4) & 0xf; 858 1.1 christos int b = inst & 0xf; 859 1.1 christos int bv = cpu.asregs.regs[b]; 860 1.3 christos 861 1.5 christos MOXIE_TRACE_INSN ("neg"); 862 1.1 christos cpu.asregs.regs[a] = - bv; 863 1.1 christos } 864 1.1 christos break; 865 1.1 christos case 0x2b: /* or */ 866 1.1 christos { 867 1.1 christos int a = (inst >> 4) & 0xf; 868 1.1 christos int b = inst & 0xf; 869 1.1 christos int av, bv; 870 1.3 christos 871 1.5 christos MOXIE_TRACE_INSN ("or"); 872 1.1 christos av = cpu.asregs.regs[a]; 873 1.1 christos bv = cpu.asregs.regs[b]; 874 1.1 christos cpu.asregs.regs[a] = av | bv; 875 1.1 christos } 876 1.1 christos break; 877 1.1 christos case 0x2c: /* not */ 878 1.1 christos { 879 1.1 christos int a = (inst >> 4) & 0xf; 880 1.1 christos int b = inst & 0xf; 881 1.1 christos int bv = cpu.asregs.regs[b]; 882 1.3 christos 883 1.5 christos MOXIE_TRACE_INSN ("not"); 884 1.1 christos cpu.asregs.regs[a] = 0xffffffff ^ bv; 885 1.1 christos } 886 1.1 christos break; 887 1.1 christos case 0x2d: /* ashr */ 888 1.1 christos { 889 1.1 christos int a = (inst >> 4) & 0xf; 890 1.1 christos int b = inst & 0xf; 891 1.1 christos int av = cpu.asregs.regs[a]; 892 1.1 christos int bv = cpu.asregs.regs[b]; 893 1.3 christos 894 1.5 christos MOXIE_TRACE_INSN ("ashr"); 895 1.1 christos cpu.asregs.regs[a] = av >> bv; 896 1.1 christos } 897 1.1 christos break; 898 1.1 christos case 0x2e: /* xor */ 899 1.1 christos { 900 1.1 christos int a = (inst >> 4) & 0xf; 901 1.1 christos int b = inst & 0xf; 902 1.1 christos int av, bv; 903 1.3 christos 904 1.5 christos MOXIE_TRACE_INSN ("xor"); 905 1.1 christos av = cpu.asregs.regs[a]; 906 1.1 christos bv = cpu.asregs.regs[b]; 907 1.1 christos cpu.asregs.regs[a] = av ^ bv; 908 1.1 christos } 909 1.1 christos break; 910 1.1 christos case 0x2f: /* mul.l */ 911 1.1 christos { 912 1.1 christos int a = (inst >> 4) & 0xf; 913 1.1 christos int b = inst & 0xf; 914 1.1 christos unsigned av = cpu.asregs.regs[a]; 915 1.1 christos unsigned bv = cpu.asregs.regs[b]; 916 1.3 christos 917 1.5 christos MOXIE_TRACE_INSN ("mul.l"); 918 1.1 christos cpu.asregs.regs[a] = av * bv; 919 1.1 christos } 920 1.1 christos break; 921 1.1 christos case 0x30: /* swi */ 922 1.1 christos { 923 1.1 christos unsigned int inum = EXTRACT_WORD(pc+2); 924 1.3 christos 925 1.5 christos MOXIE_TRACE_INSN ("swi"); 926 1.1 christos /* Set the special registers appropriately. */ 927 1.1 christos cpu.asregs.sregs[2] = 3; /* MOXIE_EX_SWI */ 928 1.1 christos cpu.asregs.sregs[3] = inum; 929 1.1 christos switch (inum) 930 1.1 christos { 931 1.10 christos case TARGET_NEWLIB_SYS_exit: 932 1.1 christos { 933 1.8 christos sim_engine_halt (sd, scpu, NULL, pc, sim_exited, 934 1.5 christos cpu.asregs.regs[2]); 935 1.1 christos break; 936 1.1 christos } 937 1.10 christos case TARGET_NEWLIB_SYS_open: 938 1.1 christos { 939 1.1 christos char fname[1024]; 940 1.1 christos int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]); 941 1.9 christos int fd; 942 1.1 christos sim_core_read_buffer (sd, scpu, read_map, fname, 943 1.1 christos cpu.asregs.regs[2], 1024); 944 1.9 christos fd = sim_io_open (sd, fname, mode); 945 1.1 christos /* FIXME - set errno */ 946 1.1 christos cpu.asregs.regs[2] = fd; 947 1.1 christos break; 948 1.1 christos } 949 1.10 christos case TARGET_NEWLIB_SYS_read: 950 1.1 christos { 951 1.1 christos int fd = cpu.asregs.regs[2]; 952 1.1 christos unsigned len = (unsigned) cpu.asregs.regs[4]; 953 1.1 christos char *buf = malloc (len); 954 1.9 christos cpu.asregs.regs[2] = sim_io_read (sd, fd, buf, len); 955 1.1 christos sim_core_write_buffer (sd, scpu, write_map, buf, 956 1.1 christos cpu.asregs.regs[3], len); 957 1.1 christos free (buf); 958 1.1 christos break; 959 1.1 christos } 960 1.10 christos case TARGET_NEWLIB_SYS_write: 961 1.1 christos { 962 1.1 christos char *str; 963 1.1 christos /* String length is at 0x12($fp) */ 964 1.1 christos unsigned count, len = (unsigned) cpu.asregs.regs[4]; 965 1.1 christos str = malloc (len); 966 1.1 christos sim_core_read_buffer (sd, scpu, read_map, str, 967 1.1 christos cpu.asregs.regs[3], len); 968 1.9 christos count = sim_io_write (sd, cpu.asregs.regs[2], str, len); 969 1.1 christos free (str); 970 1.1 christos cpu.asregs.regs[2] = count; 971 1.1 christos break; 972 1.1 christos } 973 1.10 christos case TARGET_NEWLIB_SYS_unlink: 974 1.9 christos { 975 1.9 christos char fname[1024]; 976 1.9 christos int fd; 977 1.9 christos sim_core_read_buffer (sd, scpu, read_map, fname, 978 1.9 christos cpu.asregs.regs[2], 1024); 979 1.9 christos fd = sim_io_unlink (sd, fname); 980 1.9 christos /* FIXME - set errno */ 981 1.9 christos cpu.asregs.regs[2] = fd; 982 1.9 christos break; 983 1.9 christos } 984 1.1 christos case 0xffffffff: /* Linux System Call */ 985 1.1 christos { 986 1.1 christos unsigned int handler = cpu.asregs.sregs[1]; 987 1.1 christos unsigned int sp = cpu.asregs.regs[1]; 988 1.1 christos 989 1.1 christos /* Save a slot for the static chain. */ 990 1.1 christos sp -= 4; 991 1.1 christos 992 1.1 christos /* Push the return address. */ 993 1.1 christos sp -= 4; 994 1.1 christos wlat (scpu, opc, sp, pc + 6); 995 1.1 christos 996 1.1 christos /* Push the current frame pointer. */ 997 1.1 christos sp -= 4; 998 1.1 christos wlat (scpu, opc, sp, cpu.asregs.regs[0]); 999 1.1 christos 1000 1.1 christos /* Uncache the stack pointer and set the fp & pc. */ 1001 1.1 christos cpu.asregs.regs[1] = sp; 1002 1.1 christos cpu.asregs.regs[0] = sp; 1003 1.1 christos pc = handler - 6; 1004 1.1 christos } 1005 1.1 christos default: 1006 1.1 christos break; 1007 1.1 christos } 1008 1.1 christos pc += 4; 1009 1.1 christos } 1010 1.1 christos break; 1011 1.1 christos case 0x31: /* div.l */ 1012 1.1 christos { 1013 1.1 christos int a = (inst >> 4) & 0xf; 1014 1.1 christos int b = inst & 0xf; 1015 1.1 christos int av = cpu.asregs.regs[a]; 1016 1.1 christos int bv = cpu.asregs.regs[b]; 1017 1.3 christos 1018 1.5 christos MOXIE_TRACE_INSN ("div.l"); 1019 1.1 christos cpu.asregs.regs[a] = av / bv; 1020 1.1 christos } 1021 1.1 christos break; 1022 1.1 christos case 0x32: /* udiv.l */ 1023 1.1 christos { 1024 1.1 christos int a = (inst >> 4) & 0xf; 1025 1.1 christos int b = inst & 0xf; 1026 1.1 christos unsigned int av = cpu.asregs.regs[a]; 1027 1.1 christos unsigned int bv = cpu.asregs.regs[b]; 1028 1.3 christos 1029 1.5 christos MOXIE_TRACE_INSN ("udiv.l"); 1030 1.1 christos cpu.asregs.regs[a] = (av / bv); 1031 1.1 christos } 1032 1.1 christos break; 1033 1.1 christos case 0x33: /* mod.l */ 1034 1.1 christos { 1035 1.1 christos int a = (inst >> 4) & 0xf; 1036 1.1 christos int b = inst & 0xf; 1037 1.1 christos int av = cpu.asregs.regs[a]; 1038 1.1 christos int bv = cpu.asregs.regs[b]; 1039 1.3 christos 1040 1.5 christos MOXIE_TRACE_INSN ("mod.l"); 1041 1.1 christos cpu.asregs.regs[a] = av % bv; 1042 1.1 christos } 1043 1.1 christos break; 1044 1.1 christos case 0x34: /* umod.l */ 1045 1.1 christos { 1046 1.1 christos int a = (inst >> 4) & 0xf; 1047 1.1 christos int b = inst & 0xf; 1048 1.1 christos unsigned int av = cpu.asregs.regs[a]; 1049 1.1 christos unsigned int bv = cpu.asregs.regs[b]; 1050 1.3 christos 1051 1.5 christos MOXIE_TRACE_INSN ("umod.l"); 1052 1.1 christos cpu.asregs.regs[a] = (av % bv); 1053 1.1 christos } 1054 1.1 christos break; 1055 1.1 christos case 0x35: /* brk */ 1056 1.5 christos MOXIE_TRACE_INSN ("brk"); 1057 1.8 christos sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGTRAP); 1058 1.1 christos pc -= 2; /* Adjust pc */ 1059 1.1 christos break; 1060 1.1 christos case 0x36: /* ldo.b */ 1061 1.1 christos { 1062 1.3 christos unsigned int addr = EXTRACT_OFFSET(pc+2); 1063 1.1 christos int a = (inst >> 4) & 0xf; 1064 1.1 christos int b = inst & 0xf; 1065 1.3 christos 1066 1.5 christos MOXIE_TRACE_INSN ("ldo.b"); 1067 1.1 christos addr += cpu.asregs.regs[b]; 1068 1.1 christos cpu.asregs.regs[a] = rbat (scpu, opc, addr); 1069 1.3 christos pc += 2; 1070 1.1 christos } 1071 1.1 christos break; 1072 1.1 christos case 0x37: /* sto.b */ 1073 1.1 christos { 1074 1.3 christos unsigned int addr = EXTRACT_OFFSET(pc+2); 1075 1.1 christos int a = (inst >> 4) & 0xf; 1076 1.1 christos int b = inst & 0xf; 1077 1.3 christos 1078 1.5 christos MOXIE_TRACE_INSN ("sto.b"); 1079 1.1 christos addr += cpu.asregs.regs[a]; 1080 1.1 christos wbat (scpu, opc, addr, cpu.asregs.regs[b]); 1081 1.3 christos pc += 2; 1082 1.1 christos } 1083 1.1 christos break; 1084 1.1 christos case 0x38: /* ldo.s */ 1085 1.1 christos { 1086 1.3 christos unsigned int addr = EXTRACT_OFFSET(pc+2); 1087 1.1 christos int a = (inst >> 4) & 0xf; 1088 1.1 christos int b = inst & 0xf; 1089 1.3 christos 1090 1.5 christos MOXIE_TRACE_INSN ("ldo.s"); 1091 1.1 christos addr += cpu.asregs.regs[b]; 1092 1.1 christos cpu.asregs.regs[a] = rsat (scpu, opc, addr); 1093 1.3 christos pc += 2; 1094 1.1 christos } 1095 1.1 christos break; 1096 1.1 christos case 0x39: /* sto.s */ 1097 1.1 christos { 1098 1.3 christos unsigned int addr = EXTRACT_OFFSET(pc+2); 1099 1.1 christos int a = (inst >> 4) & 0xf; 1100 1.1 christos int b = inst & 0xf; 1101 1.3 christos 1102 1.5 christos MOXIE_TRACE_INSN ("sto.s"); 1103 1.1 christos addr += cpu.asregs.regs[a]; 1104 1.1 christos wsat (scpu, opc, addr, cpu.asregs.regs[b]); 1105 1.3 christos pc += 2; 1106 1.1 christos } 1107 1.1 christos break; 1108 1.1 christos default: 1109 1.1 christos opc = opcode; 1110 1.5 christos MOXIE_TRACE_INSN ("SIGILL1"); 1111 1.8 christos sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL); 1112 1.1 christos break; 1113 1.1 christos } 1114 1.1 christos } 1115 1.1 christos 1116 1.5 christos cpu.asregs.insts++; 1117 1.1 christos pc += 2; 1118 1.5 christos cpu.asregs.regs[PC_REGNO] = pc; 1119 1.8 christos 1120 1.8 christos if (sim_events_tick (sd)) 1121 1.8 christos sim_events_process (sd); 1122 1.8 christos 1123 1.5 christos } while (1); 1124 1.1 christos } 1125 1.1 christos 1126 1.6 christos static int 1127 1.10 christos moxie_reg_store (SIM_CPU *scpu, int rn, const void *memory, int length) 1128 1.1 christos { 1129 1.1 christos if (rn < NUM_MOXIE_REGS && rn >= 0) 1130 1.1 christos { 1131 1.1 christos if (length == 4) 1132 1.1 christos { 1133 1.1 christos long ival; 1134 1.1 christos 1135 1.1 christos /* misalignment safe */ 1136 1.1 christos ival = moxie_extract_unsigned_integer (memory, 4); 1137 1.1 christos cpu.asints[rn] = ival; 1138 1.1 christos } 1139 1.1 christos 1140 1.1 christos return 4; 1141 1.1 christos } 1142 1.1 christos else 1143 1.1 christos return 0; 1144 1.1 christos } 1145 1.1 christos 1146 1.6 christos static int 1147 1.10 christos moxie_reg_fetch (SIM_CPU *scpu, int rn, void *memory, int length) 1148 1.1 christos { 1149 1.1 christos if (rn < NUM_MOXIE_REGS && rn >= 0) 1150 1.1 christos { 1151 1.1 christos if (length == 4) 1152 1.1 christos { 1153 1.1 christos long ival = cpu.asints[rn]; 1154 1.1 christos 1155 1.1 christos /* misalignment-safe */ 1156 1.1 christos moxie_store_unsigned_integer (memory, 4, ival); 1157 1.1 christos } 1158 1.1 christos 1159 1.1 christos return 4; 1160 1.1 christos } 1161 1.1 christos else 1162 1.1 christos return 0; 1163 1.1 christos } 1164 1.1 christos 1165 1.5 christos static sim_cia 1166 1.5 christos moxie_pc_get (sim_cpu *cpu) 1167 1.1 christos { 1168 1.11 christos return MOXIE_SIM_CPU (cpu)->registers[PCIDX]; 1169 1.1 christos } 1170 1.1 christos 1171 1.5 christos static void 1172 1.5 christos moxie_pc_set (sim_cpu *cpu, sim_cia pc) 1173 1.1 christos { 1174 1.11 christos MOXIE_SIM_CPU (cpu)->registers[PCIDX] = pc; 1175 1.1 christos } 1176 1.1 christos 1177 1.5 christos static void 1178 1.5 christos free_state (SIM_DESC sd) 1179 1.1 christos { 1180 1.5 christos if (STATE_MODULES (sd) != NULL) 1181 1.5 christos sim_module_uninstall (sd); 1182 1.5 christos sim_cpu_free_all (sd); 1183 1.5 christos sim_state_free (sd); 1184 1.1 christos } 1185 1.1 christos 1186 1.1 christos SIM_DESC 1187 1.6 christos sim_open (SIM_OPEN_KIND kind, host_callback *cb, 1188 1.6 christos struct bfd *abfd, char * const *argv) 1189 1.1 christos { 1190 1.5 christos int i; 1191 1.1 christos SIM_DESC sd = sim_state_alloc (kind, cb); 1192 1.1 christos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 1193 1.1 christos 1194 1.10 christos /* Set default options before parsing user options. */ 1195 1.10 christos current_target_byte_order = BFD_ENDIAN_BIG; 1196 1.10 christos 1197 1.5 christos /* The cpu data is kept in a separately allocated chunk of memory. */ 1198 1.11 christos if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct moxie_sim_cpu)) 1199 1.11 christos != SIM_RC_OK) 1200 1.5 christos { 1201 1.5 christos free_state (sd); 1202 1.5 christos return 0; 1203 1.5 christos } 1204 1.5 christos 1205 1.1 christos if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) 1206 1.5 christos { 1207 1.5 christos free_state (sd); 1208 1.5 christos return 0; 1209 1.5 christos } 1210 1.5 christos 1211 1.6 christos /* The parser will print an error message for us, so we silently return. */ 1212 1.5 christos if (sim_parse_args (sd, argv) != SIM_RC_OK) 1213 1.5 christos { 1214 1.5 christos free_state (sd); 1215 1.5 christos return 0; 1216 1.5 christos } 1217 1.1 christos 1218 1.1 christos sim_do_command(sd," memory region 0x00000000,0x4000000") ; 1219 1.1 christos sim_do_command(sd," memory region 0xE0000000,0x10000") ; 1220 1.1 christos 1221 1.5 christos /* Check for/establish the a reference program image. */ 1222 1.10 christos if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK) 1223 1.5 christos { 1224 1.5 christos free_state (sd); 1225 1.5 christos return 0; 1226 1.5 christos } 1227 1.5 christos 1228 1.1 christos /* Configure/verify the target byte order and other runtime 1229 1.1 christos configuration options. */ 1230 1.1 christos if (sim_config (sd) != SIM_RC_OK) 1231 1.1 christos { 1232 1.1 christos sim_module_uninstall (sd); 1233 1.1 christos return 0; 1234 1.1 christos } 1235 1.1 christos 1236 1.1 christos if (sim_post_argv_init (sd) != SIM_RC_OK) 1237 1.1 christos { 1238 1.1 christos /* Uninstall the modules to avoid memory leaks, 1239 1.1 christos file descriptor leaks, etc. */ 1240 1.1 christos sim_module_uninstall (sd); 1241 1.1 christos return 0; 1242 1.1 christos } 1243 1.1 christos 1244 1.5 christos /* CPU specific initialization. */ 1245 1.5 christos for (i = 0; i < MAX_NR_PROCESSORS; ++i) 1246 1.5 christos { 1247 1.5 christos SIM_CPU *cpu = STATE_CPU (sd, i); 1248 1.5 christos 1249 1.6 christos CPU_REG_FETCH (cpu) = moxie_reg_fetch; 1250 1.6 christos CPU_REG_STORE (cpu) = moxie_reg_store; 1251 1.5 christos CPU_PC_FETCH (cpu) = moxie_pc_get; 1252 1.5 christos CPU_PC_STORE (cpu) = moxie_pc_set; 1253 1.5 christos 1254 1.5 christos set_initial_gprs (); /* Reset the GPR registers. */ 1255 1.5 christos } 1256 1.5 christos 1257 1.1 christos return sd; 1258 1.1 christos } 1259 1.1 christos 1260 1.1 christos /* Load the device tree blob. */ 1261 1.1 christos 1262 1.1 christos static void 1263 1.1 christos load_dtb (SIM_DESC sd, const char *filename) 1264 1.1 christos { 1265 1.1 christos int size = 0; 1266 1.1 christos FILE *f = fopen (filename, "rb"); 1267 1.1 christos char *buf; 1268 1.1 christos sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */ 1269 1.5 christos 1270 1.5 christos /* Don't warn as the sim works fine w/out a device tree. */ 1271 1.5 christos if (f == NULL) 1272 1.5 christos return; 1273 1.1 christos fseek (f, 0, SEEK_END); 1274 1.1 christos size = ftell(f); 1275 1.1 christos fseek (f, 0, SEEK_SET); 1276 1.1 christos buf = alloca (size); 1277 1.1 christos if (size != fread (buf, 1, size, f)) 1278 1.1 christos { 1279 1.5 christos sim_io_eprintf (sd, "ERROR: error reading ``%s''.\n", filename); 1280 1.6 christos fclose (f); 1281 1.1 christos return; 1282 1.1 christos } 1283 1.1 christos sim_core_write_buffer (sd, scpu, write_map, buf, 0xE0000000, size); 1284 1.1 christos cpu.asregs.sregs[9] = 0xE0000000; 1285 1.1 christos fclose (f); 1286 1.1 christos } 1287 1.1 christos 1288 1.1 christos SIM_RC 1289 1.6 christos sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, 1290 1.6 christos char * const *argv, char * const *env) 1291 1.1 christos { 1292 1.10 christos char * const *avp; 1293 1.11 christos int argc, i, tp; 1294 1.1 christos sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */ 1295 1.1 christos 1296 1.1 christos if (prog_bfd != NULL) 1297 1.1 christos cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd); 1298 1.1 christos 1299 1.1 christos /* Copy args into target memory. */ 1300 1.1 christos avp = argv; 1301 1.1 christos for (argc = 0; avp && *avp; avp++) 1302 1.1 christos argc++; 1303 1.1 christos 1304 1.1 christos /* Target memory looks like this: 1305 1.1 christos 0x00000000 zero word 1306 1.1 christos 0x00000004 argc word 1307 1.1 christos 0x00000008 start of argv 1308 1.1 christos . 1309 1.1 christos 0x0000???? end of argv 1310 1.1 christos 0x0000???? zero word 1311 1.1 christos 0x0000???? start of data pointed to by argv */ 1312 1.1 christos 1313 1.1 christos wlat (scpu, 0, 0, 0); 1314 1.1 christos wlat (scpu, 0, 4, argc); 1315 1.1 christos 1316 1.1 christos /* tp is the offset of our first argv data. */ 1317 1.1 christos tp = 4 + 4 + argc * 4 + 4; 1318 1.1 christos 1319 1.1 christos for (i = 0; i < argc; i++) 1320 1.1 christos { 1321 1.1 christos /* Set the argv value. */ 1322 1.1 christos wlat (scpu, 0, 4 + 4 + i * 4, tp); 1323 1.1 christos 1324 1.1 christos /* Store the string. */ 1325 1.1 christos sim_core_write_buffer (sd, scpu, write_map, argv[i], 1326 1.1 christos tp, strlen(argv[i])+1); 1327 1.1 christos tp += strlen (argv[i]) + 1; 1328 1.1 christos } 1329 1.1 christos 1330 1.1 christos wlat (scpu, 0, 4 + 4 + i * 4, 0); 1331 1.1 christos 1332 1.1 christos load_dtb (sd, DTB); 1333 1.1 christos 1334 1.1 christos return SIM_RC_OK; 1335 1.1 christos } 1336