📄 xmix_vm.c
字号:
/* ---------------------- xmix_vm.c : * Implementation of the functions declared in xmix_vm.h * ------------------------------------------------------------------ * Copyright (C) 2000 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */#include "xmix_vm.h"/* auxiliar functions */G_INLINE_FUNC mix_address_tget_M_(const mix_vm_t *vm, const mix_ins_t *ins);G_INLINE_FUNC mix_word_tget_V_(const mix_vm_t *vm, const mix_ins_t *ins);G_INLINE_FUNC mix_device_t *get_dev_ (mix_vm_t *vm, mix_fspec_t type);G_INLINE_FUNC mix_address_tget_M_(const mix_vm_t *vm, const mix_ins_t *ins){ if ( ins->index == 0 ) return ins->address; else return mix_short_add(ins->address, mix_word_to_short_fast(get_rI_(vm, ins->index)));}G_INLINE_FUNC mix_word_tget_V_(const mix_vm_t *vm, const mix_ins_t *ins){ return mix_word_get_field(ins->fspec, get_cell_(vm, get_M_(vm,ins)));}G_INLINE_FUNC mix_device_t *get_dev_ (mix_vm_t *vm, mix_fspec_t type) { if (type >= BD_NO_) return NULL; if (vm->devices[type] == NULL) vm->devices[type] = vm->factory (type); return vm->devices[type];}/* Instruction handlers */static gboolean nop_handler_(mix_vm_t *vm, const mix_ins_t *ins){ g_assert(ins->opcode == mix_opNOP); inc_loc_(vm); return TRUE;}static gboolean add_handler_(mix_vm_t *vm, const mix_ins_t *ins){ mix_word_t val = get_V_(vm, ins); g_assert(ins->opcode == mix_opADD || ins->opcode == mix_opSUB); if ( ins->opcode == mix_opSUB ) mix_word_reverse_sign(val); if ( mix_word_add_and_carry(get_rA_(vm), val, NULL, &get_rA_(vm)) ) set_over_(vm,TRUE); inc_loc_(vm); return TRUE;}static gboolean mul_handler_(mix_vm_t *vm, const mix_ins_t *ins){ g_assert(ins->opcode == mix_opMUL); mix_word_mul(get_rA_(vm), get_V_(vm,ins), &get_rA_(vm), &get_rX_(vm)); inc_loc_(vm); return TRUE;}static gboolean div_handler_(mix_vm_t *vm, const mix_ins_t *ins){ g_assert(ins->opcode == mix_opDIV); if ( mix_word_div(get_rA_(vm), get_rX_(vm), get_V_(vm,ins), &get_rA_(vm), &get_rX_(vm)) ) set_over_(vm,TRUE); inc_loc_(vm); return TRUE;}static gboolean spc_handler_(mix_vm_t *vm, const mix_ins_t *ins){ g_assert(ins->opcode == mix_opSPC); switch (mix_ins_id_from_ins(*ins)) { case mix_HLT: halt_(vm, TRUE); break; case mix_CHAR: { guint32 num = mix_word_magnitude(get_rA_(vm)); mix_char_t z = mix_ascii_to_char('0'); guint i; for (i = 5; 0 < i; --i, num /= 10) mix_word_set_byte(&get_rX_(vm), i, z + num % 10); for (i = 5; 0 < i; --i, num /= 10) mix_word_set_byte(&get_rA_(vm), i, z + num % 10); break; } case mix_NUM: { guint i; mix_word_t num = MIX_WORD_ZERO; mix_word_t ten = 10; for (i = 1; i <= 5; ++i) { mix_word_mul(ten, num, NULL, &num); mix_word_add_and_carry(num, mix_word_get_byte(get_rA_(vm),i)%10, NULL, &num); } for (i = 1; i <= 5; ++i) { mix_word_mul(ten, num, NULL, &num); mix_word_add_and_carry(num, mix_word_get_byte(get_rX_(vm),i)%10, NULL, &num); } set_rA_(vm, mix_word_is_negative(get_rA_(vm)) ? mix_word_negative(num):num); break; } default: return FALSE; } inc_loc_(vm); return TRUE;}static gboolean sla_handler_(mix_vm_t *vm, const mix_ins_t *ins){ mix_short_t n = get_M_(vm,ins); g_assert(ins->opcode == mix_opSLx); g_return_val_if_fail(mix_short_is_positive(n), FALSE); switch ( mix_ins_id_from_ins(*ins) ) { case mix_SLA: mix_word_shift_left(get_rA_(vm), MIX_WORD_ZERO, n, &get_rA_(vm), NULL); break; case mix_SRA: mix_word_shift_right(get_rA_(vm), MIX_WORD_ZERO, n, &get_rA_(vm), NULL); break; case mix_SLAX: mix_word_shift_left(get_rA_(vm), get_rX_(vm), n, &get_rA_(vm), &get_rX_(vm)); break; case mix_SRAX: mix_word_shift_right(get_rA_(vm), get_rX_(vm), n, &get_rA_(vm), &get_rX_(vm)); break; case mix_SLC: mix_word_shift_left_circular(get_rA_(vm), get_rX_(vm), n, &get_rA_(vm), &get_rX_(vm)); break; case mix_SRC: mix_word_shift_right_circular(get_rA_(vm), get_rX_(vm), n, &get_rA_(vm), &get_rX_(vm)); break; default: return FALSE; } inc_loc_(vm); return TRUE;}static gboolean mov_handler_(mix_vm_t *vm, const mix_ins_t *ins){ mix_short_t from = get_M_(vm,ins), to = mix_word_to_short_fast(get_rI_(vm,1)); guint k, delta = ins->fspec; g_assert(ins->opcode == mix_opMOVE); g_return_val_if_fail(mix_short_is_positive(from), FALSE); g_return_val_if_fail(mix_short_is_positive(to), FALSE); g_return_val_if_fail(MEMOK_(from + delta -1), FALSE); g_return_val_if_fail(MEMOK_(to + delta - 1), FALSE); for (k = 0; k < delta; ++k) set_cell_(vm, to+k, get_cell_(vm, from+k)); set_rI_(vm, 1, to+delta); inc_loc_(vm); return TRUE;}static gbooleanlda_handler_(mix_vm_t *vm, const mix_ins_t *ins){ gint r = 0; mix_word_t val; mix_ins_id_t id = mix_ins_id_from_ins(*ins); g_assert(id >= mix_LDA && id <= mix_LDXN); val = get_V_(vm, ins); if ( id > mix_LDX && mix_fspec_left(ins->fspec) == 0) mix_word_reverse_sign(val); if ( (id > mix_LDA && id < mix_LDX) || (id > mix_LDAN && id < mix_LDXN) ) /* Bytes 1-3 of I regs are always null */ val = mix_word_set_field(mix_fspec_new(1,3),MIX_WORD_ZERO,val); switch (id) { case mix_LDA: case mix_LDAN: r = A_; break; case mix_LDX: case mix_LDXN: r = X_; break; case mix_LD1: case mix_LD1N: r = I1_; break; case mix_LD2: case mix_LD2N: r = I2_; break; case mix_LD3: case mix_LD3N: r = I3_; break; case mix_LD4: case mix_LD4N: r = I4_; break; case mix_LD5: case mix_LD5N: r = I5_; break; case mix_LD6: case mix_LD6N: r = I6_; break; default: g_assert_not_reached(); } set_reg_(vm, r, val); inc_loc_(vm); return TRUE;}static gbooleansta_handler_(mix_vm_t *vm, const mix_ins_t *ins){ mix_address_t addr = get_M_(vm, ins); mix_ins_id_t id = mix_ins_id_from_ins(*ins); mix_word_t from; g_assert(id >= mix_STA && id <= mix_STZ); switch (id) { case mix_STA: from = get_rA_(vm); break; case mix_STX: from = get_rX_(vm); break; case mix_STJ: from = get_rJ_(vm); break; case mix_STZ: from = MIX_WORD_ZERO; break; default: from = get_rI_(vm, id - mix_ST1 + 1); break; } set_cell_(vm, addr, mix_word_store_field(ins->fspec, from, get_cell_(vm, addr))); inc_loc_(vm); return TRUE;}static gboolean jbs_handler_ (mix_vm_t *vm, const mix_ins_t *ins){ g_assert (ins->opcode == mix_opJBUS); g_return_val_if_fail (ins->fspec < BD_NO_, TRUE); g_return_val_if_fail (get_dev_ (vm, ins->fspec) != NULL, TRUE); if ( mix_device_busy (get_dev_ (vm, ins->fspec)) ) { set_rJ_(vm, get_loc_ (vm)); set_loc_ (vm, get_M_ (vm, ins)); } else inc_loc_ (vm); return TRUE;}static gboolean ioc_handler_(mix_vm_t *vm, const mix_ins_t *ins){ mix_address_t addr; mix_device_t *dev; gboolean result; g_assert(ins->opcode == mix_opIOC); addr = get_M_ (vm, ins); g_return_val_if_fail (ins->fspec < BD_NO_, TRUE); dev = get_dev_ (vm, ins->fspec); g_return_val_if_fail (dev != NULL, TRUE); result = mix_device_ioc (dev, addr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -