Mercurial > hg > index.cgi
comparison lwasm/output.c @ 432:58cafa61ab40
Add support for undocumented custom module format (for LW)
Nothing to see here. Move along. These are not the droids you are looking
for.
author | William Astle <lost@l-w.ca> |
---|---|
date | Fri, 18 Nov 2016 21:25:43 -0700 |
parents | 9f0448022f1f |
children | 999ae00d0919 |
comparison
equal
deleted
inserted
replaced
431:6df8d62302e2 | 432:58cafa61ab40 |
---|---|
40 void write_code_obj(asmstate_t *as, FILE *of); | 40 void write_code_obj(asmstate_t *as, FILE *of); |
41 void write_code_os9(asmstate_t *as, FILE *of); | 41 void write_code_os9(asmstate_t *as, FILE *of); |
42 void write_code_hex(asmstate_t *as, FILE *of); | 42 void write_code_hex(asmstate_t *as, FILE *of); |
43 void write_code_srec(asmstate_t *as, FILE *of); | 43 void write_code_srec(asmstate_t *as, FILE *of); |
44 void write_code_ihex(asmstate_t *as, FILE *of); | 44 void write_code_ihex(asmstate_t *as, FILE *of); |
45 void write_code_lwmod(asmstate_t *as, FILE *of); | |
45 | 46 |
46 // this prevents warnings about not using the return value of fwrite() | 47 // this prevents warnings about not using the return value of fwrite() |
47 // r++ prevents the "set but not used" warnings; should be optimized out | 48 // r++ prevents the "set but not used" warnings; should be optimized out |
48 #define writebytes(s, l, c, f) do { int r; r = fwrite((s), (l), (c), (f)); r++; } while (0) | 49 #define writebytes(s, l, c, f) do { int r; r = fwrite((s), (l), (c), (f)); r++; } while (0) |
49 | 50 |
99 write_code_srec(as, of); | 100 write_code_srec(as, of); |
100 break; | 101 break; |
101 | 102 |
102 case OUTPUT_IHEX: | 103 case OUTPUT_IHEX: |
103 write_code_ihex(as, of); | 104 write_code_ihex(as, of); |
105 break; | |
106 | |
107 case OUTPUT_LWMOD: | |
108 write_code_lwmod(as, of); | |
104 break; | 109 break; |
105 | 110 |
106 default: | 111 default: |
107 fprintf(stderr, "BUG: unrecognized output format when generating output file\n"); | 112 fprintf(stderr, "BUG: unrecognized output format when generating output file\n"); |
108 fclose(of); | 113 fclose(of); |
998 | 1003 |
999 // flag no more sections | 1004 // flag no more sections |
1000 // the "" is NOT an error | 1005 // the "" is NOT an error |
1001 writebytes("", 1, 1, of); | 1006 writebytes("", 1, 1, of); |
1002 } | 1007 } |
1008 | |
1009 | |
1010 void write_code_lwmod(asmstate_t *as, FILE *of) | |
1011 { | |
1012 line_t *l; | |
1013 sectiontab_t *s; | |
1014 reloctab_t *re; | |
1015 int initsize, bsssize, mainsize, callsnum, namesize; | |
1016 unsigned char *initcode, *maincode, *callscode, *namecode; | |
1017 int relocsize; | |
1018 unsigned char *reloccode; | |
1019 int tsize, bssoff; | |
1020 int initaddr = -1; | |
1021 | |
1022 int i; | |
1023 unsigned char buf[16]; | |
1024 | |
1025 // the magic number | |
1026 buf[0] = 0x8f; | |
1027 buf[1] = 0xcf; | |
1028 | |
1029 // run through the entire system and build the byte streams for each | |
1030 // section; we will make sure we only have simple references for | |
1031 // any undefined references. That means at most an ADD (or SUB) operation | |
1032 // with a single BSS symbol reference and a single constant value. | |
1033 // We will use the constant value in the code stream and record the | |
1034 // offset in a separate code stream for the BSS relocation table. | |
1035 | |
1036 // We build everything in memory here because we need to calculate the | |
1037 // sizes of everything before we can output the complete header. | |
1038 | |
1039 for (l = as -> line_head; l; l = l -> next) | |
1040 { | |
1041 if (l -> csect) | |
1042 { | |
1043 // we're in a section - need to output some bytes | |
1044 if (l -> outputl > 0) | |
1045 for (i = 0; i < l -> outputl; i++) | |
1046 write_code_obj_sbadd(l -> csect, l -> output[i]); | |
1047 else if (l -> outputl == 0 || l -> outputl == -1) | |
1048 for (i = 0; i < l -> len; i++) | |
1049 write_code_obj_sbadd(l -> csect, 0); | |
1050 } | |
1051 } | |
1052 | |
1053 // now run through sections and set various parameters | |
1054 initsize = 0; | |
1055 bsssize = 0; | |
1056 mainsize = 0; | |
1057 callsnum = 0; | |
1058 callscode = NULL; | |
1059 maincode = NULL; | |
1060 initcode = NULL; | |
1061 namecode = NULL; | |
1062 namesize = 0; | |
1063 relocsize = 0; | |
1064 for (s = as -> sections; s; s = s -> next) | |
1065 { | |
1066 if (!strcmp(s -> name, "bss")) | |
1067 { | |
1068 bsssize = s -> oblen; | |
1069 } | |
1070 else if (!strcmp(s -> name, "main")) | |
1071 { | |
1072 maincode = s -> obytes; | |
1073 mainsize = s -> oblen; | |
1074 } | |
1075 else if (!strcmp(s -> name, "init")) | |
1076 { | |
1077 initcode = s -> obytes; | |
1078 initsize = s -> oblen; | |
1079 } | |
1080 else if (!strcmp(s -> name, "calls")) | |
1081 { | |
1082 callscode = s -> obytes; | |
1083 callsnum = s -> oblen / 2; | |
1084 } | |
1085 else if (!strcmp(s -> name, "modname")) | |
1086 { | |
1087 namecode = s -> obytes; | |
1088 namesize = 0; | |
1089 } | |
1090 for (re = s -> reloctab; re; re = re -> next) | |
1091 { | |
1092 if (re -> expr == NULL) | |
1093 relocsize += 2; | |
1094 } | |
1095 } | |
1096 if (namesize == 0) | |
1097 { | |
1098 namecode = (unsigned char *)(as -> output_file); | |
1099 } | |
1100 else | |
1101 { | |
1102 if (namecode[namesize - 1] != '\0') | |
1103 { | |
1104 namecode[namesize - 1] = '\0'; | |
1105 } | |
1106 if (!*namecode) | |
1107 namecode = (unsigned char *)(as -> output_file); | |
1108 } | |
1109 namesize = strlen((char *)namecode); | |
1110 | |
1111 tsize = namesize + 1 + initsize + mainsize + callsnum * 2 + relocsize + 11; | |
1112 bssoff = namesize + 1 + mainsize + callsnum * 2 + 11; | |
1113 // set up section base addresses | |
1114 for (s = as -> sections; s; s = s -> next) | |
1115 { | |
1116 if (!strcmp(s -> name, "main")) | |
1117 { | |
1118 s -> tbase = 11 + namesize + 1 + callsnum * 2; | |
1119 } | |
1120 else if (!strcmp(s -> name, "init")) | |
1121 { | |
1122 s -> tbase = bssoff + relocsize; | |
1123 } | |
1124 else if (!strcmp(s -> name, "calls")) | |
1125 { | |
1126 s -> tbase = 11; | |
1127 } | |
1128 else if (!strcmp(s -> name, "modname")) | |
1129 { | |
1130 s -> tbase = 11 + callsnum * 2; | |
1131 } | |
1132 } | |
1133 | |
1134 // resolve the "init" address | |
1135 if (as -> execaddr_expr) | |
1136 { | |
1137 // need to resolve address with proper section bases | |
1138 lwasm_reduce_expr(as, as -> execaddr_expr); | |
1139 initaddr = lw_expr_intval(as -> execaddr_expr); | |
1140 } | |
1141 else | |
1142 { | |
1143 initaddr = as -> execaddr; | |
1144 } | |
1145 | |
1146 // build relocation data | |
1147 reloccode = NULL; | |
1148 if (relocsize) | |
1149 { | |
1150 unsigned char *tptr; | |
1151 reloccode = lw_alloc(relocsize); | |
1152 tptr = reloccode; | |
1153 | |
1154 for (s = as -> sections; s; s = s -> next) | |
1155 { | |
1156 for (re = s -> reloctab; re; re = re -> next) | |
1157 { | |
1158 lw_expr_t te; | |
1159 line_t tl; | |
1160 int offset; | |
1161 | |
1162 tl.as = as; | |
1163 as -> cl = &tl; | |
1164 as -> csect = s; | |
1165 // as -> exportcheck = 1; | |
1166 | |
1167 if (re -> expr) | |
1168 { | |
1169 int val; | |
1170 int x; | |
1171 | |
1172 te = lw_expr_copy(re -> expr); | |
1173 lwasm_reduce_expr(as, te); | |
1174 if (!lw_expr_istype(te, lw_expr_type_int)) | |
1175 { | |
1176 val = 0; | |
1177 } | |
1178 else | |
1179 { | |
1180 val = lw_expr_intval(te); | |
1181 } | |
1182 lw_expr_destroy(te); | |
1183 x = s -> tbase; | |
1184 s -> tbase = 0; | |
1185 te = lw_expr_copy(re -> offset); | |
1186 lwasm_reduce_expr(as, te); | |
1187 offset = lw_expr_intval(te); | |
1188 lw_expr_destroy(te); | |
1189 s -> tbase = x; | |
1190 // offset *should* be the offset in the section | |
1191 s -> obytes[offset] = val >> 8; | |
1192 s -> obytes[offset + 1] = val & 0xff; | |
1193 continue; | |
1194 } | |
1195 | |
1196 offset = 0; | |
1197 te = lw_expr_copy(re -> offset); | |
1198 lwasm_reduce_expr(as, te); | |
1199 if (!lw_expr_istype(te, lw_expr_type_int)) | |
1200 { | |
1201 lw_expr_destroy(te); | |
1202 offset = 0; | |
1203 continue; | |
1204 } | |
1205 offset = lw_expr_intval(te); | |
1206 lw_expr_destroy(te); | |
1207 //offset += sbase; | |
1208 | |
1209 *tptr++ = offset >> 8; | |
1210 *tptr++ = offset & 0xff; | |
1211 } | |
1212 } | |
1213 } | |
1214 | |
1215 // total size | |
1216 buf[2] = tsize >> 8; | |
1217 buf[3] = tsize & 0xff; | |
1218 // offset to BSS relocs | |
1219 buf[4] = bssoff >> 8; | |
1220 buf[5] = bssoff & 0xff; | |
1221 // BSS size | |
1222 buf[6] = bsssize >> 8; | |
1223 buf[7] = bsssize & 0xff; | |
1224 // init routine offset | |
1225 buf[8] = initaddr >> 8; | |
1226 buf[9] = initaddr & 0xff; | |
1227 // number of call entries | |
1228 buf[10] = callsnum; | |
1229 // write the header | |
1230 writebytes(buf, 11, 1, of); | |
1231 // call data | |
1232 if (callsnum) | |
1233 writebytes(callscode, callsnum * 2, 1, of); | |
1234 // module name | |
1235 writebytes(namecode, namesize + 1, 1, of); | |
1236 // main code | |
1237 if (mainsize) | |
1238 writebytes(maincode, mainsize, 1, of); | |
1239 // bss relocs | |
1240 if (relocsize) | |
1241 writebytes(reloccode, relocsize, 1, of); | |
1242 // init stuff | |
1243 if (initsize) | |
1244 writebytes(initcode, initsize, 1, of); | |
1245 } |