/[gxemul]/trunk/src/memory.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/memory.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 40 by dpavlin, Mon Oct 8 16:22:11 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: memory.c,v 1.202 2007/04/28 09:19:51 debug Exp $   *  $Id: memory.c,v 1.204 2007/06/15 17:02:38 debug Exp $
29   *   *
30   *  Functions for handling the memory of an emulated machine.   *  Functions for handling the memory of an emulated machine.
31   */   */
# Line 130  void *zeroed_alloc(size_t s) Line 130  void *zeroed_alloc(size_t s)
130                      " environment.\n");                      " environment.\n");
131                  exit(1);                  exit(1);
132  #else  #else
133                  p = malloc(s);                  CHECK_ALLOCATION(p = malloc(s));
                 if (p == NULL) {  
                         fprintf(stderr, "out of memory\n");  
                         exit(1);  
                 }  
134                  memset(p, 0, s);                  memset(p, 0, s);
135  #endif  #endif
136          }          }
# Line 158  struct memory *memory_new(uint64_t physi Line 154  struct memory *memory_new(uint64_t physi
154          int max_bits = MAX_BITS;          int max_bits = MAX_BITS;
155          size_t s;          size_t s;
156    
157          mem = malloc(sizeof(struct memory));          CHECK_ALLOCATION(mem = malloc(sizeof(struct memory)));
         if (mem == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
   
158          memset(mem, 0, sizeof(struct memory));          memset(mem, 0, sizeof(struct memory));
159    
160          /*  Check bits_per_pagetable and bits_per_memblock for sanity:  */          /*  Check bits_per_pagetable and bits_per_memblock for sanity:  */
# Line 183  struct memory *memory_new(uint64_t physi Line 174  struct memory *memory_new(uint64_t physi
174          mem->pagetable = (unsigned char *) mmap(NULL, s,          mem->pagetable = (unsigned char *) mmap(NULL, s,
175              PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);              PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
176          if (mem->pagetable == NULL) {          if (mem->pagetable == NULL) {
177                  mem->pagetable = malloc(s);                  CHECK_ALLOCATION(mem->pagetable = malloc(s));
                 if (mem->pagetable == NULL) {  
                         fprintf(stderr, "out of memory\n");  
                         exit(1);  
                 }  
178                  memset(mem->pagetable, 0, s);                  memset(mem->pagetable, 0, s);
179          }          }
180    
# Line 426  void memory_device_register(struct memor Line 413  void memory_device_register(struct memor
413    
414          mem->n_mmapped_devices++;          mem->n_mmapped_devices++;
415    
416          mem->devices = realloc(mem->devices, sizeof(struct memory_device)          CHECK_ALLOCATION(mem->devices = realloc(mem->devices,
417              * mem->n_mmapped_devices);              sizeof(struct memory_device) * mem->n_mmapped_devices));
         if (mem->devices == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
418    
419          /*  Make space for the new entry:  */          /*  Make space for the new entry:  */
420          if (newi + 1 != mem->n_mmapped_devices)          if (newi + 1 != mem->n_mmapped_devices)
# Line 439  void memory_device_register(struct memor Line 422  void memory_device_register(struct memor
422                      sizeof(struct memory_device)                      sizeof(struct memory_device)
423                      * (mem->n_mmapped_devices - newi - 1));                      * (mem->n_mmapped_devices - newi - 1));
424    
425          mem->devices[newi].name = strdup(device_name);          CHECK_ALLOCATION(mem->devices[newi].name = strdup(device_name));
426          mem->devices[newi].baseaddr = baseaddr;          mem->devices[newi].baseaddr = baseaddr;
427          mem->devices[newi].endaddr = baseaddr + len;          mem->devices[newi].endaddr = baseaddr + len;
428          mem->devices[newi].length = len;          mem->devices[newi].length = len;
429          mem->devices[newi].flags = flags;          mem->devices[newi].flags = flags;
430          mem->devices[newi].dyntrans_data = dyntrans_data;          mem->devices[newi].dyntrans_data = dyntrans_data;
431    
         if (mem->devices[newi].name == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
   
432          if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)          if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
433              && !(flags & DM_EMULATED_RAM) && dyntrans_data == NULL) {              && !(flags & DM_EMULATED_RAM) && dyntrans_data == NULL) {
434                  fatal("\nERROR: Device dyntrans access, but dyntrans_data"                  fatal("\nERROR: Device dyntrans access, but dyntrans_data"
# Line 563  unsigned char *memory_paddr_to_hostaddr( Line 541  unsigned char *memory_paddr_to_hostaddr(
541                  table[entry] = (void *) mmap(NULL, alloclen,                  table[entry] = (void *) mmap(NULL, alloclen,
542                      PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);                      PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
543                  if (table[entry] == NULL) {                  if (table[entry] == NULL) {
544                          table[entry] = malloc(alloclen);                          CHECK_ALLOCATION(table[entry] = malloc(alloclen));
                         if (table[entry] == NULL) {  
                                 fatal("out of memory\n");  
                                 exit(1);  
                         }  
545                          memset(table[entry], 0, alloclen);                          memset(table[entry], 0, alloclen);
546                  }                  }
547          }          }
# Line 680  void memory_warn_about_unimplemented_add Line 654  void memory_warn_about_unimplemented_add
654          }          }
655  }  }
656    
657    
658    /*
659     *  dump_mem_string():
660     *
661     *  Dump the contents of emulated RAM as readable text.  Bytes that aren't
662     *  readable are dumped in [xx] notation, where xx is in hexadecimal.
663     *  Dumping ends after DUMP_MEM_STRING_MAX bytes, or when a terminating
664     *  zero byte is found.
665     */
666    #define DUMP_MEM_STRING_MAX     45
667    void dump_mem_string(struct cpu *cpu, uint64_t addr)
668    {
669            int i;
670            for (i=0; i<DUMP_MEM_STRING_MAX; i++) {
671                    unsigned char ch = '\0';
672    
673                    cpu->memory_rw(cpu, cpu->mem, addr + i, &ch, sizeof(ch),
674                        MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
675                    if (ch == '\0')
676                            return;
677                    if (ch >= ' ' && ch < 126)
678                            debug("%c", ch);  
679                    else
680                            debug("[%02x]", ch);
681            }
682    }
683    
684    
685    /*
686     *  store_byte():
687     *
688     *  Stores a byte in emulated ram. (Helper function.)
689     */
690    void store_byte(struct cpu *cpu, uint64_t addr, uint8_t data)
691    {
692            if ((addr >> 32) == 0)
693                    addr = (int64_t)(int32_t)addr;
694            cpu->memory_rw(cpu, cpu->mem,
695                addr, &data, sizeof(data), MEM_WRITE, CACHE_DATA);
696    }
697    
698    
699    /*
700     *  store_string():
701     *
702     *  Stores chars into emulated RAM until a zero byte (string terminating
703     *  character) is found. The zero byte is also copied.
704     *  (strcpy()-like helper function, host-RAM-to-emulated-RAM.)
705     */
706    void store_string(struct cpu *cpu, uint64_t addr, char *s)
707    {
708            do {
709                    store_byte(cpu, addr++, *s);
710            } while (*s++);
711    }
712    
713    
714    /*
715     *  add_environment_string():
716     *
717     *  Like store_string(), but advances the pointer afterwards. The most
718     *  obvious use is to place a number of strings (such as environment variable
719     *  strings) after one-another in emulated memory.
720     */
721    void add_environment_string(struct cpu *cpu, char *s, uint64_t *addr)
722    {
723            store_string(cpu, *addr, s);
724            (*addr) += strlen(s) + 1;
725    }
726    
727    
728    /*
729     *  add_environment_string_dual():
730     *
731     *  Add "dual" environment strings, one for the variable name and one for the
732     *  value, and update pointers afterwards.
733     */
734    void add_environment_string_dual(struct cpu *cpu,
735            uint64_t *ptrp, uint64_t *addrp, char *s1, char *s2)
736    {
737            uint64_t ptr = *ptrp, addr = *addrp;
738    
739            store_32bit_word(cpu, ptr, addr);
740            ptr += sizeof(uint32_t);
741            if (addr != 0) {
742                    store_string(cpu, addr, s1);
743                    addr += strlen(s1) + 1;
744            }
745            store_32bit_word(cpu, ptr, addr);
746            ptr += sizeof(uint32_t);
747            if (addr != 0) {
748                    store_string(cpu, addr, s2);
749                    addr += strlen(s2) + 1;
750            }
751    
752            *ptrp = ptr;
753            *addrp = addr;
754    }
755    
756    
757    /*
758     *  store_64bit_word():
759     *
760     *  Stores a 64-bit word in emulated RAM.  Byte order is taken into account.
761     *  Helper function.
762     */
763    int store_64bit_word(struct cpu *cpu, uint64_t addr, uint64_t data64)
764    {
765            unsigned char data[8];
766            if ((addr >> 32) == 0)
767                    addr = (int64_t)(int32_t)addr;
768            data[0] = (data64 >> 56) & 255;
769            data[1] = (data64 >> 48) & 255;
770            data[2] = (data64 >> 40) & 255;
771            data[3] = (data64 >> 32) & 255;
772            data[4] = (data64 >> 24) & 255;
773            data[5] = (data64 >> 16) & 255;
774            data[6] = (data64 >> 8) & 255;
775            data[7] = (data64) & 255;
776            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
777                    int tmp = data[0]; data[0] = data[7]; data[7] = tmp;
778                    tmp = data[1]; data[1] = data[6]; data[6] = tmp;
779                    tmp = data[2]; data[2] = data[5]; data[5] = tmp;
780                    tmp = data[3]; data[3] = data[4]; data[4] = tmp;
781            }
782            return cpu->memory_rw(cpu, cpu->mem,
783                addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);
784    }
785    
786    
787    /*
788     *  store_32bit_word():
789     *
790     *  Stores a 32-bit word in emulated RAM.  Byte order is taken into account.
791     *  (This function takes a 64-bit word as argument, to suppress some
792     *  warnings, but only the lowest 32 bits are used.)
793     */
794    int store_32bit_word(struct cpu *cpu, uint64_t addr, uint64_t data32)
795    {
796            unsigned char data[4];
797    
798            data[0] = (data32 >> 24) & 255;
799            data[1] = (data32 >> 16) & 255;
800            data[2] = (data32 >> 8) & 255;
801            data[3] = (data32) & 255;
802            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
803                    int tmp = data[0]; data[0] = data[3]; data[3] = tmp;
804                    tmp = data[1]; data[1] = data[2]; data[2] = tmp;
805            }
806            return cpu->memory_rw(cpu, cpu->mem,
807                addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);
808    }
809    
810    
811    /*
812     *  store_16bit_word():
813     *
814     *  Stores a 16-bit word in emulated RAM.  Byte order is taken into account.
815     *  (This function takes a 64-bit word as argument, to suppress some
816     *  warnings, but only the lowest 16 bits are used.)
817     */
818    int store_16bit_word(struct cpu *cpu, uint64_t addr, uint64_t data16)
819    {
820            unsigned char data[2];
821    
822            data[0] = (data16 >> 8) & 255;
823            data[1] = (data16) & 255;
824            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
825                    int tmp = data[0]; data[0] = data[1]; data[1] = tmp;
826            }
827            return cpu->memory_rw(cpu, cpu->mem,
828                addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);
829    }
830    
831    
832    /*
833     *  store_buf():
834     *
835     *  memcpy()-like helper function, from host RAM to emulated RAM.
836     */
837    void store_buf(struct cpu *cpu, uint64_t addr, char *s, size_t len)
838    {
839            size_t psize = 1024;    /*  1024 256 64 16 4 1  */
840    
841            while (len != 0) {
842                    if ((addr & (psize-1)) == 0) {
843                            while (len >= psize) {
844                                    cpu->memory_rw(cpu, cpu->mem, addr,
845                                        (unsigned char *)s, psize, MEM_WRITE,
846                                        CACHE_DATA);
847                                    addr += psize;
848                                    s += psize;
849                                    len -= psize;
850                            }
851                    }
852                    psize >>= 2;
853            }
854    
855            while (len-- != 0)
856                    store_byte(cpu, addr++, *s++);
857    }
858    
859    
860    /*
861     *  store_pointer_and_advance():
862     *
863     *  Stores a 32-bit or 64-bit pointer in emulated RAM, and advances the
864     *  target address. (Useful for e.g. ARCBIOS environment initialization.)
865     */
866    void store_pointer_and_advance(struct cpu *cpu, uint64_t *addrp,
867            uint64_t data, int flag64)
868    {
869            uint64_t addr = *addrp;
870            if (flag64) {
871                    store_64bit_word(cpu, addr, data);
872                    addr += 8;
873            } else {
874                    store_32bit_word(cpu, addr, data);
875                    addr += 4;
876            }
877            *addrp = addr;
878    }
879    
880    
881    /*
882     *  load_64bit_word():
883     *
884     *  Helper function. Emulated byte order is taken into account.
885     */
886    uint64_t load_64bit_word(struct cpu *cpu, uint64_t addr)
887    {
888            unsigned char data[8];
889    
890            cpu->memory_rw(cpu, cpu->mem,
891                addr, data, sizeof(data), MEM_READ, CACHE_DATA);
892    
893            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
894                    int tmp = data[0]; data[0] = data[7]; data[7] = tmp;
895                    tmp = data[1]; data[1] = data[6]; data[6] = tmp;
896                    tmp = data[2]; data[2] = data[5]; data[5] = tmp;
897                    tmp = data[3]; data[3] = data[4]; data[4] = tmp;
898            }
899    
900            return
901                ((uint64_t)data[0] << 56) + ((uint64_t)data[1] << 48) +
902                ((uint64_t)data[2] << 40) + ((uint64_t)data[3] << 32) +
903                ((uint64_t)data[4] << 24) + ((uint64_t)data[5] << 16) +
904                ((uint64_t)data[6] << 8) + (uint64_t)data[7];
905    }
906    
907    
908    /*
909     *  load_32bit_word():
910     *
911     *  Helper function. Emulated byte order is taken into account.
912     */
913    uint32_t load_32bit_word(struct cpu *cpu, uint64_t addr)
914    {
915            unsigned char data[4];
916    
917            cpu->memory_rw(cpu, cpu->mem,
918                addr, data, sizeof(data), MEM_READ, CACHE_DATA);
919    
920            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
921                    int tmp = data[0]; data[0] = data[3]; data[3] = tmp;
922                    tmp = data[1]; data[1] = data[2]; data[2] = tmp;
923            }
924    
925            return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
926    }
927    
928    
929    /*
930     *  load_16bit_word():
931     *
932     *  Helper function. Emulated byte order is taken into account.
933     */
934    uint16_t load_16bit_word(struct cpu *cpu, uint64_t addr)
935    {
936            unsigned char data[2];
937    
938            cpu->memory_rw(cpu, cpu->mem,
939                addr, data, sizeof(data), MEM_READ, CACHE_DATA);
940    
941            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
942                    int tmp = data[0]; data[0] = data[1]; data[1] = tmp;
943            }
944    
945            return (data[0] << 8) + data[1];
946    }
947    
948    
949    /*
950     *  store_64bit_word_in_host():
951     *
952     *  Stores a 64-bit word in the _host's_ RAM.  Emulated byte order is taken
953     *  into account.  This is useful when building structs in the host's RAM
954     *  which will later be copied into emulated RAM.
955     */
956    void store_64bit_word_in_host(struct cpu *cpu,
957            unsigned char *data, uint64_t data64)
958    {
959            data[0] = (data64 >> 56) & 255;
960            data[1] = (data64 >> 48) & 255;
961            data[2] = (data64 >> 40) & 255;
962            data[3] = (data64 >> 32) & 255;
963            data[4] = (data64 >> 24) & 255;
964            data[5] = (data64 >> 16) & 255;
965            data[6] = (data64 >> 8) & 255;
966            data[7] = (data64) & 255;
967            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
968                    int tmp = data[0]; data[0] = data[7]; data[7] = tmp;
969                    tmp = data[1]; data[1] = data[6]; data[6] = tmp;
970                    tmp = data[2]; data[2] = data[5]; data[5] = tmp;
971                    tmp = data[3]; data[3] = data[4]; data[4] = tmp;
972            }
973    }
974    
975    
976    /*
977     *  store_32bit_word_in_host():
978     *
979     *  See comment for store_64bit_word_in_host().
980     *
981     *  (Note:  The data32 parameter is a uint64_t. This is done to suppress
982     *  some warnings.)
983     */
984    void store_32bit_word_in_host(struct cpu *cpu,
985            unsigned char *data, uint64_t data32)
986    {
987            data[0] = (data32 >> 24) & 255;
988            data[1] = (data32 >> 16) & 255;
989            data[2] = (data32 >> 8) & 255;
990            data[3] = (data32) & 255;
991            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
992                    int tmp = data[0]; data[0] = data[3]; data[3] = tmp;
993                    tmp = data[1]; data[1] = data[2]; data[2] = tmp;
994            }
995    }
996    
997    
998    /*
999     *  store_16bit_word_in_host():
1000     *
1001     *  See comment for store_64bit_word_in_host().
1002     */
1003    void store_16bit_word_in_host(struct cpu *cpu,
1004            unsigned char *data, uint16_t data16)
1005    {
1006            data[0] = (data16 >> 8) & 255;
1007            data[1] = (data16) & 255;
1008            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
1009                    int tmp = data[0]; data[0] = data[1]; data[1] = tmp;
1010            }
1011    }
1012    

Legend:
Removed from v.40  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26