⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 archdescrip.cxx

📁 C++ 编写的EROS RTOS
💻 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 + -