📄 data.c
字号:
/* SPIM S20 MIPS simulator. Code to manipulate data segment directives. Copyright (C) 1990-2004 by James Larus (larus@cs.wisc.edu). ALL RIGHTS RESERVED. SPIM is distributed under the following conditions: You may make copies of SPIM for your own use and modify those copies. All copies of SPIM must retain my name and copyright notice. You may not sell SPIM or distributed SPIM in conjunction with a commerical product or service without the expressed written consent of James Larus. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *//* $Header: /Software/SPIM/src/data.c 12 11/27/04 8:55p Larus $*/#include "spim.h"#include "string-stream.h"#include "spim-utils.h"#include "inst.h"#include "reg.h"#include "mem.h"#include "sym-tbl.h"#include "parser.h"#include "run.h"#include "data.h"/* The first 64K of the data segment are dedicated to small data segment, which is pointed to by $gp. This register points to the middle of the segment, so we can use the full offset field in an instruction. */static mem_addr next_data_pc; /* Location for next datum in user process */static mem_addr next_k_data_pc; /* Location for next datum in kernel */static int in_kernel = 0; /* Non-zero => data goes to kdata, not data */#define DATA_PC (in_kernel ? next_k_data_pc : next_data_pc)#define BUMP_DATA_PC(DELTA) {if (in_kernel) \ next_k_data_pc += DELTA; \ else {next_data_pc += DELTA;}}static mem_addr next_gp_item_addr; /* Address of next item accessed off $gp */static int auto_alignment = 1; /* Non-zero => align literal to natural bound*//* If TO_KERNEL is non-zero, subsequent data will be placed in the kernel data segment. If it is zero, data will go to the user's data segment.*/voiduser_kernel_data_segment (int to_kernel){ in_kernel = to_kernel;}voidend_of_assembly_file (){ in_kernel = 0; auto_alignment = 1;}/* Set the point at which the first datum is stored to be ADDRESS + 64K. The 64K increment allocates an area pointed to by register $gp, which is initialized. */voiddata_begins_at_point (mem_addr addr){ if (bare_machine) next_data_pc = addr; else { next_gp_item_addr = addr; gp_midpoint = addr + 32*K; R[REG_GP] = gp_midpoint; next_data_pc = addr + 64 * K; }}/* Set the point at which the first datum is stored in the kernel's data segment. */voidk_data_begins_at_point (mem_addr addr){ next_k_data_pc = addr;}/* Arrange that the next datum is stored on a memory boundary with its low ALIGNMENT bits equal to 0. If argument is 0, disable automatic alignment.*/voidalign_data (int alignment){ if (alignment == 0) auto_alignment = 0; else if (in_kernel) { next_k_data_pc = (next_k_data_pc + (1 << alignment) - 1) & (-1 << alignment); fix_current_label_address (next_k_data_pc); } else { next_data_pc = (next_data_pc + (1 << alignment) - 1) & (-1 << alignment); fix_current_label_address (next_data_pc); }}voidset_data_alignment (int alignment){ if (auto_alignment) align_data (alignment);}voidenable_data_alignment (){ auto_alignment = 1;}/* Set the location (in user or kernel data space) for the next datum. */voidset_data_pc (mem_addr addr){ if (in_kernel) next_k_data_pc = addr; else next_data_pc = addr;}/* Return the address at which the next datum will be stored. */mem_addrcurrent_data_pc (){ return (DATA_PC);}/* Bump the address at which the next data will be stored by VALUE bytes. */voidincrement_data_pc (int value){ BUMP_DATA_PC (value);}/* Process a .extern NAME SIZE directive. */voidextern_directive (char *name, int size){ label *sym = make_label_global (name); if (!bare_machine && size > 0 && size <= SMALL_DATA_SEG_MAX_SIZE && next_gp_item_addr + size < gp_midpoint + 32*K) { sym->gp_flag = 1; sym->addr = next_gp_item_addr; next_gp_item_addr += size; }}/* Process a .lcomm NAME SIZE directive. */voidlcomm_directive (char *name, int size){ if (!bare_machine && size > 0 && size <= SMALL_DATA_SEG_MAX_SIZE && next_gp_item_addr + size < gp_midpoint + 32*K) { label *sym = record_label (name, next_gp_item_addr, 1); sym->gp_flag = 1; next_gp_item_addr += size; /* Don't need to initialize since memory starts with 0's */ } else { (void)record_label (name, next_data_pc, 1); for ( ; size > 0; size --) { set_mem_byte (DATA_PC, 0); BUMP_DATA_PC(1); } }}/* Process a .ascii STRING or .asciiz STRING directive. */voidstore_string (char *string, int length, int null_terminate){ for ( ; length > 0; string ++, length --) { set_mem_byte (DATA_PC, *string); BUMP_DATA_PC(1); } if (null_terminate) { set_mem_byte (DATA_PC, 0); BUMP_DATA_PC(1); }}/* Process a .byte EXPR directive. */voidstore_byte (int value){ set_mem_byte (DATA_PC, value); BUMP_DATA_PC (1);}/* Process a .half EXPR directive. */voidstore_half (int value){ if ((DATA_PC & 0x1) != 0) {#ifdef BIGENDIAN store_byte ((value >> 8) & 0xff); store_byte (value & 0xff);#else store_byte (value & 0xff); store_byte ((value >> 8) & 0xff);#endif } else { set_mem_half (DATA_PC, value); BUMP_DATA_PC (BYTES_PER_WORD / 2); }}/* Process a .word EXPR directive. */voidstore_word (int value){ if ((DATA_PC & 0x3) != 0) {#ifdef BIGENDIAN store_half ((value >> 16) & 0xffff); store_half (value & 0xffff);#else store_half (value & 0xffff); store_half ((value >> 16) & 0xffff);#endif } else { set_mem_word (DATA_PC, value); BUMP_DATA_PC (BYTES_PER_WORD); }}/* Process a .double EXPR directive. */voidstore_double (double *value){ if ((DATA_PC & 0x7) != 0) { store_word (* ((mem_word *) value)); store_word (* (((mem_word *) value) + 1)); } else { set_mem_word (DATA_PC, *((mem_word *) value)); BUMP_DATA_PC (BYTES_PER_WORD); set_mem_word (DATA_PC, *(((mem_word *) value) + 1)); BUMP_DATA_PC (BYTES_PER_WORD); }}/* Process a .float EXPR directive. */voidstore_float (double *value){ float val = (float)*value; float *vp = &val; if ((DATA_PC & 0x3) != 0) { store_half (*(mem_word *) vp & 0xffff); store_half ((*(mem_word *) vp >> 16) & 0xffff); } else { set_mem_word (DATA_PC, *((mem_word *) vp)); BUMP_DATA_PC (BYTES_PER_WORD); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -