📄 archdescrip.cxx
字号:
/* * Copyright (C) 1998, 1999, 2001, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * 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, * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <assert.h>#include <string.h>#include <eros/target.h>#include <erosimg/ArchDescrip.hxx>#include <erosimg/ErosImage.hxx>#include <erosimg/Diag.hxx>#include <disk/DiskKey.hxx>/* NOTE: Having all of this information hard-coded into the program is * stupid. It should be read out of a file! It's easy enough to make * that change, but at the moment I don't have the time to do so. *//* All initialization values are viewed as strings expressed in human * readable hexadecimal. The string is padded on the right with 0's * to be the proper number of bytes for the register. It is then * converted to binary form. * * If the register is big endian, the value is simply copied in order. * * The current register description is not sufficient to deal with * bit-reversed registers. *//* BIG indicates that the register is big endian. The binary * formatted value must be reversed before copying into the number * key. * * LTL indicates that the register is little endian. The value should * be copied into the number key verbatim. * */#define REG(s) InternedString(#s)#define BIG(s) REG(s), true#define LTL(s) REG(s), false#define ARCH(s) InternedString(s)/* The 'RegLayout' structure describes where a register's value is * placed in the domain. Since a register value may be split across * multiple keys, we need to list all of the keys, the offset into the * keys' number value, the offset into the register value, and the * number of bytes to store. * * Most architectures have only one general registers annex. SPARC * may prove an exception, so I'm including a whichAnnex field. It's * easier to remove it (or ignore it) later than to backfill. * */struct RegLayout { InternedString arch; /* architecture name */ InternedString name; /* register name */ uint32_t annex; /* 0 == domain root, 14 == genKeys */ uint32_t slot; /* slot of key */ uint32_t slotOffset; /* offset in number key */ uint32_t valueOffset; /* offset in register value */ uint32_t len; /* bytes to copy */};#include "gen.RegisterDescriptions.cxx"static uint32_t nRegDescrip = sizeof(Registers) / sizeof(RegDescrip);static uint32_t nRegLayout = sizeof(Layout) / sizeof(RegLayout);RegDescrip *RegDescrip::Lookup(InternedString& arch, InternedString& regName){ for (uint32_t i = 0; i < nRegDescrip; i++) if (Registers[i].arch == arch && Registers[i].name == regName) return &Registers[i]; return 0;}boolRegDescrip::IsArchName(InternedString& arch){ for (uint32_t i = 0; i < nRegDescrip; i++) if (Registers[i].arch == arch) return true; return false;}static uint8_tMakeuint8_tFromHex(char xhi, char xlo){ uint8_t bhi = 0; uint8_t blo = 0; if (xhi >= 'A' && xhi <= 'F') bhi = (xhi - 'A' + 10); else if (xhi >= 'a' && xhi <= 'f') bhi = (xhi - 'a' + 10); else bhi = (xhi - '0'); bhi <<= 4; if (xlo >= 'A' && xlo <= 'F') blo = (xlo - 'A' + 10); else if (xlo >= 'a' && xlo <= 'f') blo = (xlo - 'a' + 10); else blo = (xlo - '0'); return bhi | blo;}static voidzero_extend_value(const char *value, char padded_value[RegDescrip::MaxRegSize*2]){ int valLen = strlen(value); for (int i = 0; i < RegDescrip::MaxRegSize*2; i++) padded_value[i] = '0'; char *offset_pos = &padded_value[RegDescrip::MaxRegSize * 2]; offset_pos -= valLen; for (int i = 0; i < valLen; i++) *offset_pos++ = value[i];}static voidconvert_to_binary(char padded_value[RegDescrip::MaxRegSize*2], uint8_t binary_value[RegDescrip::MaxRegSize], bool big_endian){ if (big_endian) { for (uint32_t i = 0; i < RegDescrip::MaxRegSize; i++) binary_value[i] = Makeuint8_tFromHex(padded_value[i*2], padded_value[i*2+1]); } else { uint32_t last_pos = RegDescrip::MaxRegSize - 1; for (uint32_t i = 0; i < RegDescrip::MaxRegSize; i++) binary_value[last_pos - i] = Makeuint8_tFromHex(padded_value[i*2], padded_value[i*2+1]); }}/* This is the heart of the architected register support. Given a key * to a domain root and a RegDescrip pointer, it updates the domain * according to the description specified by the relevant RegLayout * entries. * * The passed value should be a string of hexadecimal characters * beginning with "0x" with the most significant digit first * (i.e. written according to C/C++ input conventions). This routine * will craft the binary format according to the endian requirements * of the target architecture and write the value into the appropriate * slots. */voidRegDescrip::WriteValue(ErosImage& image, DiskKey& rootNodeKey, const InternedString& value){ const char *valStr = value.str(); if (valStr[0] != '0' || (valStr[1] != 'x' && valStr[1] != 'X')) Diag::fatal(5, "Invalid register value \"%s\" passed to WriteValue\n", valStr); char padded_value[MaxRegSize * 2]; uint8_t binary_buffer[MaxRegSize]; valStr += 2; zero_extend_value(valStr, padded_value); convert_to_binary(padded_value, binary_buffer, big_endian); uint8_t *binary_value = binary_buffer; /* If the register is big endian, it is now way over on the right of * the binary converted value. We need to find the proper start of * the value if it is smaller than that. */ if (big_endian) binary_value = &binary_buffer[MaxRegSize - len]; for (uint32_t i = 0; i < nRegLayout; i++) { if (Layout[i].arch != arch) continue; if (Layout[i].name != name) continue; DiskKey nodeKey = rootNodeKey; if (Layout[i].annex) nodeKey = image.GetNodeSlot(nodeKey, Layout[i].annex); DiskKey key = image.GetNodeSlot(nodeKey, Layout[i].slot); assert(key.GetType() == KT_Number && key.IsUnprepared()); uint8_t *numString = (uint8_t *) &key.nk.value[0]; numString += Layout[i].slotOffset; const uint8_t *valString = binary_value + Layout[i].valueOffset; for (uint32_t l = 0; l < Layout[i].len; l++) { numString[l] = valString[l]; } image.SetNodeSlot(nodeKey, Layout[i].slot, key); }}voidRegDescrip::InitProcess(ErosImage& ei, DiskKey& rootNodeKey, InternedString& arch){ unsigned int i; /* Put number keys in all the slots that need them. */ DiskKey zeroNumberKey = NumberKey(0);#if EROS_NODE_SIZE == 32 for (i = ProcFirstRootRegSlot; i <= ProcLastRootRegSlot; i++) ei.SetNodeSlot(rootNodeKey, i, zeroNumberKey);#else#error "Unsupported node size"#endif /* Loose end: If there are annexes, need to zero them. */ for (i = 0; i < nRegDescrip; i++) if (Registers[i].arch == arch) Registers[i].WriteValue(ei, rootNodeKey, Registers[i].dfltValue);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -